diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index de5b2ea6c0439405f9099eb7373e1b3b4e6d1aa9..92b072b4dd3c5b455c939d614b2404172b47e3e5 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3542,7 +3542,7 @@ thingtypes } 124 { - title = "AquaBuzz"; + title = "Buggle"; sprite = "BBUZA1"; width = 20; height = 24; @@ -5673,8 +5673,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle"; - sprite = "GARGA1"; + title = "Glaregoyle"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5684,8 +5684,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Up)"; - sprite = "GARGA1"; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5695,8 +5695,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Down)"; - sprite = "GARGA1"; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5706,8 +5706,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Long)"; - sprite = "GARGA1"; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 71f44624ecdeac17e0eddf7955cf1791b9a7408c..97feae18bbda248b274a9e3c0b1797b97260b790 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -425,7 +425,11 @@ if(${SRB2_CONFIG_HWRENDER}) ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c ) set (SRB2_HWRENDER_HEADERS @@ -439,6 +443,10 @@ if(${SRB2_CONFIG_HWRENDER}) ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h ) set(SRB2_R_OPENGL_SOURCES diff --git a/src/Makefile b/src/Makefile index f2f3b305d3bb6fdeee683873ddbc5a9ee3d0bc54..7c9ce8fd26614775c64d391591ca88f0c225cb8c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -226,7 +226,8 @@ else #OPTS+=-DUSE_PALETTED_TEXTURE OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ - $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o + $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o endif ifdef NOHS @@ -647,16 +648,18 @@ ifdef MINGW $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \ - d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ + hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ + am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ else $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \ - d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ + hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ + am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ endif @@ -734,16 +737,18 @@ ifndef NOHW $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \ - d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ + hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ + am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \ - d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ + hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ + am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ endif diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 411d847b54e90d5b310d1e340f02d403c527b919..8d6de765470f15b9c2c1c2029b2ea758347e46bd 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2491,7 +2491,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) void CL_Reset(void) { if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); if (metalplayback) G_StopMetalDemo(); if (demorecording) @@ -4708,7 +4708,12 @@ void TryRunTics(tic_t realtics) if (neededtic > gametic && !resynch_local_inprogress) { if (advancedemo) - D_StartTitle(); + { + if (timedemo_quit) + COM_ImmedExecute("quit"); + else + D_StartTitle(); + } else // run the count * tics while (neededtic > gametic) diff --git a/src/d_main.c b/src/d_main.c index ca40fcb24783aece322647b61d619e2da06beeb2..0a13c6d0b0108bc83acbfc1501e40c92305eaaa4 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -291,11 +291,8 @@ static void D_Display(void) switch (gamestate) { case GS_TITLESCREEN: - if (!titlemapinaction || !curbghide) { - F_TitleScreenDrawer(); - break; - } - /* FALLTHRU */ + F_TitleScreenDrawer(); + break; case GS_LEVEL: if (!gametic) break; @@ -366,56 +363,11 @@ static void D_Display(void) // clean up border stuff // see if the border needs to be initially drawn - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap))) + if (gamestate == GS_LEVEL) { // draw the view directly - if (!automapactive && !dedicated && cv_renderview.value) - { - if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) - { - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - objectsdrawn = 0; - #ifdef HWRENDER - if (rendermode != render_soft) - HWR_RenderPlayerView(0, &players[displayplayer]); - else - #endif - if (rendermode != render_none) - R_RenderPlayerView(&players[displayplayer]); - } - - // render the second screen - if (splitscreen && players[secondarydisplayplayer].mo) - { - #ifdef HWRENDER - if (rendermode != render_soft) - HWR_RenderPlayerView(1, &players[secondarydisplayplayer]); - else - #endif - if (rendermode != render_none) - { - viewwindowy = vid.height / 2; - M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); - - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - - R_RenderPlayerView(&players[secondarydisplayplayer]); - - viewwindowy = 0; - M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); - } - } - - // Image postprocessing effect - if (rendermode == render_soft) - { - if (postimgtype) - V_DoPostProcessor(0, postimgtype, postimgparam); - if (postimgtype2) - V_DoPostProcessor(1, postimgtype2, postimgparam2); - } - } + D_Render(); if (lastdraw) { @@ -428,14 +380,9 @@ static void D_Display(void) lastdraw = false; } - if (gamestate == GS_LEVEL) - { - ST_Drawer(); - F_TextPromptDrawer(); - HU_Drawer(); - } - else - F_TitleScreenDrawer(); + ST_Drawer(); + F_TextPromptDrawer(); + HU_Drawer(); } } @@ -491,6 +438,13 @@ static void D_Display(void) F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN); } + // reset counters so timedemo doesn't count the wipe duration + if (timingdemo) + { + framecount = 0; + demostarttime = I_GetTime(); + } + wipetypepost = -1; } else @@ -531,6 +485,56 @@ static void D_Display(void) } } +void D_Render(void) +{ + if (!automapactive && !dedicated && cv_renderview.value) + { + if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) + { + topleft = screens[0] + viewwindowy*vid.width + viewwindowx; + objectsdrawn = 0; +#ifdef HWRENDER + if (rendermode != render_soft) + HWR_RenderPlayerView(0, &players[displayplayer]); + else +#endif + if (rendermode != render_none) + R_RenderPlayerView(&players[displayplayer]); + } + + // render the second screen + if (splitscreen && players[secondarydisplayplayer].mo) + { +#ifdef HWRENDER + if (rendermode != render_soft) + HWR_RenderPlayerView(1, &players[secondarydisplayplayer]); + else +#endif + if (rendermode != render_none) + { + viewwindowy = vid.height / 2; + M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); + + topleft = screens[0] + viewwindowy*vid.width + viewwindowx; + + R_RenderPlayerView(&players[secondarydisplayplayer]); + + viewwindowy = 0; + M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); + } + } + + // Image postprocessing effect + if (rendermode == render_soft) + { + if (postimgtype) + V_DoPostProcessor(0, postimgtype, postimgparam); + if (postimgtype2) + V_DoPostProcessor(1, postimgtype2, postimgparam2); + } + } +} + // ========================================================================= // D_SRB2Loop // ========================================================================= @@ -544,9 +548,6 @@ void D_SRB2Loop(void) if (dedicated) server = true; - if (M_CheckParm("-voodoo")) // 256x256 Texture Limiter - COM_BufAddText("gr_voodoocompatibility on\n"); - // Pushing of + parameters is now done back in D_SRB2Main, not here. CONS_Printf("I_StartupKeyboard()...\n"); diff --git a/src/d_main.h b/src/d_main.h index d67a5bb498ba0f45d37b2be8c6bd15fde96cc78a..65c51802a7c644c871b862ef0ff28182204d0d6b 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -54,4 +54,7 @@ const char *D_Home(void); void D_AdvanceDemo(void); void D_StartTitle(void); +/* Here for title maps */ +void D_Render(void); + #endif //__D_MAIN__ diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b14f92b33bae700dbbbb79a5b526c2110129ad23..62c505ee0b726569f63ae6e3a0ec10a8c6b69aa8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -365,6 +365,11 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; +char timedemo_name[256]; +boolean timedemo_csv; +char timedemo_csv_id[256]; +boolean timedemo_quit; + INT16 gametype = GT_COOP; boolean splitscreen = false; boolean circuitmap = false; @@ -1206,9 +1211,9 @@ static void SendNameAndColor(void) players[consoleplayer].mo->color = players[consoleplayer].skincolor; if (metalrecording) - { // Metal Sonic is Sonic, obviously. - SetPlayerSkinByNum(consoleplayer, 0); - CV_StealthSet(&cv_skin, skins[0].name); + { // Starring Metal Sonic as themselves, obviously. + SetPlayerSkinByNum(consoleplayer, 5); + CV_StealthSet(&cv_skin, skins[5].name); } else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { @@ -1569,11 +1574,11 @@ static void Command_Playdemo_f(void) static void Command_Timedemo_f(void) { - char name[256]; + size_t i = 0; - if (COM_Argc() != 2) + if (COM_Argc() < 2) { - CONS_Printf(M_GetText("timedemo <demoname>: time a demo\n")); + CONS_Printf(M_GetText("timedemo <demoname> [-csv [<trialid>]] [-quit]: time a demo\n")); return; } @@ -1590,12 +1595,23 @@ static void Command_Timedemo_f(void) G_StopMetalDemo(); // open the demo file - strcpy (name, COM_Argv(1)); + strcpy (timedemo_name, COM_Argv(1)); // dont add .lmp so internal game demos can be played - CONS_Printf(M_GetText("Timing demo '%s'.\n"), name); + // print timedemo results as CSV? + i = COM_CheckParm("-csv"); + timedemo_csv = (i > 0); + if (COM_CheckParm("-quit") != i + 1) + strcpy(timedemo_csv_id, COM_Argv(i + 1)); // user-defined string to identify row + else + timedemo_csv_id[0] = 0; - G_TimeDemo(name); + // exit after the timedemo? + timedemo_quit = (COM_CheckParm("-quit") > 0); + + CONS_Printf(M_GetText("Timing demo '%s'.\n"), timedemo_name); + + G_TimeDemo(timedemo_name); } // stop current demo @@ -1646,7 +1662,31 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese // The supplied data are assumed to be good. I_Assert(delay >= 0 && delay <= 2); if (mapnum != -1) + { CV_SetValue(&cv_nextmap, mapnum); + // Kick bot from special stages + if (botskin) + { + if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS))) + { + if (botingame) + { + //CL_RemoveSplitscreenPlayer(); + botingame = false; + playeringame[1] = false; + } + } + else if (!botingame) + { + //CL_AddSplitscreenPlayer(); + botingame = true; + secondarydisplayplayer = 1; + playeringame[1] = true; + players[1].bot = 1; + SendNameAndColor2(); + } + } + } CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene); if ((netgame || multiplayer) && !((gametype == newgametype) && (newgametype == GT_COOP))) @@ -1689,29 +1729,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese return; } - // Kick bot from special stages - if (botskin) - { - if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS))) - { - if (botingame) - { - //CL_RemoveSplitscreenPlayer(); - botingame = false; - playeringame[1] = false; - } - } - else if (!botingame) - { - //CL_AddSplitscreenPlayer(); - botingame = true; - secondarydisplayplayer = 1; - playeringame[1] = true; - players[1].bot = 1; - SendNameAndColor2(); - } - } - chmappending++; if (netgame) WRITEUINT32(buf_p, M_RandomizedSeed()); // random seed diff --git a/src/d_netcmd.h b/src/d_netcmd.h index e789e5b50f467d8dceec697ab841adcf851e0bf4..0b538890ec569dc8a2062889dc9842c502b89af3 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -113,6 +113,11 @@ extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; +extern char timedemo_name[256]; +extern boolean timedemo_csv; +extern char timedemo_csv_id[256]; +extern boolean timedemo_quit; + typedef enum { XD_NAMEANDCOLOR = 1, diff --git a/src/dehacked.c b/src/dehacked.c index 2f89fb675073053cc3461fbd1271203006646cfb..5bcb64073cec9239df8d58f3e98c3c871ae2678b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5583,25 +5583,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CYBRAKDEMONVILEEXPLOSION3", // Metal Sonic (Race) - // S_PLAY_STND - "S_METALSONIC_STAND", - // S_PLAY_TAP1 - "S_METALSONIC_WAIT1", - "S_METALSONIC_WAIT2", - // S_PLAY_WALK - "S_METALSONIC_WALK1", - "S_METALSONIC_WALK2", - "S_METALSONIC_WALK3", - "S_METALSONIC_WALK4", - "S_METALSONIC_WALK5", - "S_METALSONIC_WALK6", - "S_METALSONIC_WALK7", - "S_METALSONIC_WALK8", - // S_PLAY_SPD1 - "S_METALSONIC_RUN1", - "S_METALSONIC_RUN2", - "S_METALSONIC_RUN3", - "S_METALSONIC_RUN4", + "S_METALSONIC_RACE", // Metal Sonic (Battle) "S_METALSONIC_FLOAT", "S_METALSONIC_VECTOR", @@ -5944,7 +5926,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ARROW", "S_ARROWBONK", - // Trapgoyle Demon fire + // Glaregoyle Demon fire "S_DEMONFIRE", // GFZ flowers @@ -6312,29 +6294,35 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WALLVINE_LONG", "S_WALLVINE_SHORT", - // Trapgoyles - "S_TRAPGOYLE", - "S_TRAPGOYLE_CHECK", - "S_TRAPGOYLE_FIRE1", - "S_TRAPGOYLE_FIRE2", - "S_TRAPGOYLE_FIRE3", - "S_TRAPGOYLEUP", - "S_TRAPGOYLEUP_CHECK", - "S_TRAPGOYLEUP_FIRE1", - "S_TRAPGOYLEUP_FIRE2", - "S_TRAPGOYLEUP_FIRE3", - "S_TRAPGOYLEDOWN", - "S_TRAPGOYLEDOWN_CHECK", - "S_TRAPGOYLEDOWN_FIRE1", - "S_TRAPGOYLEDOWN_FIRE2", - "S_TRAPGOYLEDOWN_FIRE3", - "S_TRAPGOYLELONG", - "S_TRAPGOYLELONG_CHECK", - "S_TRAPGOYLELONG_FIRE1", - "S_TRAPGOYLELONG_FIRE2", - "S_TRAPGOYLELONG_FIRE3", - "S_TRAPGOYLELONG_FIRE4", - "S_TRAPGOYLELONG_FIRE5", + // Glaregoyles + "S_GLAREGOYLE", + "S_GLAREGOYLE_CHARGE", + "S_GLAREGOYLE_BLINK", + "S_GLAREGOYLE_HOLD", + "S_GLAREGOYLE_FIRE", + "S_GLAREGOYLE_LOOP", + "S_GLAREGOYLE_COOLDOWN", + "S_GLAREGOYLEUP", + "S_GLAREGOYLEUP_CHARGE", + "S_GLAREGOYLEUP_BLINK", + "S_GLAREGOYLEUP_HOLD", + "S_GLAREGOYLEUP_FIRE", + "S_GLAREGOYLEUP_LOOP", + "S_GLAREGOYLEUP_COOLDOWN", + "S_GLAREGOYLEDOWN", + "S_GLAREGOYLEDOWN_CHARGE", + "S_GLAREGOYLEDOWN_BLINK", + "S_GLAREGOYLEDOWN_HOLD", + "S_GLAREGOYLEDOWN_FIRE", + "S_GLAREGOYLEDOWN_LOOP", + "S_GLAREGOYLEDOWN_COOLDOWN", + "S_GLAREGOYLELONG", + "S_GLAREGOYLELONG_CHARGE", + "S_GLAREGOYLELONG_BLINK", + "S_GLAREGOYLELONG_HOLD", + "S_GLAREGOYLELONG_FIRE", + "S_GLAREGOYLELONG_LOOP", + "S_GLAREGOYLELONG_COOLDOWN", // ATZ's Red Crystal/Target "S_TARGET_IDLE", @@ -6346,6 +6334,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // ATZ's green flame "S_GREENFLAME", + // ATZ Blue Gargoyle + "S_BLUEGARGOYLE", + // Stalagmites "S_STG0", "S_STG1", @@ -7535,8 +7526,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BUMBLEBORE_STUCK2", "S_BUMBLEBORE_DIE", - "S_BBUZZFLY1", - "S_BBUZZFLY2", + "S_BUGGLEIDLE", + "S_BUGGLEFLY", "S_SMASHSPIKE_FLOAT", "S_SMASHSPIKE_EASE1", @@ -7932,7 +7923,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CANNONBALL", // Cannonball "MT_CANNONBALLDECOR", // Decorative/still cannonball "MT_ARROW", // Arrow - "MT_DEMONFIRE", // Trapgoyle fire + "MT_DEMONFIRE", // Glaregoyle fire // Greenflower Scenery "MT_GFZFLOWER1", @@ -8095,12 +8086,13 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Egg Rock Scenery // Azure Temple Scenery - "MT_TRAPGOYLE", - "MT_TRAPGOYLEUP", - "MT_TRAPGOYLEDOWN", - "MT_TRAPGOYLELONG", + "MT_GLAREGOYLE", + "MT_GLAREGOYLEUP", + "MT_GLAREGOYLEDOWN", + "MT_GLAREGOYLELONG", "MT_TARGET", "MT_GREENFLAME", + "MT_BLUEGARGOYLE", // Stalagmites "MT_STALAGMITE0", @@ -8375,7 +8367,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_HIVEELEMENTAL", "MT_BUMBLEBORE", - "MT_BUBBLEBUZZ", + "MT_BUGGLE", "MT_SMASHINGSPIKEBALL", "MT_CACOLANTERN", diff --git a/src/doomtype.h b/src/doomtype.h index 7acdde966835b97f6977214e8925729bdbe14108..5f60e21b51cc6aec62c1a3427a897c47d649816d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -326,16 +326,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz); /* Miscellaneous types that don't fit anywhere else (Can this be changed?) */ +typedef struct +{ + UINT8 red; + UINT8 green; + UINT8 blue; + UINT8 alpha; +} byteColor_t; + union FColorRGBA { UINT32 rgba; - struct - { - UINT8 red; - UINT8 green; - UINT8 blue; - UINT8 alpha; - } s; + byteColor_t s; } ATTRPACK; typedef union FColorRGBA RGBA_t; diff --git a/src/f_finale.c b/src/f_finale.c index 635e5f99e745b0b20561038b535570c881e73883..764825e6fc2c38db5f1301bcd1fa3ec650b52d58 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2580,7 +2580,9 @@ void F_TitleScreenDrawer(void) // Draw that sky! if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); - else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) + else if (titlemapinaction && curbghide && ! hidetitlemap) + D_Render(); + else F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); // Don't draw outside of the title screen, or if the patch isn't there. @@ -3312,10 +3314,6 @@ void F_TitleScreenTicker(boolean run) if (run) finalecount++; - // don't trigger if doing anything besides idling on title - if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN) - return; - // Execute the titlemap camera settings if (titlemapinaction) { @@ -3362,6 +3360,10 @@ void F_TitleScreenTicker(boolean run) } } + // don't trigger if doing anything besides idling on title + if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN) + return; + // no demos to play? or, are they disabled? if (!cv_rollingdemos.value || !numDemos) return; diff --git a/src/g_game.c b/src/g_game.c index ceab3a465d4ff48f1de7714badf0634b47fde439..18d0cdfe849027a034deae84f95c760294534e70 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -104,7 +104,7 @@ UINT32 demoIdleTime = 3*TICRATE; boolean timingdemo; // if true, exit with report on completion boolean nodrawers; // for comparative timing purposes boolean noblit; // for comparative timing purposes -static tic_t demostarttime; // for comparative timing purposes +tic_t demostarttime; // for comparative timing purposes boolean netgame; // only true if packets are broadcast boolean multiplayer; @@ -289,7 +289,7 @@ static struct { // There is no conflict here. typedef struct demoghost { UINT8 checksum[16]; - UINT8 *buffer, *p, color; + UINT8 *buffer, *p, color, fadein; UINT16 version; mobj_t oldmo, *mo; struct demoghost *next; @@ -2755,6 +2755,8 @@ void G_DoReborn(INT32 playernum) LUAh_MapChange(gamemap); #endif G_DoLoadLevel(true); + if (metalrecording) + G_BeginMetal(); return; } } @@ -2922,7 +2924,7 @@ boolean G_GametypeUsesLives(void) { // Coop, Competitive if ((gametype == GT_COOP || gametype == GT_COMPETITION) - && !modeattacking // No lives in Time Attack + && !(modeattacking || metalrecording) // No lives in Time Attack //&& !G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)) // No lives in NiGHTS return true; @@ -3053,7 +3055,7 @@ static void G_DoCompleted(void) if (metalplayback) G_StopMetalDemo(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -4049,7 +4051,7 @@ char *G_BuildMapTitle(INT32 mapnum) // DEMO RECORDING // -#define DEMOVERSION 0x000a +#define DEMOVERSION 0x000c #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -4065,6 +4067,8 @@ char *G_BuildMapTitle(INT32 mapnum) #define ZT_BUTTONS 0x08 #define ZT_AIMING 0x10 #define DEMOMARKER 0x80 // demoend +#define METALDEATH 0x44 +#define METALSNICE 0x69 static ticcmd_t oldcmd; @@ -4073,7 +4077,6 @@ static ticcmd_t oldcmd; #define GZT_MOMXY 0x02 #define GZT_MOMZ 0x04 #define GZT_ANGLE 0x08 -// Not used for Metal Sonic #define GZT_FRAME 0x10 // Animation frame #define GZT_SPR2 0x20 // Player animations #define GZT_EXTRA 0x40 @@ -4089,7 +4092,15 @@ static ticcmd_t oldcmd; #define EZT_SCALE 0x10 // Changed size #define EZT_HIT 0x20 // Damaged a mobj #define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) -// spare EZT slot 0x80 +#define EZT_HEIGHT 0x80 // Changed height + +// GZT_FOLLOW flags +#define FZT_SPAWNED 0x01 // just been spawned +#define FZT_SKIN 0x02 // has skin +#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only) +#define FZT_COLORIZED 0x08 // colorized (ditto) +#define FZT_SCALE 0x10 // different scale to object +// spare FZT slots 0x20 to 0x80 static mobj_t oldmetal, oldghost; @@ -4215,28 +4226,28 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) void G_GhostAddThok(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK; } void G_GhostAddSpin(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN; } void G_GhostAddRev(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV; } void G_GhostAddFlip(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags |= EZT_FLIP; } @@ -4256,7 +4267,7 @@ void G_GhostAddColor(ghostcolor_t color) void G_GhostAddScale(fixed_t scale) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; if (ghostext.lastscale == scale) { @@ -4282,6 +4293,7 @@ void G_WriteGhostTic(mobj_t *ghost) char ziptic = 0; UINT8 *ziptic_p; UINT32 i; + fixed_t height; if (!demo_p) return; @@ -4371,6 +4383,12 @@ void G_WriteGhostTic(mobj_t *ghost) ghostext.flags |= EZT_SPRITE; } + if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height) + { + oldghost.height = height; + ghostext.flags |= EZT_HEIGHT; + } + if (ghostext.flags) { ziptic |= GZT_EXTRA; @@ -4410,26 +4428,60 @@ void G_WriteGhostTic(mobj_t *ghost) ghostext.hitlist = NULL; } if (ghostext.flags & EZT_SPRITE) - WRITEUINT8(demo_p,oldghost.sprite); + WRITEUINT16(demo_p,oldghost.sprite); + if (ghostext.flags & EZT_HEIGHT) + { + height >>= FRACBITS; + WRITEINT16(demo_p, height); + } ghostext.flags = 0; } - if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do + if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do { INT16 temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; ziptic |= GZT_FOLLOW; + if (ghost->player->followmobj->skin) + followtic |= FZT_SKIN; + + if (!(oldghost.flags2 & MF2_AMBUSH)) + { + followtic |= FZT_SPAWNED; + WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS); + if (ghost->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; + if (ghost->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins)); + oldghost.flags2 |= MF2_AMBUSH; + } + temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8); WRITEINT16(demo_p,temp); - WRITEUINT8(demo_p,ghost->player->followmobj->sprite); - WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + WRITEUINT16(demo_p,ghost->player->followmobj->sprite); WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); + WRITEUINT8(demo_p,ghost->player->followmobj->color); + if (ghost->player->followmobj->scale != ghost->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,ghost->player->followmobj->scale); + } + + *followtic_p = followtic; } + else + oldghost.flags2 &= ~MF2_AMBUSH; *ziptic_p = ziptic; @@ -4533,15 +4585,28 @@ void G_ConsGhostTic(void) } } if (xziptic & EZT_SPRITE) - demo_p++; + demo_p += sizeof(UINT16); + if (xziptic & EZT_HEIGHT) + demo_p += sizeof(INT16); } if (ziptic & GZT_FOLLOW) { // Even more... + UINT8 followtic = READUINT8(demo_p); + if (followtic & FZT_SPAWNED) + { + demo_p += sizeof(INT16); + if (followtic & FZT_SKIN) + demo_p++; + } + if (followtic & FZT_SCALE) + demo_p += sizeof(fixed_t); demo_p += sizeof(INT16); demo_p += sizeof(INT16); demo_p += sizeof(INT16); - demo_p++; + if (followtic & FZT_SKIN) + demo_p++; + demo_p += sizeof(UINT16); demo_p++; demo_p++; } @@ -4629,6 +4694,11 @@ void G_GhostTicker(void) g->mo->z = g->oldmo.z; P_SetThingPosition(g->mo); g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT; + if (g->fadein) + { + g->mo->frame += (((--g->fadein)/6)<<FF_TRANSSHIFT); // this calc never exceeds 9 unless g->fadein is bad, and it's only set once, so... + g->mo->flags2 &= ~MF2_DONTDRAW; + } g->mo->sprite2 = g->oldmo.sprite2; if (ziptic & GZT_EXTRA) @@ -4686,33 +4756,38 @@ void G_GhostTicker(void) break; } } - if (type == MT_GHOST) - { - mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60 - } - else + if (type != MT_NULL) { - mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); - mobj->sprite = states[mobjinfo[type].spawnstate].sprite; - mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT; - mobj->tics = -1; // nope. - mobj->color = g->mo->color; - if (g->mo->eflags & MFE_VERTICALFLIP) + if (type == MT_GHOST) + { + mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60 + } + else { - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= MFE_VERTICALFLIP; + mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); + mobj->sprite = states[mobjinfo[type].spawnstate].sprite; + mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT; + mobj->color = g->mo->color; + mobj->skin = g->mo->skin; + P_SetScale(mobj, (mobj->destscale = g->mo->scale)); + + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS80; + mobj->fuse = mobj->tics; + } + mobj->tics = -1; // nope. } - P_SetScale(mobj, g->mo->scale); - mobj->destscale = g->mo->scale; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_UnsetThingPosition(mobj); + mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + P_SetThingPosition(mobj); + if (!mobj->fuse) + mobj->fuse = 8; + P_SetTarget(&mobj->target, g->mo); } - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_UnsetThingPosition(mobj); - mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... - P_SetThingPosition(mobj); - mobj->fuse = 8; - P_SetTarget(&mobj->target, g->mo); } if (xziptic & EZT_HIT) { // Spawn hit poofs for killing things! @@ -4742,7 +4817,12 @@ void G_GhostTicker(void) } } if (xziptic & EZT_SPRITE) - g->mo->sprite = READUINT8(g->p); + g->mo->sprite = READUINT16(g->p); + if (xziptic & EZT_HEIGHT) + { + fixed_t temp = READINT16(g->p)<<FRACBITS; + g->mo->height = FixedMul(temp, g->mo->scale); + } } // Tick ghost colors (Super and Mario Invincibility flashing) @@ -4768,55 +4848,81 @@ void G_GhostTicker(void) #define follow g->mo->tracer if (ziptic & GZT_FOLLOW) { // Even more... - if (!follow) + UINT8 followtic = READUINT8(g->p); + fixed_t temp; + if (followtic & FZT_SPAWNED) { - mobj_t *newmo = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST); - P_SetTarget(&g->mo->tracer, newmo); - P_SetTarget(&newmo->tracer, g->mo); - newmo->skin = g->mo->skin; - newmo->tics = -1; - newmo->flags2 |= MF2_LINKDRAW; - - follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP); - follow->destscale = g->mo->destscale; - if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST)); + P_SetTarget(&follow->tracer, g->mo); + follow->tics = -1; + temp = READINT16(g->p)<<FRACBITS; + follow->height = FixedMul(follow->scale, temp); + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; + + if (followtic & FZT_COLORIZED) + follow->colorized = true; + + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(g->p)]; } - else + if (follow) { - if (xziptic & EZT_FLIP) - g->mo->eflags ^= MFE_VERTICALFLIP; - if (xziptic & EZT_SCALE) - { + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(g->p); + else follow->destscale = g->mo->destscale; - if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); + + P_UnsetThingPosition(follow); + temp = READINT16(g->p)<<8; + follow->x = g->mo->x + temp; + temp = READINT16(g->p)<<8; + follow->y = g->mo->y + temp; + temp = READINT16(g->p)<<8; + follow->z = g->mo->z + temp; + P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(g->p); + else + follow->sprite2 = 0; + follow->sprite = READUINT16(g->p); + follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK); + follow->angle = g->mo->angle; + follow->color = READUINT8(g->p); + + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } } } - - P_UnsetThingPosition(follow); - follow->x = g->mo->x + (READINT16(g->p)<<8); - follow->y = g->mo->y + (READINT16(g->p)<<8); - follow->z = g->mo->z + (READINT16(g->p)<<8); - P_SetThingPosition(follow); - follow->sprite = READUINT8(g->p); - follow->sprite2 = READUINT8(g->p); - follow->frame = (READUINT8(g->p)) | tr_trans30<<FF_TRANSSHIFT; - - follow->angle = g->mo->angle; - follow->color = g->mo->color; } else if (follow) { P_RemoveMobj(follow); P_SetTarget(&follow, NULL); } -#undef follow - // Demo ends after ghost data. if (*g->p == DEMOMARKER) { g->mo->momx = g->mo->momy = g->mo->momz = 0; +#if 1 // freeze frame (maybe more useful for time attackers) + g->mo->colorized = true; + if (follow) + follow->colorized = true; +#else // dissapearing act + g->mo->fuse = TICRATE; + if (follow) + follow->fuse = TICRATE; +#endif if (p) p->next = g->next; else @@ -4825,17 +4931,41 @@ void G_GhostTicker(void) continue; } p = g; +#undef follow } } void G_ReadMetalTic(mobj_t *metal) { UINT8 ziptic; - UINT16 speed; - UINT8 statetype; + UINT8 xziptic = 0; if (!metal_p) return; + + if (!metal->health) + { + G_StopMetalDemo(); + return; + } + + switch (*metal_p) + { + case METALSNICE: + break; + case METALDEATH: + if (metal->tracer) + P_RemoveMobj(metal->tracer); + P_KillMobj(metal, NULL, NULL, 0); + /* FALLTHRU */ + case DEMOMARKER: + default: + // end of demo data stream + G_StopMetalDemo(); + return; + } + metal_p++; + ziptic = READUINT8(metal_p); // Read changes from the tic @@ -4862,9 +4992,9 @@ void G_ReadMetalTic(mobj_t *metal) if (ziptic & GZT_ANGLE) metal->angle = READUINT8(metal_p)<<24; if (ziptic & GZT_FRAME) - metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.) + oldmetal.frame = READUINT32(metal_p); if (ziptic & GZT_SPR2) - metal_p++; + oldmetal.sprite2 = READUINT8(metal_p); // Set movement, position, and angle // oldmetal contains where you're supposed to be. @@ -4876,67 +5006,160 @@ void G_ReadMetalTic(mobj_t *metal) metal->y = oldmetal.y; metal->z = oldmetal.z; P_SetThingPosition(metal); + metal->frame = oldmetal.frame; + metal->sprite2 = oldmetal.sprite2; if (ziptic & GZT_EXTRA) { // But wait, there's more! - ziptic = READUINT8(metal_p); - if (ziptic & EZT_FLIP) + xziptic = READUINT8(metal_p); + if (xziptic & EZT_FLIP) metal->eflags ^= MFE_VERTICALFLIP; - if (ziptic & EZT_SCALE) + if (xziptic & EZT_SCALE) { metal->destscale = READFIXED(metal_p); if (metal->destscale != metal->scale) P_SetScale(metal, metal->destscale); } - } - - // Calculates player's speed based on distance-of-a-line formula - speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS; - - // Use speed to decide an appropriate state - if (speed > 28) // default skin runspeed - statetype = 2; - else if (speed > 1) // stopspeed - statetype = 1; - else - statetype = 0; + if (xziptic & EZT_THOKMASK) + { // Let's only spawn ONE of these per frame, thanks. + mobj_t *mobj; + INT32 type = -1; + if (metal->skin) + { + skin_t *skin = (skin_t *)metal->skin; + switch (xziptic & EZT_THOKMASK) + { + case EZT_THOK: + type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; + break; + case EZT_SPIN: + type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; + break; + case EZT_REV: + type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + break; + } + } + if (type != MT_NULL) + { + if (type == MT_GHOST) + { + mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us + } + else + { + mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK); + mobj->sprite = states[mobjinfo[type].spawnstate].sprite; + mobj->frame = states[mobjinfo[type].spawnstate].frame; + mobj->angle = metal->angle; + mobj->color = metal->color; + mobj->skin = metal->skin; + P_SetScale(mobj, (mobj->destscale = metal->scale)); - // Set state - if (statetype != metal->threshold) - { - switch (statetype) + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS70; + mobj->fuse = mobj->tics; + } + mobj->tics = -1; // nope. + } + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_UnsetThingPosition(mobj); + mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + P_SetThingPosition(mobj); + if (!mobj->fuse) + mobj->fuse = 8; + P_SetTarget(&mobj->target, metal); + } + } + if (xziptic & EZT_SPRITE) + metal->sprite = READUINT16(metal_p); + if (xziptic & EZT_HEIGHT) { - case 2: // run - P_SetMobjState(metal,metal->info->meleestate); - break; - case 1: // walk - P_SetMobjState(metal,metal->info->seestate); - break; - default: // stand - P_SetMobjState(metal,metal->info->spawnstate); - break; + fixed_t temp = READINT16(metal_p)<<FRACBITS; + metal->height = FixedMul(temp, metal->scale); } - metal->threshold = statetype; } - // TODO: Modify state durations based on movement speed, similar to players? +#define follow metal->tracer + if (ziptic & GZT_FOLLOW) + { // Even more... + UINT8 followtic = READUINT8(metal_p); + fixed_t temp; + if (followtic & FZT_SPAWNED) + { + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST)); + P_SetTarget(&follow->tracer, metal); + follow->tics = -1; + temp = READINT16(metal_p)<<FRACBITS; + follow->height = FixedMul(follow->scale, temp); + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; + + if (followtic & FZT_COLORIZED) + follow->colorized = true; + + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(metal_p)]; + } + if (follow) + { + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(metal_p); + else + follow->destscale = metal->destscale; + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); + + P_UnsetThingPosition(follow); + temp = READINT16(metal_p)<<8; + follow->x = metal->x + temp; + temp = READINT16(metal_p)<<8; + follow->y = metal->y + temp; + temp = READINT16(metal_p)<<8; + follow->z = metal->z + temp; + P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(metal_p); + else + follow->sprite2 = 0; + follow->sprite = READUINT16(metal_p); + follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits + follow->angle = metal->angle; + follow->color = READUINT8(metal_p); - if (*metal_p == DEMOMARKER) - { - // end of demo data stream - G_StopMetalDemo(); - return; - } + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } + } + } + } + else if (follow) + { + P_RemoveMobj(follow); + P_SetTarget(&follow, NULL); + } +#undef follow } void G_WriteMetalTic(mobj_t *metal) { UINT8 ziptic = 0; UINT8 *ziptic_p; + fixed_t height; - if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered! + if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated! return; + WRITEUINT8(demo_p, METALSNICE); ziptic_p = demo_p++; // the ziptic, written at the end of this function #define MAXMOM (0xFFFF<<8) @@ -4949,10 +5172,10 @@ void G_WriteMetalTic(mobj_t *metal) oldmetal.x = metal->x; oldmetal.y = metal->y; oldmetal.z = metal->z; + ziptic |= GZT_XYZ; WRITEFIXED(demo_p,oldmetal.x); WRITEFIXED(demo_p,oldmetal.y); WRITEFIXED(demo_p,oldmetal.z); - ziptic |= GZT_XYZ; } else { @@ -4965,16 +5188,16 @@ void G_WriteMetalTic(mobj_t *metal) { oldmetal.momx = momx; oldmetal.momy = momy; + ziptic |= GZT_MOMXY; WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momy); - ziptic |= GZT_MOMXY; } momx = (INT16)((metal->z-oldmetal.z)>>8); if (momx != oldmetal.momz) { oldmetal.momz = momx; - WRITEINT16(demo_p,momx); ziptic |= GZT_MOMZ; + WRITEINT16(demo_p,momx); } // This SHOULD set oldmetal.x/y/z to match metal->x/y/z @@ -4997,33 +5220,104 @@ void G_WriteMetalTic(mobj_t *metal) WRITEUINT8(demo_p,oldmetal.angle); } - // Metal Sonic does not need our state changes. - // ... currently. + // Store the sprite frame. + if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame) + { + oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits + ziptic |= GZT_FRAME; + WRITEUINT32(demo_p,oldmetal.frame); + } + + if (metal->sprite == SPR_PLAY + && metal->sprite2 != oldmetal.sprite2) + { + oldmetal.sprite2 = metal->sprite2; + ziptic |= GZT_SPR2; + WRITEUINT8(demo_p,oldmetal.sprite2); + } + + // Check for sprite set changes + if (metal->sprite != oldmetal.sprite) + { + oldmetal.sprite = metal->sprite; + ghostext.flags |= EZT_SPRITE; + } + + if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height) + { + oldmetal.height = height; + ghostext.flags |= EZT_HEIGHT; + } + if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever { - UINT8 *exttic_p = NULL; - UINT8 exttic = 0; - if ((metal->eflags & MFE_VERTICALFLIP) != (oldmetal.eflags & MFE_VERTICALFLIP)) + ziptic |= GZT_EXTRA; + + if (ghostext.scale == ghostext.lastscale) + ghostext.flags &= ~EZT_SCALE; + + WRITEUINT8(demo_p,ghostext.flags); + if (ghostext.flags & EZT_SCALE) { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_FLIP; - oldmetal.eflags ^= MFE_VERTICALFLIP; + WRITEFIXED(demo_p,ghostext.scale); + ghostext.lastscale = ghostext.scale; } - if (metal->scale != oldmetal.scale) + if (ghostext.flags & EZT_SPRITE) + WRITEUINT16(demo_p,oldmetal.sprite); + if (ghostext.flags & EZT_HEIGHT) + { + height >>= FRACBITS; + WRITEINT16(demo_p, height); + } + ghostext.flags = 0; + } + + if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW))) + { + INT16 temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; + + ziptic |= GZT_FOLLOW; + + if (metal->player->followmobj->skin) + followtic |= FZT_SKIN; + + if (!(oldmetal.flags2 & MF2_AMBUSH)) { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_SCALE; - WRITEFIXED(demo_p,metal->scale); - oldmetal.scale = metal->scale; + followtic |= FZT_SPAWNED; + WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS); + if (metal->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; + if (metal->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins)); + oldmetal.flags2 |= MF2_AMBUSH; } - if (exttic_p) + + if (metal->player->followmobj->scale != metal->scale) { - *exttic_p = exttic; - ziptic |= GZT_EXTRA; + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,metal->player->followmobj->scale); } + + temp = (INT16)((metal->player->followmobj->x-metal->x)>>8); + WRITEINT16(demo_p,temp); + temp = (INT16)((metal->player->followmobj->y-metal->y)>>8); + WRITEINT16(demo_p,temp); + temp = (INT16)((metal->player->followmobj->z-metal->z)>>8); + WRITEINT16(demo_p,temp); + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,metal->player->followmobj->sprite2); + WRITEUINT16(demo_p,metal->player->followmobj->sprite); + WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits + WRITEUINT8(demo_p,metal->player->followmobj->color); + + *followtic_p = followtic; } + else + oldmetal.flags2 &= ~MF2_AMBUSH; *ziptic_p = ziptic; @@ -5031,7 +5325,7 @@ void G_WriteMetalTic(mobj_t *metal) // latest demos with mouse aiming byte in ticcmd if (demo_p >= demoend - 32) { - G_StopMetalRecording(); // no more space + G_StopMetalRecording(false); // no more space return; } } @@ -5165,22 +5459,36 @@ void G_BeginRecording(void) // And mobjtype_t is best with UINT32 too... WRITEUINT32(demo_p, player->followitem); - // Save pflag data + // Save pflag data - see SendWeaponPref() { UINT8 buf = 0; - if (player->pflags & PF_FLIPCAM) + pflags_t pflags = 0; + if (cv_flipcam.value) + { buf |= 0x01; - if (player->pflags & PF_ANALOGMODE) + pflags |= PF_FLIPCAM; + } + if (cv_analog.value) + { buf |= 0x02; - if (player->pflags & PF_DIRECTIONCHAR) + pflags |= PF_ANALOGMODE; + } + if (cv_directionchar.value) + { buf |= 0x04; - if (player->pflags & PF_AUTOBRAKE) + pflags |= PF_DIRECTIONCHAR; + } + if (cv_autobrake.value) + { buf |= 0x08; + pflags |= PF_AUTOBRAKE; + } if (cv_usejoystick.value) buf |= 0x10; CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value)); WRITEUINT8(demo_p,buf); + player->pflags = pflags; } // Save netvar data @@ -5209,8 +5517,10 @@ void G_BeginMetal(void) { mobj_t *mo = players[consoleplayer].mo; +#if 0 if (demo_p) return; +#endif demo_p = demobuffer; @@ -5225,6 +5535,9 @@ void G_BeginMetal(void) M_Memcpy(demo_p, "METL", 4); demo_p += 4; + memset(&ghostext,0,sizeof(ghostext)); + ghostext.lastscale = ghostext.scale = FRACUNIT; + // Set up our memory. memset(&oldmetal,0,sizeof(oldmetal)); oldmetal.x = mo->x; @@ -5873,7 +6186,9 @@ void G_AddGhost(char *defdemoname) gh->mo->state = states+S_PLAY_STND; gh->mo->sprite = gh->mo->state->sprite; gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); - gh->mo->frame = tr_trans20<<FF_TRANSSHIFT; + //gh->mo->frame = tr_trans30<<FF_TRANSSHIFT; + gh->mo->flags2 |= MF2_DONTDRAW; + gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible gh->mo->tics = -1; CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname); @@ -5994,19 +6309,23 @@ void G_StopMetalDemo(void) } // Stops metal sonic recording. -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void) +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill) { boolean saved = false; if (demo_p) { UINT8 *p = demobuffer+16; // checksum position + if (kill) + WRITEUINT8(demo_p, METALDEATH); // add the metal death marker + else + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker #ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. + { + UINT8 i; + for (i = 0; i < 16; i++, p++) + *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. + } #else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file. #endif saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. @@ -6064,7 +6383,46 @@ boolean G_CheckDemoStatus(void) timingdemo = false; f1 = (double)demotime; f2 = (double)framecount*TICRATE; - CONS_Printf(M_GetText("timed %u gametics in %d realtics\n%f seconds, %f avg fps\n"), leveltime,demotime,f1/TICRATE,f2/f1); + + CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"), + leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1); + + // CSV-readable timedemo results, for external parsing + if (timedemo_csv) + { + FILE *f; + const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv"); + const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n"; + const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n"; + boolean headerrow = !FIL_FileExists(csvpath); + UINT8 procbits = 0; + + // Bitness + if (sizeof(void*) == 4) + procbits = 32; + else if (sizeof(void*) == 8) + procbits = 64; + + f = fopen(csvpath, "a+"); + + if (f) + { + if (headerrow) + fputs(header, f); + fprintf(f, rowformat, + timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits); + fclose(f); + CONS_Printf("Timedemo results saved to '%s'\n", csvpath); + } + else + { + // Just print the CSV output to console + CON_LogMessage(header); + CONS_Printf(rowformat, + timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits); + } + } + if (restorecv_vidwait != cv_vidwait.value) CV_SetValue(&cv_vidwait, restorecv_vidwait); D_AdvanceDemo(); diff --git a/src/g_game.h b/src/g_game.h index 198cbc396ccb5d76b1596d3ef7d45b89ee755d98..22abae17dea2c66d116fc109fe08101161d3c646 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -37,6 +37,7 @@ extern boolean playeringame[MAXPLAYERS]; // demoplaying back and demo recording extern boolean demoplayback, titledemo, demorecording, timingdemo; +extern tic_t demostarttime; // Quit after playing a demo from cmdline. extern boolean singledemo; @@ -174,7 +175,7 @@ void G_AddGhost(char *defdemoname); void G_DoPlayMetal(void); void G_DoneLevelLoad(void); void G_StopMetalDemo(void); -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 7f5a04526115859ec9ea89fa802749af19be8cc0..6eaafca6d0deec87da0404a1ecb508880e06494c 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -506,43 +506,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockheight < 1) I_Error("3D GenerateTexture : too small"); } - else if (cv_voodoocompatibility.value) - { - if (originalwidth > 256 || originalheight > 256) - { - blockwidth = 256; - while (originalwidth < blockwidth) - blockwidth >>= 1; - if (blockwidth < 1) - I_Error("3D GenerateTexture : too small"); - - blockheight = 256; - while (originalheight < blockheight) - blockheight >>= 1; - if (blockheight < 1) - I_Error("3D GenerateTexture : too small"); - } - else - { - //size up to nearest power of 2 - blockwidth = 1; - while (blockwidth < originalwidth) - blockwidth <<= 1; - // scale down the original graphics to fit in 256 - if (blockwidth > 256) - blockwidth = 256; - //I_Error("3D GenerateTexture : too big"); - - //size up to nearest power of 2 - blockheight = 1; - while (blockheight < originalheight) - blockheight <<= 1; - // scale down the original graphics to fit in 256 - if (blockheight > 256) - blockheight = 255; - //I_Error("3D GenerateTexture : too big"); - } - } else { #ifdef GLIDE_API_COMPATIBILITY @@ -771,18 +734,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm newwidth = blockwidth; newheight = blockheight; } - else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256. - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(grPatch->width, blockwidth); - newheight = min(grPatch->height, blockheight); - - if (newwidth > 256 || newheight > 256) - { - newwidth = blockwidth; - newheight = blockheight; - } - } else { // no rounddown, do not size up patches, so they don't look 'scaled' @@ -925,29 +876,6 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } -// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch. -lumpnum_t gr_patchflat; - -static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) -{ - UINT8 *flat; - patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); -#ifndef NO_PNG_LUMPS - size_t lumplength = W_LumpLength(flatlumpnum); - - if (R_IsLumpPNG((UINT8 *)patch, lumplength)) - patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false); -#endif - - grMipmap->width = (UINT16)SHORT(patch->width); - grMipmap->height = (UINT16)SHORT(patch->height); - - flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); - memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); - - R_PatchToFlat(patch, flat); -} - static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size, pflatsize; @@ -988,40 +916,15 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) break; } - if (R_CheckIfPatch(flatlumpnum)) - HWR_LoadPatchFlat(grMipmap, flatlumpnum); - else - { - grMipmap->width = (UINT16)pflatsize; - grMipmap->height = (UINT16)pflatsize; + grMipmap->width = (UINT16)pflatsize; + grMipmap->height = (UINT16)pflatsize; - // the flat raw data needn't be converted with palettized textures - W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); - } + // the flat raw data needn't be converted with palettized textures + W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), + PU_HWRCACHE, &grMipmap->grInfo.data)); } -// Download a Doom 'flat' to the hardware cache and make it ready for use -void HWR_GetFlat(lumpnum_t flatlumpnum) -{ - GLMipmap_t *grmip; - - grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; - - if (!grmip->downloaded && !grmip->grInfo.data) - HWR_CacheFlat(grmip, flatlumpnum); - - HWD.pfnSetTexture(grmip); - - // The system-memory data can be purged now. - Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); - - gr_patchflat = 0; - if (R_CheckIfPatch(flatlumpnum)) - gr_patchflat = flatlumpnum; -} - -static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) +static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) { UINT8 *flat; @@ -1043,24 +946,53 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) R_TextureToFlat(texturenum, flat); } -void HWR_GetTextureFlat(INT32 texturenum) +// Download a Doom 'flat' to the hardware cache and make it ready for use +void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) { - GLTexture_t *grtex; -#ifdef PARANOIA - if ((unsigned)texturenum >= gr_numtextures) - I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n"); -#endif - if (texturenum == 0 || texturenum == -1) + GLMipmap_t *grmip; + if (flatlumpnum == LUMPERROR) return; - grtex = &gr_textures2[texturenum]; - if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) - HWR_LoadTextureFlat(&grtex->mipmap, texturenum); + grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; + if (!grmip->downloaded && !grmip->grInfo.data) + HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(&grtex->mipmap); + HWD.pfnSetTexture(grmip); // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); +} + +void HWR_GetLevelFlat(levelflat_t *levelflat) +{ + // Who knows? + if (levelflat == NULL) + return; + + if (levelflat->type == LEVELFLAT_FLAT) + HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum); + else if (levelflat->type == LEVELFLAT_TEXTURE) + { + GLTexture_t *grtex; + INT32 texturenum = levelflat->u.texture.num; +#ifdef PARANOIA + if ((unsigned)texturenum >= gr_numtextures) + I_Error("HWR_GetLevelFlat: texturenum >= numtextures\n"); +#endif + if (texturenum == 0 || texturenum == -1) + return; + grtex = &gr_textures2[texturenum]; + + if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) + HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); + + HWD.pfnSetTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); + } + else // set no texture + HWD.pfnSetTexture(NULL); } // @@ -1286,18 +1218,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) newwidth = blockwidth; newheight = blockheight; } - else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256. - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(SHORT(pic->width),blockwidth); - newheight = min(SHORT(pic->height),blockheight); - - if (newwidth > 256 || newheight > 256) - { - newwidth = blockwidth; - newheight = blockheight; - } - } else { // no rounddown, do not size up patches, so they don't look 'scaled' diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index 6d120efe72c4ca251b61dfa5c68be1b206719d31..4bdc753ec870e750c1f9fc3768d46defbc0a788a 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -77,8 +77,8 @@ #include "r_opengl/r_opengl.h" #ifdef HAVE_SPHEREFRUSTRUM -static GLdouble viewMatrix[16]; -static GLdouble projMatrix[16]; +static GLfloat viewMatrix[16]; +static GLfloat projMatrix[16]; float frustum[6][4]; #endif @@ -380,8 +380,8 @@ void gld_FrustrumSetup(void) float t; float clip[16]; - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); - pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix); + pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12); clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13); diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b8354c82d14b04291e30826e7a63db670149bc6d..eed96ddc04799769108520147f17f456b5eaef25 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -95,18 +95,34 @@ typedef struct //Hurdler: Transform (coords + angles) //BP: transform order : scale(rotation_x(rotation_y(translation(v)))) + +// Kart features +//#define USE_FTRANSFORM_ANGLEZ +//#define USE_FTRANSFORM_MIRROR + +// Vanilla features +#define USE_MODEL_NEXTFRAME + typedef struct { FLOAT x,y,z; // position +#ifdef USE_FTRANSFORM_ANGLEZ + FLOAT anglex,angley,anglez; // aimingangle / viewangle +#else FLOAT anglex,angley; // aimingangle / viewangle +#endif FLOAT scalex,scaley,scalez; FLOAT fovxangle, fovyangle; - INT32 splitscreen; + UINT8 splitscreen; boolean flip; // screenflip #ifdef ROTSPRITE - // rotsprite boolean roll; - FLOAT centerx,centery; + SINT8 nightsroll; + FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ + FLOAT centerx, centery; +#endif +#ifdef USE_FTRANSFORM_MIRROR + boolean mirror; // SRB2Kart: Encore Mode #endif } FTransform; @@ -150,7 +166,7 @@ enum EPolyFlags // When set, pass the color constant into the FSurfaceInfo -> FlatColor PF_NoTexture = 0x00002000, // Use the small white texture PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona - PF_MD2 = 0x00008000, // Tell the rendrer we are drawing an MD2 + PF_Unused = 0x00008000, // Unused PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapY = 0x00040000, // Force repeat texture on Y @@ -208,8 +224,6 @@ enum hwdsetspecialstate HWD_SET_FOG_COLOR, HWD_SET_FOG_DENSITY, HWD_SET_FOV, - HWD_SET_POLYGON_SMOOTH, - HWD_SET_PALETTECOLOR, HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, HWD_NUMSTATE diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index d9e688c0aaa5d8745754c662f50472b621ae47ba..3b0620cc134c96c480aade16dce049e4d443e71c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -647,7 +647,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize); v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize); - HWR_GetFlat(flatlumpnum); + HWR_LiterallyGetFlat(flatlumpnum); //Hurdler: Boris, the same comment as above... but maybe for pics // it not a problem since they don't have any transparent pixel diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e0507bc7083f9f54cebe7b3ab6952fa5a932ee03..aed1611f111176ba0ab9c907362e154421894825 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -59,20 +59,18 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale); -EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); +EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetRenderVersion) (void); -#ifdef SHUFFLE #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); -#endif EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); -EXPORT void HWRAPI(DoScreenWipe) (float alpha); +EXPORT void HWRAPI(DoScreenWipe) (void); EXPORT void HWRAPI(DrawIntermissionBG) (void); EXPORT void HWRAPI(MakeScreenTexture) (void); EXPORT void HWRAPI(MakeScreenFinalTexture) (void); @@ -98,8 +96,8 @@ struct hwdriver_s GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility - DrawMD2 pfnDrawMD2; - DrawMD2i pfnDrawMD2i; + DrawModel pfnDrawModel; + CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; GetRenderVersion pfnGetRenderVersion; @@ -109,9 +107,7 @@ struct hwdriver_s #ifndef HAVE_SDL Shutdown pfnShutdown; #endif -#ifdef SHUFFLE PostImgRedraw pfnPostImgRedraw; -#endif FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; EndScreenWipe pfnEndScreenWipe; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index d55b010d87f37073947625e59505b381813842bf..69cf8bf46c1e2549ec356cf5e9048e1fa66e3917 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -23,6 +23,7 @@ #include "hw_defs.h" #include "hw_main.h" #include "../m_misc.h" +#include "../p_setup.h" // the original aspect ratio of Doom graphics isn't square #define ORIGINAL_ASPECT (320.0f/200.0f) @@ -101,8 +102,8 @@ void HWR_InitTextureCache(void); void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); -void HWR_GetFlat(lumpnum_t flatlumpnum); -void HWR_GetTextureFlat(INT32 texturenum); +void HWR_GetLevelFlat(levelflat_t *levelflat); +void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); GLTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); @@ -119,8 +120,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern lumpnum_t gr_patchflat; - extern float gr_patch_scalex; extern float gr_patch_scaley; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 25a6c5701b8f7821001ca56576bbd2ba34355cdb..f9e26733e158acebf84369020fd36a214ae45468 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -71,12 +71,12 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif #ifdef SORTING -void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else -static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, +static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector); static void HWR_Render3DWater(void); static void HWR_RenderTransparentWalls(void); @@ -523,7 +523,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) + FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -531,9 +531,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatwidth, fflatheight; - INT32 flatflag; - boolean texflat = true; + float fflatwidth = 64.0f, fflatheight = 64.0f; + INT32 flatflag = 63; + boolean texflat = false; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -542,7 +542,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #ifdef ESLOPE pslope_t *slope = NULL; #endif - patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -598,48 +597,49 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts); } - len = W_LumpLength(lumpnum); - - switch (len) + // set texture for polygon + if (levelflat != NULL) { - case 4194304: // 2048x2048 lump - fflatwidth = fflatheight = 2048.0f; - break; - case 1048576: // 1024x1024 lump - fflatwidth = fflatheight = 1024.0f; - break; - case 262144:// 512x512 lump - fflatwidth = fflatheight = 512.0f; - break; - case 65536: // 256x256 lump - fflatwidth = fflatheight = 256.0f; - break; - case 16384: // 128x128 lump - fflatwidth = fflatheight = 128.0f; - break; - case 1024: // 32x32 lump - fflatwidth = fflatheight = 32.0f; - break; - default: // 64x64 lump - fflatwidth = fflatheight = 64.0f; - break; - } + if (levelflat->type == LEVELFLAT_TEXTURE) + { + fflatwidth = textures[levelflat->u.texture.num]->width; + fflatheight = textures[levelflat->u.texture.num]->height; + texflat = true; + } + else if (levelflat->type == LEVELFLAT_FLAT) + { + len = W_LumpLength(levelflat->u.flat.lumpnum); - flatflag = ((INT32)fflatwidth)-1; + switch (len) + { + case 4194304: // 2048x2048 lump + fflatwidth = fflatheight = 2048.0f; + break; + case 1048576: // 1024x1024 lump + fflatwidth = fflatheight = 1024.0f; + break; + case 262144:// 512x512 lump + fflatwidth = fflatheight = 512.0f; + break; + case 65536: // 256x256 lump + fflatwidth = fflatheight = 256.0f; + break; + case 16384: // 128x128 lump + fflatwidth = fflatheight = 128.0f; + break; + case 1024: // 32x32 lump + fflatwidth = fflatheight = 32.0f; + break; + default: // 64x64 lump + fflatwidth = fflatheight = 64.0f; + break; + } - if (texturenum != 0 && texturenum != -1) - { - fflatwidth = textures[texturenum]->width; - fflatheight = textures[texturenum]->height; - } - else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = SHORT(patch->width); - fflatheight = SHORT(patch->height); + flatflag = ((INT32)fflatwidth)-1; + } } - else - texflat = false; + else // set no texture + HWD.pfnSetTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); @@ -1973,7 +1973,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { // Single sided line... Deal only with the middletexture (if one exists) gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture) + if (gr_midtexture && gr_linedef->special != 41) // Ignore horizon line for OGL { { fixed_t texturevpeg; @@ -3184,23 +3184,22 @@ static inline void HWR_AddPolyObjectSegs(void) #ifdef POLYOBJECTS_PLANES static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, + FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatwidth, fflatheight; - INT32 flatflag; - boolean texflat = true; + float fflatwidth = 64.0f, fflatheight = 64.0f; + INT32 flatflag = 63; + boolean texflat = false; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; size_t nrPlaneVerts; - patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -3226,48 +3225,49 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts); } - len = W_LumpLength(lumpnum); - - switch (len) + // set texture for polygon + if (levelflat != NULL) { - case 4194304: // 2048x2048 lump - fflatwidth = fflatheight = 2048.0f; - break; - case 1048576: // 1024x1024 lump - fflatwidth = fflatheight = 1024.0f; - break; - case 262144:// 512x512 lump - fflatwidth = fflatheight = 512.0f; - break; - case 65536: // 256x256 lump - fflatwidth = fflatheight = 256.0f; - break; - case 16384: // 128x128 lump - fflatwidth = fflatheight = 128.0f; - break; - case 1024: // 32x32 lump - fflatwidth = fflatheight = 32.0f; - break; - default: // 64x64 lump - fflatwidth = fflatheight = 64.0f; - break; - } + if (levelflat->type == LEVELFLAT_TEXTURE) + { + fflatwidth = textures[levelflat->u.texture.num]->width; + fflatheight = textures[levelflat->u.texture.num]->height; + texflat = true; + } + else if (levelflat->type == LEVELFLAT_FLAT) + { + len = W_LumpLength(levelflat->u.flat.lumpnum); - flatflag = ((INT32)fflatwidth)-1; + switch (len) + { + case 4194304: // 2048x2048 lump + fflatwidth = fflatheight = 2048.0f; + break; + case 1048576: // 1024x1024 lump + fflatwidth = fflatheight = 1024.0f; + break; + case 262144:// 512x512 lump + fflatwidth = fflatheight = 512.0f; + break; + case 65536: // 256x256 lump + fflatwidth = fflatheight = 256.0f; + break; + case 16384: // 128x128 lump + fflatwidth = fflatheight = 128.0f; + break; + case 1024: // 32x32 lump + fflatwidth = fflatheight = 32.0f; + break; + default: // 64x64 lump + fflatwidth = fflatheight = 64.0f; + break; + } - if (texturenum != 0 && texturenum != -1) - { - fflatwidth = textures[texturenum]->width; - fflatheight = textures[texturenum]->height; - } - else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = SHORT(patch->width); - fflatheight = SHORT(patch->height); + flatflag = ((INT32)fflatwidth)-1; + } } - else - texflat = false; + else // set no texture + HWD.pfnSetTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); @@ -3401,15 +3401,14 @@ static void HWR_AddPolyObjectPlanes(void) FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight, + HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { - HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); - HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); + HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic], polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } @@ -3425,15 +3424,14 @@ static void HWR_AddPolyObjectPlanes(void) FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight, + HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { - HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); - HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); + HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic], polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } @@ -3584,13 +3582,12 @@ static void HWR_Subsector(size_t num) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); - HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum); + HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]); HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap); } } else @@ -3607,13 +3604,12 @@ static void HWR_Subsector(size_t num) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); - HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum); + HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]); HWR_RenderPlane(NULL, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap); } } else @@ -3672,7 +3668,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, 0, + HWR_AddTransparentFloor(NULL, &extrasubsectors[num], false, *rover->bottomheight, @@ -3684,14 +3680,13 @@ static void HWR_Subsector(size_t num) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING - HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum, + HWR_Add3DWater(&levelflats[*rover->bottompic], &extrasubsectors[num], *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, rover->alpha-1, rover->master->frontsector); #else - HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, - levelflats[*rover->bottompic].texturenum, + HWR_AddTransparentFloor(&levelflats[*rover->bottompic], &extrasubsectors[num], false, *rover->bottomheight, @@ -3702,10 +3697,9 @@ static void HWR_Subsector(size_t num) } else { - HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); - HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); + HWR_GetLevelFlat(&levelflats[*rover->bottompic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, + HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3737,7 +3731,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, 0, + HWR_AddTransparentFloor(NULL, &extrasubsectors[num], true, *rover->topheight, @@ -3749,14 +3743,13 @@ static void HWR_Subsector(size_t num) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING - HWR_Add3DWater(levelflats[*rover->toppic].lumpnum, + HWR_Add3DWater(&levelflats[*rover->toppic], &extrasubsectors[num], *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, rover->alpha-1, rover->master->frontsector); #else - HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, - levelflats[*rover->bottompic].texturenum, + HWR_AddTransparentFloor(&levelflats[*rover->toppic], &extrasubsectors[num], true, *rover->topheight, @@ -3768,10 +3761,9 @@ static void HWR_Subsector(size_t num) } else { - HWR_GetFlat(levelflats[*rover->toppic].lumpnum); - HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); + HWR_GetLevelFlat(&levelflats[*rover->toppic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, + HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -5099,8 +5091,7 @@ typedef struct boolean isceiling; fixed_t fixedheight; INT32 lightlevel; - lumpnum_t lumpnum; - INT32 texturenum; + levelflat_t *levelflat; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5118,8 +5109,7 @@ typedef struct boolean isceiling; fixed_t fixedheight; INT32 lightlevel; - lumpnum_t lumpnum; - INT32 texturenum; + levelflat_t *levelflat; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5150,7 +5140,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -5168,8 +5158,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].lightlevel = lightlevel; - planeinfo[numplanes].lumpnum = lumpnum; - planeinfo[numplanes].texturenum = texturenum; + planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -5183,7 +5172,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -5201,8 +5190,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, poly polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].lightlevel = lightlevel; - polyplaneinfo[numpolyplanes].lumpnum = lumpnum; - polyplaneinfo[numpolyplanes].texturenum = texturenum; + polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -5364,12 +5352,9 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - { - HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); - HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum); - } + HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat); HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -5377,12 +5362,9 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - { - HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); - HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum); - } + HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat); HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { @@ -5427,17 +5409,17 @@ static void HWR_DrawSprites(void) #endif if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) + if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) HWR_DrawSprite(spr); else - HWR_DrawMD2(spr); + HWR_DrawModel(spr); } else { - if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + if (!cv_grmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) HWR_DrawSprite(spr); else - HWR_DrawMD2(spr); + HWR_DrawModel(spr); } } } @@ -5578,7 +5560,7 @@ static void HWR_ProjectSprite(mobj_t *thing) tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear + if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear return; // The above can stay as it works for cutting sprites that are too close @@ -5806,6 +5788,15 @@ static void HWR_ProjectSprite(mobj_t *thing) // New colormap stuff for skins Tails 06-07-2002 if (thing->colorized) vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE); + else if (thing->player && thing->player->dashmode >= DASHMODE_THRESHOLD + && (thing->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) + { + if (thing->player->charflags & SF_MACHINE) + vis->colormap = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE); + } else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)thing->skin-skins; @@ -6359,6 +6350,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) // note: sets viewangle, viewx, viewy, viewz R_SetupFrame(player); + framecount++; // timedemo // copy view cam position for local use dup_viewx = viewx; @@ -6655,13 +6647,13 @@ void HWR_Startup(void) // do this once if (!startupdone) { - CONS_Printf("HWR_Startup()\n"); + CONS_Printf("HWR_Startup()...\n"); HWR_InitPolyPool(); // add console cmds & vars HWR_AddEngineCommands(); HWR_InitTextureCache(); - HWR_InitMD2(); + HWR_InitModels(); #ifdef ALAM_LIGHTING HWR_InitLight(); @@ -6712,10 +6704,11 @@ void transform(float *cx, float *cy, float *cz) //Hurdler: 3D Water stuff +#ifndef SORTING + #define MAX_3DWATER 512 -#ifndef SORTING -static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, +static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector) { static size_t allocedplanes = 0; @@ -6731,17 +6724,15 @@ static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, } planeinfo[numfloors].fixedheight = fixedheight; planeinfo[numfloors].lightlevel = lightlevel; - planeinfo[numfloors].lumpnum = lumpnum; + planeinfo[numfloors].levelflat = levelflat; planeinfo[numfloors].xsub = xsub; planeinfo[numfloors].alpha = alpha; planeinfo[numfloors].FOFSector = FOFSector; numfloors++; } -#endif #define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz) -#if 0 static void HWR_QuickSortPlane(INT32 start, INT32 finish) { INT32 left = start; @@ -6771,9 +6762,7 @@ static void HWR_QuickSortPlane(INT32 start, INT32 finish) if (start < right) HWR_QuickSortPlane(start, right); if (left < finish) HWR_QuickSortPlane(left, finish); } -#endif -#ifndef SORTING static void HWR_Render3DWater(void) { size_t i; @@ -6804,8 +6793,8 @@ static void HWR_Render3DWater(void) gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid for (i = 0; i < numfloors; i++) { - HWR_GetFlat(planeinfo[i].lumpnum); - HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].lumpnum, + HWR_GetLevelFlat(planeinfo[i].levelflat); + HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat, planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap); } numfloors = 0; @@ -6838,6 +6827,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I wallinfo[numwalls].wallcolormap = wallcolormap; numwalls++; } + #ifndef SORTING static void HWR_RenderTransparentWalls(void) { @@ -6870,6 +6860,7 @@ static void HWR_RenderTransparentWalls(void) numwalls = 0; } #endif + static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { FOutVector trVerts[4]; @@ -6928,11 +6919,6 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE #endif } -void HWR_SetPaletteColor(INT32 palcolor) -{ - HWD.pfnSetSpecialState(HWD_SET_PALETTECOLOR, palcolor); -} - INT32 HWR_GetTextureUsed(void) { return HWD.pfnGetTextureUsed(); @@ -6979,7 +6965,6 @@ void HWR_DoPostProcessor(player_t *player) if (splitscreen) // Not supported in splitscreen - someone want to add support? return; -#ifdef SHUFFLE // Drunken vision! WooOOooo~ if (*type == postimg_water || *type == postimg_heat) { @@ -7022,7 +7007,6 @@ void HWR_DoPostProcessor(player_t *player) HWD.pfnMakeScreenTexture(); } // Flipping of the screen isn't done here anymore -#endif // SHUFFLE } void HWR_StartScreenWipe(void) @@ -7069,7 +7053,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) HWR_GetFadeMask(lumpnum); - HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing + HWD.pfnDoScreenWipe(); HWRWipeCounter += 0.05f; // increase opacity of end screen diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 31e97cc130fb9ce740194a704a8525905bdc0369..3a0a58427fbb1d2d8bed6173cb04430b32c45541 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -60,7 +60,6 @@ void HWR_AddCommands(void); void HWR_CorrectSWTricks(void); void transform(float *cx, float *cy, float *cz); FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); -void HWR_SetPaletteColor(INT32 palcolor); INT32 HWR_GetTextureUsed(void); void HWR_DoPostProcessor(player_t *player); void HWR_StartScreenWipe(void); @@ -83,7 +82,8 @@ extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif extern consvar_t cv_grfov; -extern consvar_t cv_grmd2; +extern consvar_t cv_grmodels; +extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grfog; extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogdensity; @@ -94,7 +94,6 @@ extern consvar_t cv_grgammablue; extern consvar_t cv_grfiltermode; extern consvar_t cv_granisotropicmode; extern consvar_t cv_grcorrecttricks; -extern consvar_t cv_voodoocompatibility; extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6b69e45bf0b980ff661972f60e2d8f6adb632472..c4b28076baf7fcc03aed656dd39fce2c63f3b59c 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -35,6 +35,7 @@ #include "hw_drv.h" #include "hw_light.h" #include "hw_md2.h" +#include "../d_main.h" #include "../r_bsp.h" #include "../r_main.h" #include "../m_misc.h" @@ -43,6 +44,7 @@ #include "../r_things.h" #include "../r_draw.h" #include "../p_tick.h" +#include "hw_model.h" #include "hw_main.h" #include "../v_video.h" @@ -75,172 +77,6 @@ #include "errno.h" #endif -#define NUMVERTEXNORMALS 162 -float avertexnormals[NUMVERTEXNORMALS][3] = { -{-0.525731f, 0.000000f, 0.850651f}, -{-0.442863f, 0.238856f, 0.864188f}, -{-0.295242f, 0.000000f, 0.955423f}, -{-0.309017f, 0.500000f, 0.809017f}, -{-0.162460f, 0.262866f, 0.951056f}, -{0.000000f, 0.000000f, 1.000000f}, -{0.000000f, 0.850651f, 0.525731f}, -{-0.147621f, 0.716567f, 0.681718f}, -{0.147621f, 0.716567f, 0.681718f}, -{0.000000f, 0.525731f, 0.850651f}, -{0.309017f, 0.500000f, 0.809017f}, -{0.525731f, 0.000000f, 0.850651f}, -{0.295242f, 0.000000f, 0.955423f}, -{0.442863f, 0.238856f, 0.864188f}, -{0.162460f, 0.262866f, 0.951056f}, -{-0.681718f, 0.147621f, 0.716567f}, -{-0.809017f, 0.309017f, 0.500000f}, -{-0.587785f, 0.425325f, 0.688191f}, -{-0.850651f, 0.525731f, 0.000000f}, -{-0.864188f, 0.442863f, 0.238856f}, -{-0.716567f, 0.681718f, 0.147621f}, -{-0.688191f, 0.587785f, 0.425325f}, -{-0.500000f, 0.809017f, 0.309017f}, -{-0.238856f, 0.864188f, 0.442863f}, -{-0.425325f, 0.688191f, 0.587785f}, -{-0.716567f, 0.681718f, -0.147621f}, -{-0.500000f, 0.809017f, -0.309017f}, -{-0.525731f, 0.850651f, 0.000000f}, -{0.000000f, 0.850651f, -0.525731f}, -{-0.238856f, 0.864188f, -0.442863f}, -{0.000000f, 0.955423f, -0.295242f}, -{-0.262866f, 0.951056f, -0.162460f}, -{0.000000f, 1.000000f, 0.000000f}, -{0.000000f, 0.955423f, 0.295242f}, -{-0.262866f, 0.951056f, 0.162460f}, -{0.238856f, 0.864188f, 0.442863f}, -{0.262866f, 0.951056f, 0.162460f}, -{0.500000f, 0.809017f, 0.309017f}, -{0.238856f, 0.864188f, -0.442863f}, -{0.262866f, 0.951056f, -0.162460f}, -{0.500000f, 0.809017f, -0.309017f}, -{0.850651f, 0.525731f, 0.000000f}, -{0.716567f, 0.681718f, 0.147621f}, -{0.716567f, 0.681718f, -0.147621f}, -{0.525731f, 0.850651f, 0.000000f}, -{0.425325f, 0.688191f, 0.587785f}, -{0.864188f, 0.442863f, 0.238856f}, -{0.688191f, 0.587785f, 0.425325f}, -{0.809017f, 0.309017f, 0.500000f}, -{0.681718f, 0.147621f, 0.716567f}, -{0.587785f, 0.425325f, 0.688191f}, -{0.955423f, 0.295242f, 0.000000f}, -{1.000000f, 0.000000f, 0.000000f}, -{0.951056f, 0.162460f, 0.262866f}, -{0.850651f, -0.525731f, 0.000000f}, -{0.955423f, -0.295242f, 0.000000f}, -{0.864188f, -0.442863f, 0.238856f}, -{0.951056f, -0.162460f, 0.262866f}, -{0.809017f, -0.309017f, 0.500000f}, -{0.681718f, -0.147621f, 0.716567f}, -{0.850651f, 0.000000f, 0.525731f}, -{0.864188f, 0.442863f, -0.238856f}, -{0.809017f, 0.309017f, -0.500000f}, -{0.951056f, 0.162460f, -0.262866f}, -{0.525731f, 0.000000f, -0.850651f}, -{0.681718f, 0.147621f, -0.716567f}, -{0.681718f, -0.147621f, -0.716567f}, -{0.850651f, 0.000000f, -0.525731f}, -{0.809017f, -0.309017f, -0.500000f}, -{0.864188f, -0.442863f, -0.238856f}, -{0.951056f, -0.162460f, -0.262866f}, -{0.147621f, 0.716567f, -0.681718f}, -{0.309017f, 0.500000f, -0.809017f}, -{0.425325f, 0.688191f, -0.587785f}, -{0.442863f, 0.238856f, -0.864188f}, -{0.587785f, 0.425325f, -0.688191f}, -{0.688191f, 0.587785f, -0.425325f}, -{-0.147621f, 0.716567f, -0.681718f}, -{-0.309017f, 0.500000f, -0.809017f}, -{0.000000f, 0.525731f, -0.850651f}, -{-0.525731f, 0.000000f, -0.850651f}, -{-0.442863f, 0.238856f, -0.864188f}, -{-0.295242f, 0.000000f, -0.955423f}, -{-0.162460f, 0.262866f, -0.951056f}, -{0.000000f, 0.000000f, -1.000000f}, -{0.295242f, 0.000000f, -0.955423f}, -{0.162460f, 0.262866f, -0.951056f}, -{-0.442863f, -0.238856f, -0.864188f}, -{-0.309017f, -0.500000f, -0.809017f}, -{-0.162460f, -0.262866f, -0.951056f}, -{0.000000f, -0.850651f, -0.525731f}, -{-0.147621f, -0.716567f, -0.681718f}, -{0.147621f, -0.716567f, -0.681718f}, -{0.000000f, -0.525731f, -0.850651f}, -{0.309017f, -0.500000f, -0.809017f}, -{0.442863f, -0.238856f, -0.864188f}, -{0.162460f, -0.262866f, -0.951056f}, -{0.238856f, -0.864188f, -0.442863f}, -{0.500000f, -0.809017f, -0.309017f}, -{0.425325f, -0.688191f, -0.587785f}, -{0.716567f, -0.681718f, -0.147621f}, -{0.688191f, -0.587785f, -0.425325f}, -{0.587785f, -0.425325f, -0.688191f}, -{0.000000f, -0.955423f, -0.295242f}, -{0.000000f, -1.000000f, 0.000000f}, -{0.262866f, -0.951056f, -0.162460f}, -{0.000000f, -0.850651f, 0.525731f}, -{0.000000f, -0.955423f, 0.295242f}, -{0.238856f, -0.864188f, 0.442863f}, -{0.262866f, -0.951056f, 0.162460f}, -{0.500000f, -0.809017f, 0.309017f}, -{0.716567f, -0.681718f, 0.147621f}, -{0.525731f, -0.850651f, 0.000000f}, -{-0.238856f, -0.864188f, -0.442863f}, -{-0.500000f, -0.809017f, -0.309017f}, -{-0.262866f, -0.951056f, -0.162460f}, -{-0.850651f, -0.525731f, 0.000000f}, -{-0.716567f, -0.681718f, -0.147621f}, -{-0.716567f, -0.681718f, 0.147621f}, -{-0.525731f, -0.850651f, 0.000000f}, -{-0.500000f, -0.809017f, 0.309017f}, -{-0.238856f, -0.864188f, 0.442863f}, -{-0.262866f, -0.951056f, 0.162460f}, -{-0.864188f, -0.442863f, 0.238856f}, -{-0.809017f, -0.309017f, 0.500000f}, -{-0.688191f, -0.587785f, 0.425325f}, -{-0.681718f, -0.147621f, 0.716567f}, -{-0.442863f, -0.238856f, 0.864188f}, -{-0.587785f, -0.425325f, 0.688191f}, -{-0.309017f, -0.500000f, 0.809017f}, -{-0.147621f, -0.716567f, 0.681718f}, -{-0.425325f, -0.688191f, 0.587785f}, -{-0.162460f, -0.262866f, 0.951056f}, -{0.442863f, -0.238856f, 0.864188f}, -{0.162460f, -0.262866f, 0.951056f}, -{0.309017f, -0.500000f, 0.809017f}, -{0.147621f, -0.716567f, 0.681718f}, -{0.000000f, -0.525731f, 0.850651f}, -{0.425325f, -0.688191f, 0.587785f}, -{0.587785f, -0.425325f, 0.688191f}, -{0.688191f, -0.587785f, 0.425325f}, -{-0.955423f, 0.295242f, 0.000000f}, -{-0.951056f, 0.162460f, 0.262866f}, -{-1.000000f, 0.000000f, 0.000000f}, -{-0.850651f, 0.000000f, 0.525731f}, -{-0.955423f, -0.295242f, 0.000000f}, -{-0.951056f, -0.162460f, 0.262866f}, -{-0.864188f, 0.442863f, -0.238856f}, -{-0.951056f, 0.162460f, -0.262866f}, -{-0.809017f, 0.309017f, -0.500000f}, -{-0.864188f, -0.442863f, -0.238856f}, -{-0.951056f, -0.162460f, -0.262866f}, -{-0.809017f, -0.309017f, -0.500000f}, -{-0.681718f, 0.147621f, -0.716567f}, -{-0.681718f, -0.147621f, -0.716567f}, -{-0.850651f, 0.000000f, -0.525731f}, -{-0.688191f, 0.587785f, -0.425325f}, -{-0.587785f, 0.425325f, -0.688191f}, -{-0.425325f, 0.688191f, -0.587785f}, -{-0.425325f, -0.688191f, -0.587785f}, -{-0.587785f, -0.425325f, -0.688191f}, -{-0.688191f, -0.587785f, -0.425325f}, -}; - md2_t md2_models[NUMSPRITES]; md2_t md2_playermodels[MAXSKINS]; @@ -248,230 +84,25 @@ md2_t md2_playermodels[MAXSKINS]; /* * free model */ -static void md2_freeModel (md2_model_t *model) +#if 0 +static void md2_freeModel (model_t *model) { - if (model) - { - if (model->skins) - free(model->skins); - - if (model->texCoords) - free(model->texCoords); - - if (model->triangles) - free(model->triangles); - - if (model->frames) - { - size_t i; - - for (i = 0; i < model->header.numFrames; i++) - { - if (model->frames[i].vertices) - free(model->frames[i].vertices); - } - free(model->frames); - } - - if (model->spr2frames) - free(model->spr2frames); - - if (model->glCommandBuffer) - free(model->glCommandBuffer); - - free(model); - } + UnloadModel(model); } +#endif // // load model // // Hurdler: the current path is the Legacy.exe path -static md2_model_t *md2_readModel(const char *filename) +static model_t *md2_readModel(const char *filename) { - FILE *file; - md2_model_t *model; - UINT8 buffer[MD2_MAX_FRAMESIZE]; - size_t i; - - model = calloc(1, sizeof (*model)); - if (model == NULL) - return 0; - //Filename checking fixed ~Monster Iestyn and Golden - file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb"); - if (!file) - { - free(model); - return 0; - } - - // initialize model and read header - - if (fread(&model->header, sizeof (model->header), 1, file) != 1 - || model->header.magic != MD2_IDENT - || model->header.version != MD2_VERSION) - { - fclose(file); - free(model); - return 0; - } - - model->header.numSkins = 1; - -#define MD2LIMITCHECK(field, max, msgname) \ - if (field > max) \ - { \ - CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \ - md2_freeModel (model); \ - fclose(file); \ - return 0; \ - } - - // Uncomment if these are actually needed -// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins") -// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates") - MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles") - MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames") - MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices") - -#undef MD2LIMITCHECK - - // read skins - fseek(file, model->header.offsetSkins, SEEK_SET); - if (model->header.numSkins > 0) - { - model->skins = calloc(sizeof (md2_skin_t), model->header.numSkins); - if (!model->skins || model->header.numSkins != - fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file)) - { - md2_freeModel (model); - fclose(file); - return 0; - } - } - - // read texture coordinates - fseek(file, model->header.offsetTexCoords, SEEK_SET); - if (model->header.numTexCoords > 0) - { - model->texCoords = calloc(sizeof (md2_textureCoordinate_t), model->header.numTexCoords); - if (!model->texCoords || model->header.numTexCoords != - fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file)) - { - md2_freeModel (model); - fclose(file); - return 0; - } - } - - // read triangles - fseek(file, model->header.offsetTriangles, SEEK_SET); - if (model->header.numTriangles > 0) - { - model->triangles = calloc(sizeof (md2_triangle_t), model->header.numTriangles); - if (!model->triangles || model->header.numTriangles != - fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file)) - { - md2_freeModel (model); - fclose(file); - return 0; - } - } - - // read alias frames - fseek(file, model->header.offsetFrames, SEEK_SET); - if (model->header.numFrames > 0) - { - model->frames = calloc(sizeof (md2_frame_t), model->header.numFrames); - if (!model->frames) - { - md2_freeModel (model); - fclose(file); - return 0; - } - - for (i = 0; i < model->header.numFrames; i++) - { - md2_alias_frame_t *frame = (md2_alias_frame_t *)(void *)buffer; - size_t j; - - model->frames[i].vertices = calloc(sizeof (md2_triangleVertex_t), model->header.numVertices); - if (!model->frames[i].vertices || model->header.frameSize != - fread(frame, 1, model->header.frameSize, file)) - { - md2_freeModel (model); - fclose(file); - return 0; - } - - strcpy(model->frames[i].name, frame->name); - if (frame->name[0] == 'S') - { - boolean super; - if ((super = (fastncmp("UPER", frame->name+1, 4))) // SUPER - || fastncmp("PR2_", frame->name+1, 4)) // SPR2_ - { - UINT8 spr2; - for (spr2 = 0; spr2 < free_spr2; spr2++) - if (fastncmp(frame->name+5,spr2names[spr2],3) - && ((frame->name[8] == spr2names[spr2][3]) - || (frame->name[8] == '.' && spr2names[spr2][3] == '_'))) - break; - - if (spr2 < free_spr2) - { - if (!model->spr2frames) - { - model->spr2frames = calloc(sizeof (size_t), 2*NUMPLAYERSPRITES*2); - if (!model->spr2frames) - { - md2_freeModel (model); - fclose(file); - return 0; - } - } - if (super) - spr2 |= FF_SPR2SUPER; - if (model->spr2frames[spr2*2 + 1]++ == 0) // numspr2frames - model->spr2frames[spr2*2] = i; // starting frame - CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %s, number of frames %s\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], sizeu1(model->spr2frames[spr2*2]), sizeu2(model->spr2frames[spr2*2 + 1])); - } - } - } - for (j = 0; j < model->header.numVertices; j++) - { - model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0]; - model->frames[i].vertices[j].vertex[2] = -1* ((float) ((INT32) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]); - model->frames[i].vertices[j].vertex[1] = (float) ((INT32) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2]; - model->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0]; - model->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1]; - model->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2]; - } - } - } - - // read gl commands - fseek(file, model->header.offsetGlCommands, SEEK_SET); - if (model->header.numGlCommands) - { - model->glCommandBuffer = calloc(sizeof (INT32), model->header.numGlCommands); - if (!model->glCommandBuffer || model->header.numGlCommands != - fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file)) - { - md2_freeModel (model); - fclose(file); - return 0; - } - } - - fclose(file); - - return model; + return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC); } -static inline void md2_printModelInfo (md2_model_t *model) +static inline void md2_printModelInfo (model_t *model) { #if 0 INT32 i; @@ -530,7 +161,7 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif png_FILE_p png_FILE; //Filename checking fixed ~Monster Iestyn and Golden - char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); + char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); @@ -659,7 +290,7 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, INT32 ch, rep; FILE *file; //Filename checking fixed ~Monster Iestyn and Golden - char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); + char *pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); @@ -720,7 +351,7 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, } // -----------------+ -// md2_loadTexture : Download a pcx or png texture for MD2 models +// md2_loadTexture : Download a pcx or png texture for models // -----------------+ static void md2_loadTexture(md2_t *model) { @@ -830,7 +461,7 @@ static void md2_loadBlendTexture(md2_t *model) // Don't spam the console, or the OS with fopen requests! static boolean nomd2s = false; -void HWR_InitMD2(void) +void HWR_InitModels(void) { size_t i; INT32 s; @@ -838,7 +469,7 @@ void HWR_InitMD2(void) char name[18], filename[32]; float scale, offset; - CONS_Printf("InitMD2()...\n"); + CONS_Printf("HWR_InitModels()...\n"); for (s = 0; s < MAXSKINS; s++) { md2_playermodels[s].scale = -1.0f; @@ -858,13 +489,13 @@ void HWR_InitMD2(void) md2_models[i].error = false; } - // read the md2.dat file + // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno)); + CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); nomd2s = true; return; } @@ -872,7 +503,7 @@ void HWR_InitMD2(void) { if (stricmp(name, "PLAY") == 0) { - CONS_Printf("MD2 for sprite PLAY detected in md2.dat, use a player skin instead!\n"); + CONS_Printf("Model for sprite PLAY detected in models.dat, use a player skin instead!\n"); continue; } @@ -906,7 +537,7 @@ void HWR_InitMD2(void) } } // no sprite/player skin name found?!? - CONS_Printf("Unknown sprite/player skin %s detected in md2.dat\n", name); + //CONS_Printf("Unknown sprite/player skin %s detected in models.dat\n", name); md2found: // move on to next line... continue; @@ -914,7 +545,7 @@ md2found: fclose(f); } -void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup +void HWR_AddPlayerModel(int skin) // For skins that were added after startup { FILE *f; char name[18], filename[32]; @@ -923,20 +554,20 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup if (nomd2s) return; - CONS_Printf("AddPlayerMD2()...\n"); + //CONS_Printf("HWR_AddPlayerModel()...\n"); - // read the md2.dat file + // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - CONS_Printf("Error while loading md2.dat\n"); + CONS_Printf("Error while loading models.dat\n"); nomd2s = true; return; } - // Check for any MD2s that match the names of player skins! + // Check for any model that match the names of player skins! while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) { if (stricmp(name, skins[skin].name) == 0) @@ -950,17 +581,16 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup } } - //CONS_Printf("MD2 for player skin %s not found\n", skins[skin].name); + //CONS_Printf("Model for player skin %s not found\n", skins[skin].name); md2_playermodels[skin].notfound = true; playermd2found: fclose(f); } - -void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startup +void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup { FILE *f; - // name[18] is used to check for names in the md2.dat file that match with sprites or player skins + // name[18] is used to check for names in the models.dat file that match with sprites or player skins // 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; @@ -971,18 +601,18 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check return; - // Read the md2.dat file + // Read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - CONS_Printf("Error while loading md2.dat\n"); + CONS_Printf("Error while loading models.dat\n"); nomd2s = true; return; } - // Check for any MD2s that match the names of player skins! + // Check for any MD2s that match the names of sprite names! while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) { if (stricmp(name, sprnames[spritenum]) == 0) @@ -1006,7 +636,6 @@ spritemd2found: // 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) @@ -1190,39 +819,40 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED); } +#define NORMALFOG 0x00000000 +#define FADEFOG 0x19000000 + +static boolean HWR_CanInterpolateModel(mobj_t *mobj, model_t *model) +{ + if (cv_grmodelinterpolation.value == 2) // Always interpolate + return true; + return model->interpolate[(mobj->frame & FF_FRAMEMASK)]; +} + +static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame) +{ + if (cv_grmodelinterpolation.value == 2) // Always interpolate + return true; + return spr2frame->interpolate; +} +// +// HWR_GetModelSprite2 (see P_GetSkinSprite2) +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +// -// -----------------+ -// HWR_DrawMD2 : Draw MD2 -// : (monsters, bonuses, weapons, lights, ...) -// Returns : -// -----------------+ - /* - wait/stand - death - pain - walk - shoot/fire - - die? - atka? - atkb? - attacka/b/c/d? - res? - run? - */ - -static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) +static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) { UINT8 super = 0, i = 0; - if (!md2 || !skin) + if (!md2 || !md2->model || !md2->model->spr2frames || !skin) return 0; if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; - while (!(md2->model->spr2frames[spr2*2 + 1]) + while (!md2->model->spr2frames[spr2].numframes && spr2 != SPR2_STND && ++i != 32) // recursion limiter { @@ -1263,19 +893,23 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p return spr2; } -#define NORMALFOG 0x00000000 -#define FADEFOG 0x19000000 -void HWR_DrawMD2(gr_vissprite_t *spr) +// +// HWR_DrawModel +// + +void HWR_DrawModel(gr_vissprite_t *spr) { FSurfaceInfo Surf; char filename[64]; - INT32 frame; + INT32 frame = 0; + INT32 nextFrame = -1; + UINT8 spr2 = 0; FTransform p; md2_t *md2; UINT8 color[4]; - if (!cv_grmd2.value) + if (!cv_grmodels.value) return; if (spr->precip) @@ -1321,13 +955,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // Look at HWR_ProjectSprite for more { GLPatch_t *gpatch; - INT32 *buff; INT32 durs = spr->mobj->state->tics; INT32 tics = spr->mobj->tics; - md2_frame_t *curr, *next = NULL; + //mdlframe_t *next = NULL; const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; + INT32 mod; float finalscale; // Apparently people don't like jump frames like that, so back it goes @@ -1358,13 +992,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr) return; // we already failed loading this before :( if (!md2->model) { - //CONS_Debug(DBG_RENDER, "Loading MD2... (%s)", sprnames[spr->mobj->sprite]); - sprintf(filename, "md2/%s", md2->filename); + //CONS_Debug(DBG_RENDER, "Loading model... (%s)", sprnames[spr->mobj->sprite]); + sprintf(filename, "models/%s", md2->filename); md2->model = md2_readModel(filename); if (md2->model) { md2_printModelInfo(md2->model); + HWD.pfnCreateModelVBOs(md2->model); } else { @@ -1403,16 +1038,21 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } else if (spr->mobj->color) { - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + if (spr->mobj->colorized) + skinnum = TC_RAINBOW; + else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (spr->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) { - if (spr->mobj->colorized) - skinnum = TC_RAINBOW; + if (spr->mobj->player->charflags & SF_MACHINE) + skinnum = TC_DASHMODE; else - { - skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); - } + skinnum = TC_RAINBOW; } - else skinnum = TC_DEFAULT; + else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + 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); } @@ -1436,70 +1076,69 @@ void HWR_DrawMD2(gr_vissprite_t *spr) tics = spr->mobj->anim_duration; } -#define INTERPOLERATION_LIMIT TICRATE/4 - + frame = (spr->mobj->frame & FF_FRAMEMASK); if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) { - UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); - UINT8 mod = md2->model->spr2frames[spr2*2 + 1] ? md2->model->spr2frames[spr2*2 + 1] : md2->model->header.numFrames; - if (mod > ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) + spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); + mod = md2->model->spr2frames[spr2].numframes; +#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod + if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK); - if (frame >= mod) - frame = 0; - buff = md2->model->glCommandBuffer; - curr = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame]; - if (cv_grmd2.value == 1 && tics <= durs && tics <= INTERPOLERATION_LIMIT) - { - if (durs > INTERPOLERATION_LIMIT) - durs = INTERPOLERATION_LIMIT; +#endif + if (!mod) + mod = 1; + frame = md2->model->spr2frames[spr2].frames[frame%mod]; + } + else + { + mod = md2->model->meshes[0].numFrames; + if (!mod) + mod = 1; + } - if (spr->mobj->frame & FF_ANIMATE +#ifdef USE_MODEL_NEXTFRAME +#define INTERPOLERATION_LIMIT TICRATE/4 + if (cv_grmodelinterpolation.value && tics <= durs && tics <= INTERPOLERATION_LIMIT) + { + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) + { + if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2]) + && (spr->mobj->frame & FF_ANIMATE || (spr->mobj->state->nextstate != S_NULL - && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite - && (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2)) + && states[spr->mobj->state->nextstate].sprite == SPR_PLAY + && ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2))))) { - if (++frame >= mod) - frame = 0; + nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextFrame >= mod) + nextFrame = 0; if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) - next = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame]; + nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; + else + nextFrame = -1; } } - } - else - { - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; - buff = md2->model->glCommandBuffer; - curr = &md2->model->frames[frame]; - if (cv_grmd2.value == 1 && tics <= durs && tics <= INTERPOLERATION_LIMIT) + else if (HWR_CanInterpolateModel(spr->mobj, md2->model)) { - if (durs > INTERPOLERATION_LIMIT) - durs = INTERPOLERATION_LIMIT; - // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation if (spr->mobj->frame & FF_ANIMATE) { - UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; - if (nextframe >= (UINT32)spr->mobj->state->var1) - nextframe = (spr->mobj->state->frame & FF_FRAMEMASK); - nextframe %= md2->model->header.numFrames; - next = &md2->model->frames[nextframe]; + nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextFrame >= (INT32)(spr->mobj->state->var1 + (spr->mobj->state->frame & FF_FRAMEMASK))) + nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK) % mod; } else { - if (spr->mobj->state->nextstate != S_NULL - && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite) - { - const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; - next = &md2->model->frames[nextframe]; - } + if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL + && !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_WAIT) && spr->mobj->state == &states[S_PLAY_STND])) + nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % mod; } } } - #undef INTERPOLERATION_LIMIT +#endif //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(spr->mobj->x); @@ -1519,7 +1158,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (sprframe->rotate) { - const fixed_t anglef = AngleFixed((spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle)); + fixed_t anglef = AngleFixed(spr->mobj->angle); + + if (spr->mobj->player) + anglef = AngleFixed(spr->mobj->player->drawangle); + else + anglef = AngleFixed(spr->mobj->angle); + p.angley = FIXED_TO_FLOAT(anglef); } else @@ -1528,21 +1173,50 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } - // rotsprite #ifdef ROTSPRITE + p.rollangle = 0.0f; + p.nightsroll = 0; if (spr->mobj->rollangle) { // do i have to support ROTANGLES here?????? fixed_t anglef = AngleFixed(spr->mobj->rollangle); - p.anglex = FIXED_TO_FLOAT(anglef); + p.rollangle = FIXED_TO_FLOAT(anglef); // pivot p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2); p.centery = FIXED_TO_FLOAT(spr->mobj->height/2); p.roll = true; + // NiGHTS-specific conditional + //if (spr->mobj->player) + { + statenum_t state = spr->mobj->state-states; + if ((state == S_PLAY_NIGHTS_FLY0) || (state == S_PLAY_NIGHTS_DRILL0)) + { + angle_t ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle); + if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right + p.nightsroll = 1; + else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left + p.nightsroll = -1; + } + } + } +#endif + + p.anglex = 0.0f; + +#ifdef USE_FTRANSFORM_ANGLEZ + // Slope rotation from Kart + 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); } - else #endif - p.anglex = 0.0f; color[0] = Surf.FlatColor.s.red; color[1] = Surf.FlatColor.s.green; @@ -1553,8 +1227,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); p.flip = atransform.flip; +#ifdef USE_FTRANSFORM_MIRROR + p.mirror = atransform.mirror; // from Kart +#endif - HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 24a5639330c12fe59ed1aae43ace60d54139c0f3..a5f5fc1174b1e0bc1e9a69fa8e5b75f0d78b9234 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -22,104 +22,7 @@ #define _HW_MD2_H_ #include "hw_glob.h" -#include "../info.h" - -// magic number "IDP2" or 844121161 -#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I') -// model version -#define MD2_VERSION 8 - -// magic number "IDP2" or 844121161 -#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I') -// model version -#define MD2_VERSION 8 - -#define MD2_MAX_TRIANGLES 8192 -#define MD2_MAX_VERTICES 4096 -#define MD2_MAX_TEXCOORDS 4096 -#define MD2_MAX_FRAMES 512 -#define MD2_MAX_SKINS 32 -#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128) - -#if defined(_MSC_VER) -#pragma pack(1) -#endif -typedef struct -{ - UINT32 magic; - UINT32 version; - UINT32 skinWidth; - UINT32 skinHeight; - UINT32 frameSize; - UINT32 numSkins; - UINT32 numVertices; - UINT32 numTexCoords; - UINT32 numTriangles; - UINT32 numGlCommands; - UINT32 numFrames; - UINT32 offsetSkins; - UINT32 offsetTexCoords; - UINT32 offsetTriangles; - UINT32 offsetFrames; - UINT32 offsetGlCommands; - UINT32 offsetEnd; -} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes - -typedef struct -{ - UINT8 vertex[3]; - UINT8 lightNormalIndex; -} ATTRPACK md2_alias_triangleVertex_t; - -typedef struct -{ - float vertex[3]; - float normal[3]; -} ATTRPACK md2_triangleVertex_t; - -typedef struct -{ - INT16 vertexIndices[3]; - INT16 textureIndices[3]; -} ATTRPACK md2_triangle_t; - -typedef struct -{ - INT16 s, t; -} ATTRPACK md2_textureCoordinate_t; - -typedef struct -{ - float scale[3]; - float translate[3]; - char name[16]; - md2_alias_triangleVertex_t alias_vertices[1]; -} ATTRPACK md2_alias_frame_t; - -typedef struct -{ - char name[16]; - md2_triangleVertex_t *vertices; -} ATTRPACK md2_frame_t; - -typedef char md2_skin_t[64]; - -typedef struct -{ - float s, t; - INT32 vertexIndex; -} ATTRPACK md2_glCommandVertex_t; - -typedef struct -{ - md2_header_t header; - md2_skin_t *skins; - md2_textureCoordinate_t *texCoords; - md2_triangle_t *triangles; - md2_frame_t *frames; - size_t *spr2frames; // size_t spr2frames[2*NUMPLAYERSPRITES][2]; - INT32 *glCommandBuffer; -} ATTRPACK md2_model_t; +#include "hw_model.h" #if defined(_MSC_VER) #pragma pack() @@ -130,7 +33,7 @@ typedef struct char filename[32]; float scale; float offset; - md2_model_t *model; + model_t *model; void *grpatch; void *blendgrpatch; boolean notfound; @@ -141,9 +44,9 @@ typedef struct extern md2_t md2_models[NUMSPRITES]; extern md2_t md2_playermodels[MAXSKINS]; -void HWR_InitMD2(void); -void HWR_DrawMD2(gr_vissprite_t *spr); -void HWR_AddPlayerMD2(INT32 skin); -void HWR_AddSpriteMD2(size_t spritenum); +void HWR_InitModels(void); +void HWR_DrawModel(gr_vissprite_t *spr); +void HWR_AddPlayerModel(INT32 skin); +void HWR_AddSpriteModel(size_t spritenum); #endif // _HW_MD2_H_ diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c new file mode 100644 index 0000000000000000000000000000000000000000..fed81e411dacc6b3f87ccb985cb49c0331381770 --- /dev/null +++ b/src/hardware/hw_md2load.c @@ -0,0 +1,576 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "../doomdef.h" +#include "hw_md2load.h" +#include "hw_model.h" +#include "../z_zone.h" + +#define NUMVERTEXNORMALS 162 + +// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and +// you'll have your normals. +float avertexnormals[NUMVERTEXNORMALS][3] = { +{-0.525731f, 0.000000f, 0.850651f}, +{-0.442863f, 0.238856f, 0.864188f}, +{-0.295242f, 0.000000f, 0.955423f}, +{-0.309017f, 0.500000f, 0.809017f}, +{-0.162460f, 0.262866f, 0.951056f}, +{0.000000f, 0.000000f, 1.000000f}, +{0.000000f, 0.850651f, 0.525731f}, +{-0.147621f, 0.716567f, 0.681718f}, +{0.147621f, 0.716567f, 0.681718f}, +{0.000000f, 0.525731f, 0.850651f}, +{0.309017f, 0.500000f, 0.809017f}, +{0.525731f, 0.000000f, 0.850651f}, +{0.295242f, 0.000000f, 0.955423f}, +{0.442863f, 0.238856f, 0.864188f}, +{0.162460f, 0.262866f, 0.951056f}, +{-0.681718f, 0.147621f, 0.716567f}, +{-0.809017f, 0.309017f, 0.500000f}, +{-0.587785f, 0.425325f, 0.688191f}, +{-0.850651f, 0.525731f, 0.000000f}, +{-0.864188f, 0.442863f, 0.238856f}, +{-0.716567f, 0.681718f, 0.147621f}, +{-0.688191f, 0.587785f, 0.425325f}, +{-0.500000f, 0.809017f, 0.309017f}, +{-0.238856f, 0.864188f, 0.442863f}, +{-0.425325f, 0.688191f, 0.587785f}, +{-0.716567f, 0.681718f, -0.147621f}, +{-0.500000f, 0.809017f, -0.309017f}, +{-0.525731f, 0.850651f, 0.000000f}, +{0.000000f, 0.850651f, -0.525731f}, +{-0.238856f, 0.864188f, -0.442863f}, +{0.000000f, 0.955423f, -0.295242f}, +{-0.262866f, 0.951056f, -0.162460f}, +{0.000000f, 1.000000f, 0.000000f}, +{0.000000f, 0.955423f, 0.295242f}, +{-0.262866f, 0.951056f, 0.162460f}, +{0.238856f, 0.864188f, 0.442863f}, +{0.262866f, 0.951056f, 0.162460f}, +{0.500000f, 0.809017f, 0.309017f}, +{0.238856f, 0.864188f, -0.442863f}, +{0.262866f, 0.951056f, -0.162460f}, +{0.500000f, 0.809017f, -0.309017f}, +{0.850651f, 0.525731f, 0.000000f}, +{0.716567f, 0.681718f, 0.147621f}, +{0.716567f, 0.681718f, -0.147621f}, +{0.525731f, 0.850651f, 0.000000f}, +{0.425325f, 0.688191f, 0.587785f}, +{0.864188f, 0.442863f, 0.238856f}, +{0.688191f, 0.587785f, 0.425325f}, +{0.809017f, 0.309017f, 0.500000f}, +{0.681718f, 0.147621f, 0.716567f}, +{0.587785f, 0.425325f, 0.688191f}, +{0.955423f, 0.295242f, 0.000000f}, +{1.000000f, 0.000000f, 0.000000f}, +{0.951056f, 0.162460f, 0.262866f}, +{0.850651f, -0.525731f, 0.000000f}, +{0.955423f, -0.295242f, 0.000000f}, +{0.864188f, -0.442863f, 0.238856f}, +{0.951056f, -0.162460f, 0.262866f}, +{0.809017f, -0.309017f, 0.500000f}, +{0.681718f, -0.147621f, 0.716567f}, +{0.850651f, 0.000000f, 0.525731f}, +{0.864188f, 0.442863f, -0.238856f}, +{0.809017f, 0.309017f, -0.500000f}, +{0.951056f, 0.162460f, -0.262866f}, +{0.525731f, 0.000000f, -0.850651f}, +{0.681718f, 0.147621f, -0.716567f}, +{0.681718f, -0.147621f, -0.716567f}, +{0.850651f, 0.000000f, -0.525731f}, +{0.809017f, -0.309017f, -0.500000f}, +{0.864188f, -0.442863f, -0.238856f}, +{0.951056f, -0.162460f, -0.262866f}, +{0.147621f, 0.716567f, -0.681718f}, +{0.309017f, 0.500000f, -0.809017f}, +{0.425325f, 0.688191f, -0.587785f}, +{0.442863f, 0.238856f, -0.864188f}, +{0.587785f, 0.425325f, -0.688191f}, +{0.688191f, 0.587785f, -0.425325f}, +{-0.147621f, 0.716567f, -0.681718f}, +{-0.309017f, 0.500000f, -0.809017f}, +{0.000000f, 0.525731f, -0.850651f}, +{-0.525731f, 0.000000f, -0.850651f}, +{-0.442863f, 0.238856f, -0.864188f}, +{-0.295242f, 0.000000f, -0.955423f}, +{-0.162460f, 0.262866f, -0.951056f}, +{0.000000f, 0.000000f, -1.000000f}, +{0.295242f, 0.000000f, -0.955423f}, +{0.162460f, 0.262866f, -0.951056f}, +{-0.442863f, -0.238856f, -0.864188f}, +{-0.309017f, -0.500000f, -0.809017f}, +{-0.162460f, -0.262866f, -0.951056f}, +{0.000000f, -0.850651f, -0.525731f}, +{-0.147621f, -0.716567f, -0.681718f}, +{0.147621f, -0.716567f, -0.681718f}, +{0.000000f, -0.525731f, -0.850651f}, +{0.309017f, -0.500000f, -0.809017f}, +{0.442863f, -0.238856f, -0.864188f}, +{0.162460f, -0.262866f, -0.951056f}, +{0.238856f, -0.864188f, -0.442863f}, +{0.500000f, -0.809017f, -0.309017f}, +{0.425325f, -0.688191f, -0.587785f}, +{0.716567f, -0.681718f, -0.147621f}, +{0.688191f, -0.587785f, -0.425325f}, +{0.587785f, -0.425325f, -0.688191f}, +{0.000000f, -0.955423f, -0.295242f}, +{0.000000f, -1.000000f, 0.000000f}, +{0.262866f, -0.951056f, -0.162460f}, +{0.000000f, -0.850651f, 0.525731f}, +{0.000000f, -0.955423f, 0.295242f}, +{0.238856f, -0.864188f, 0.442863f}, +{0.262866f, -0.951056f, 0.162460f}, +{0.500000f, -0.809017f, 0.309017f}, +{0.716567f, -0.681718f, 0.147621f}, +{0.525731f, -0.850651f, 0.000000f}, +{-0.238856f, -0.864188f, -0.442863f}, +{-0.500000f, -0.809017f, -0.309017f}, +{-0.262866f, -0.951056f, -0.162460f}, +{-0.850651f, -0.525731f, 0.000000f}, +{-0.716567f, -0.681718f, -0.147621f}, +{-0.716567f, -0.681718f, 0.147621f}, +{-0.525731f, -0.850651f, 0.000000f}, +{-0.500000f, -0.809017f, 0.309017f}, +{-0.238856f, -0.864188f, 0.442863f}, +{-0.262866f, -0.951056f, 0.162460f}, +{-0.864188f, -0.442863f, 0.238856f}, +{-0.809017f, -0.309017f, 0.500000f}, +{-0.688191f, -0.587785f, 0.425325f}, +{-0.681718f, -0.147621f, 0.716567f}, +{-0.442863f, -0.238856f, 0.864188f}, +{-0.587785f, -0.425325f, 0.688191f}, +{-0.309017f, -0.500000f, 0.809017f}, +{-0.147621f, -0.716567f, 0.681718f}, +{-0.425325f, -0.688191f, 0.587785f}, +{-0.162460f, -0.262866f, 0.951056f}, +{0.442863f, -0.238856f, 0.864188f}, +{0.162460f, -0.262866f, 0.951056f}, +{0.309017f, -0.500000f, 0.809017f}, +{0.147621f, -0.716567f, 0.681718f}, +{0.000000f, -0.525731f, 0.850651f}, +{0.425325f, -0.688191f, 0.587785f}, +{0.587785f, -0.425325f, 0.688191f}, +{0.688191f, -0.587785f, 0.425325f}, +{-0.955423f, 0.295242f, 0.000000f}, +{-0.951056f, 0.162460f, 0.262866f}, +{-1.000000f, 0.000000f, 0.000000f}, +{-0.850651f, 0.000000f, 0.525731f}, +{-0.955423f, -0.295242f, 0.000000f}, +{-0.951056f, -0.162460f, 0.262866f}, +{-0.864188f, 0.442863f, -0.238856f}, +{-0.951056f, 0.162460f, -0.262866f}, +{-0.809017f, 0.309017f, -0.500000f}, +{-0.864188f, -0.442863f, -0.238856f}, +{-0.951056f, -0.162460f, -0.262866f}, +{-0.809017f, -0.309017f, -0.500000f}, +{-0.681718f, 0.147621f, -0.716567f}, +{-0.681718f, -0.147621f, -0.716567f}, +{-0.850651f, 0.000000f, -0.525731f}, +{-0.688191f, 0.587785f, -0.425325f}, +{-0.587785f, 0.425325f, -0.688191f}, +{-0.425325f, 0.688191f, -0.587785f}, +{-0.425325f, -0.688191f, -0.587785f}, +{-0.587785f, -0.425325f, -0.688191f}, +{-0.688191f, -0.587785f, -0.425325f}, +}; + +typedef struct +{ + int ident; // A "magic number" that's used to identify the .md2 file + int version; // The version of the file, always 8 + int skinwidth; // Width of the skin(s) in pixels + int skinheight; // Height of the skin(s) in pixels + int framesize; // Size of each frame in bytes + int numSkins; // Number of skins with the model + int numXYZ; // Number of vertices in each frame + int numST; // Number of texture coordinates in each frame. + int numTris; // Number of triangles in each frame + int numGLcmds; // Number of dwords (4 bytes) in the gl command list. + int numFrames; // Number of frames + int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names. + int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates + int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles + int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames + int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands + int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize) +} md2header_t; + +typedef struct +{ + unsigned short meshIndex[3]; // indices into the array of vertices in each frames + unsigned short stIndex[3]; // indices into the array of texture coordinates +} md2triangle_t; + +typedef struct +{ + short s; + short t; +} md2texcoord_t; + +typedef struct +{ + unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal. + unsigned char lightNormalIndex; // Index to the array of normals +} md2vertex_t; + +typedef struct +{ + float scale[3]; // Used by the v member in the md2framePoint structure + float translate[3]; // Used by the v member in the md2framePoint structure + char name[16]; // Name of the frame +} md2frame_t; + +// Load the model +model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) +{ + FILE *f; + + model_t *retModel = NULL; + md2header_t *header; + + size_t fileLen; + int i, j; + size_t namelen; + char *texturefilename; + const char *texPos; + + char *buffer; + + const float WUNITS = 1.0f; + float dataScale = WUNITS; + + md2triangle_t *tris; + md2texcoord_t *texcoords; + md2frame_t *frames; + char *fname = NULL; + int foffset = 0; + + int t; + + // MD2 currently does not work with tinyframes, so force useFloat = true + // + // <SSNTails> + // the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float. + // + // MD2 is intended to be draw in triangle strips and fans + // not very compatible with a modern GL implementation, either + // so the idea would be to full float expand it, and put it in a vertex buffer object + // I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else. + // You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates + // I already have the decompression work done + + useFloat = true; + + f = fopen(fileName, "rb"); + + if (!f) + return NULL; + + retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); + + //size_t fileLen; + + //int i, j; + + //size_t namelen; + //char *texturefilename; + texPos = strchr(fileName, '/'); + + if (texPos) + { + texPos++; + namelen = strlen(texPos) + 1; + texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0); + strcpy(texturefilename, texPos); + } + else + { + namelen = strlen(fileName) + 1; + texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0); + strcpy(texturefilename, fileName); + } + + texturefilename[namelen - 2] = 'z'; + texturefilename[namelen - 3] = 'u'; + texturefilename[namelen - 4] = 'b'; + + // find length of file + fseek(f, 0, SEEK_END); + fileLen = ftell(f); + fseek(f, 0, SEEK_SET); + + // read in file + buffer = malloc(fileLen); + if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error + fclose(f); + + // get pointer to file header + header = (md2header_t*)buffer; + + retModel->numMeshes = 1; // MD2 only has one mesh + retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0); + retModel->meshes[0].numFrames = header->numFrames; + // const float WUNITS = 1.0f; + // float dataScale = WUNITS; + + // Tris and ST are simple structures that can be straight-copied + tris = (md2triangle_t*)&buffer[header->offsetTris]; + texcoords = (md2texcoord_t*)&buffer[header->offsetST]; + frames = (md2frame_t*)&buffer[header->offsetFrames]; + + retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0); + fname = retModel->framenames; + for (i = 0; i < header->numFrames; i++) + { + md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset]; + memcpy(fname, fr->name, 16); + foffset += sizeof(md2frame_t) + (sizeof(md2vertex_t) * header->numXYZ); + fname += 16; + } + + // Read in textures + retModel->numMaterials = header->numSkins; + + if (retModel->numMaterials <= 0) // Always at least one skin, duh + retModel->numMaterials = 1; + + retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0); + + // int t; + for (t = 0; t < retModel->numMaterials; t++) + { + retModel->materials[t].ambient[0] = 0.8f; + retModel->materials[t].ambient[1] = 0.8f; + retModel->materials[t].ambient[2] = 0.8f; + retModel->materials[t].ambient[3] = 1.0f; + retModel->materials[t].diffuse[0] = 0.8f; + retModel->materials[t].diffuse[1] = 0.8f; + retModel->materials[t].diffuse[2] = 0.8f; + retModel->materials[t].diffuse[3] = 1.0f; + retModel->materials[t].emissive[0] = 0.0f; + retModel->materials[t].emissive[1] = 0.0f; + retModel->materials[t].emissive[2] = 0.0f; + retModel->materials[t].emissive[3] = 1.0f; + retModel->materials[t].specular[0] = 0.0f; + retModel->materials[t].specular[1] = 0.0f; + retModel->materials[t].specular[2] = 0.0f; + retModel->materials[t].specular[3] = 1.0f; + retModel->materials[t].shininess = 0.0f; + retModel->materials[t].spheremap = false; + + /* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE); + + if (!systemSucks) + { + // Check for a normal map...?? + char openfilename[1024]; + char normalMapName[1024]; + strcpy(normalMapName, texturefilename); + size_t len = strlen(normalMapName); + char *ptr = &normalMapName[len]; + ptr--; // z + ptr--; // u + ptr--; // b + ptr--; // . + *ptr++ = '_'; + *ptr++ = 'n'; + *ptr++ = '.'; + *ptr++ = 'b'; + *ptr++ = 'u'; + *ptr++ = 'z'; + *ptr++ = '\0'; + + sprintf(openfilename, "%s/%s", "textures", normalMapName); + // Convert backslashes to forward slashes + for (int k = 0; k < 1024; k++) + { + if (openfilename[k] == '\0') + break; + + if (openfilename[k] == '\\') + openfilename[k] = '/'; + } + + Resource::resource_t *res = Resource::Open(openfilename); + if (res) + { + Resource::Close(res); + retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE); + } + }*/ + } + + retModel->meshes[0].numTriangles = header->numTris; + + if (!useFloat) // Decompress to MD3 'tinyframe' space + { + char *ptr; + + md2triangle_t *trisPtr; + unsigned short *indexptr; + float *uvptr; + + dataScale = 0.015624f; // 1 / 64.0f + retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0); + retModel->meshes[0].numVertices = header->numXYZ; + retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0); + + ptr = (char*)frames; + for (i = 0; i < header->numFrames; i++, ptr += header->framesize) + { + short *vertptr; + char *normptr; + // char *tanptr; + + md2vertex_t *vertex; + + md2frame_t *framePtr = (md2frame_t*)ptr; + retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0); + retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0); + + // if (retModel->materials[0].lightmap) + // retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag); + retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0); + + vertptr = retModel->meshes[0].tinyframes[i].vertices; + normptr = retModel->meshes[0].tinyframes[i].normals; + + // tanptr = retModel->meshes[0].tinyframes[i].tangents; + retModel->meshes[0].tinyframes[i].material = &retModel->materials[0]; + + framePtr++; // Advance to vertex list + vertex = (md2vertex_t*)framePtr; + framePtr--; + for (j = 0; j < header->numXYZ; j++, vertex++) + { + *vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale); + vertptr++; + *vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale); + vertptr++; + *vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale); + vertptr++; + + // Normal + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127); + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127); + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127); + } + } + + // This doesn't need to be done every frame! + trisPtr = tris; + indexptr = retModel->meshes[0].indices; + uvptr = (float*)retModel->meshes[0].uvs; + for (j = 0; j < header->numTris; j++, trisPtr++) + { + *indexptr = trisPtr->meshIndex[0]; + indexptr++; + *indexptr = trisPtr->meshIndex[1]; + indexptr++; + *indexptr = trisPtr->meshIndex[2]; + indexptr++; + + uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth; + uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight); + uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth; + uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight); + uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth; + uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); + } + } + else // Full float loading method + { + md2triangle_t *trisPtr; + float *uvptr; + + char *ptr; + + retModel->meshes[0].numVertices = header->numTris * 3; + retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0); + retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0); + + trisPtr = tris; + uvptr = retModel->meshes[0].uvs; + for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++) + { + *uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth; + *uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight); + *uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth; + *uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight); + *uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth; + *uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); + } + + ptr = (char*)frames; + for (i = 0; i < header->numFrames; i++, ptr += header->framesize) + { + float *vertptr, *normptr; + + md2vertex_t *vertex; + + md2frame_t *framePtr = (md2frame_t*)ptr; + retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0); + retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0); + // if (retModel->materials[0].lightmap) + // retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag); + //float *vertptr, *normptr; + normptr = (float*)retModel->meshes[0].frames[i].normals; + vertptr = (float*)retModel->meshes[0].frames[i].vertices; + trisPtr = tris; + + retModel->meshes[0].frames[i].material = &retModel->materials[0]; + + framePtr++; // Advance to vertex list + vertex = (md2vertex_t*)framePtr; + framePtr--; + for (j = 0; j < header->numTris; j++, trisPtr++) + { + *vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS; + vertptr++; + *vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS; + vertptr++; + *vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS; + vertptr++; + + *vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS; + vertptr++; + *vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS; + vertptr++; + *vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS; + vertptr++; + + *vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS; + vertptr++; + *vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS; + vertptr++; + *vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS; + vertptr++; + + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1]; + + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1]; + + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1]; + } + } + } + + free(buffer); + return retModel; +} diff --git a/src/hardware/hw_md2load.h b/src/hardware/hw_md2load.h new file mode 100644 index 0000000000000000000000000000000000000000..1662d6471eca6780ebd0213595b8985e4968da20 --- /dev/null +++ b/src/hardware/hw_md2load.h @@ -0,0 +1,19 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#ifndef _HW_MD2LOAD_H_ +#define _HW_MD2LOAD_H_ + +#include "hw_model.h" +#include "../doomtype.h" + +// Load the Model +model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat); + +#endif diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c new file mode 100644 index 0000000000000000000000000000000000000000..87931d27ba104e1f9a4109515f6497ad19bae453 --- /dev/null +++ b/src/hardware/hw_md3load.c @@ -0,0 +1,522 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "../doomdef.h" +#include "hw_md3load.h" +#include "hw_model.h" +#include "../z_zone.h" + +typedef struct +{ + int ident; // A "magic number" that's used to identify the .md3 file + int version; // The version of the file, always 15 + char name[64]; + int flags; + int numFrames; // Number of frames + int numTags; + int numSurfaces; + int numSkins; // Number of skins with the model + int offsetFrames; + int offsetTags; + int offsetSurfaces; + int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize) +} md3modelHeader; + +typedef struct +{ + float minBounds[3]; // First corner of the bounding box + float maxBounds[3]; // Second corner of the bounding box + float localOrigin[3]; // Local origin, usually (0, 0, 0) + float radius; // Radius of bounding sphere + char name[16]; // Name of frame +} md3Frame; + +typedef struct +{ + char name[64]; // Name of tag + float origin[3]; // Coordinates of tag + float axis[9]; // Orientation of tag object +} md3Tag; + +typedef struct +{ + int ident; + char name[64]; // Name of this surface + int flags; + int numFrames; // # of keyframes + int numShaders; // # of shaders + int numVerts; // # of vertices + int numTriangles; // # of triangles + int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start + int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start + int offsetST; // Relative offset from start of this struct to where the list of tex coords start + int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start + int offsetEnd; // Relative offset from start of this struct to where this surface ends +} md3Surface; + +typedef struct +{ + char name[64]; // Name of this shader + int shaderIndex; // Shader index number +} md3Shader; + +typedef struct +{ + int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object. +} md3Triangle; + +typedef struct +{ + float st[2]; +} md3TexCoord; + +typedef struct +{ + short x, y, z, n; +} md3Vertex; + +static float latlnglookup[256][256][3]; + +static void GetNormalFromLatLong(short latlng, float *out) +{ + float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)]; + + out[0] = *lookup++; + out[1] = *lookup++; + out[2] = *lookup++; +} + +#if 0 +static void NormalToLatLng(float *n, short *out) +{ + // Special cases + if (0.0f == n[0] && 0.0f == n[1]) + { + if (n[2] > 0.0f) + *out = 0; + else + *out = 128; + } + else + { + char x, y; + + x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f)); + y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f)); + + *out = (x << 8) + y; + } +} +#endif + +static inline void LatLngToNormal(short n, float *out) +{ + const float PI = (3.1415926535897932384626433832795f); + float lat = (float)(n >> 8); + float lng = (float)(n & 255); + + lat *= PI / 128.0f; + lng *= PI / 128.0f; + + out[0] = cosf(lat) * sinf(lng); + out[1] = sinf(lat) * sinf(lng); + out[2] = cosf(lng); +} + +static void LatLngInit(void) +{ + int i, j; + for (i = 0; i < 256; i++) + { + for (j = 0; j < 256; j++) + LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]); + } +} + +static boolean latlnginit = false; + +model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) +{ + const float WUNITS = 1.0f; + model_t *retModel = NULL; + md3Frame *frames = NULL; + char *fname = NULL; + md3modelHeader *mdh; + long fileLen; + long fileReadLen; + char *buffer; + int surfEnd; + int i, t; + int matCount; + FILE *f; + + if (!latlnginit) + { + LatLngInit(); + latlnginit = true; + } + + f = fopen(fileName, "rb"); + + if (!f) + return NULL; + + retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); + + // find length of file + fseek(f, 0, SEEK_END); + fileLen = ftell(f); + fseek(f, 0, SEEK_SET); + + // read in file + buffer = malloc(fileLen); + fileReadLen = fread(buffer, fileLen, 1, f); + fclose(f); + + (void)fileReadLen; // intentionally ignore return value, per buildbot + + // get pointer to file header + mdh = (md3modelHeader*)buffer; + + retModel->numMeshes = mdh->numSurfaces; + + retModel->numMaterials = 0; + surfEnd = 0; + for (i = 0; i < mdh->numSurfaces; i++) + { + md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces]; + surfEnd += mdS->offsetEnd; + + retModel->numMaterials += mdS->numShaders; + } + + // Initialize materials + if (retModel->numMaterials <= 0) // Always at least one skin, duh + retModel->numMaterials = 1; + + retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0); + + for (t = 0; t < retModel->numMaterials; t++) + { + retModel->materials[t].ambient[0] = 0.3686f; + retModel->materials[t].ambient[1] = 0.3684f; + retModel->materials[t].ambient[2] = 0.3684f; + retModel->materials[t].ambient[3] = 1.0f; + retModel->materials[t].diffuse[0] = 0.8863f; + retModel->materials[t].diffuse[1] = 0.8850f; + retModel->materials[t].diffuse[2] = 0.8850f; + retModel->materials[t].diffuse[3] = 1.0f; + retModel->materials[t].emissive[0] = 0.0f; + retModel->materials[t].emissive[1] = 0.0f; + retModel->materials[t].emissive[2] = 0.0f; + retModel->materials[t].emissive[3] = 1.0f; + retModel->materials[t].specular[0] = 0.4902f; + retModel->materials[t].specular[1] = 0.4887f; + retModel->materials[t].specular[2] = 0.4887f; + retModel->materials[t].specular[3] = 1.0f; + retModel->materials[t].shininess = 25.0f; + retModel->materials[t].spheremap = false; + } + + retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0); + + frames = (md3Frame*)&buffer[mdh->offsetFrames]; + retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0); + fname = retModel->framenames; + for (i = 0; i < mdh->numFrames; i++) + { + memcpy(fname, frames->name, 16); + fname += 16; + frames++; + } + + matCount = 0; + for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++) + { + int j; + md3Shader *mdShader; + md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd]; + surfEnd += mdS->offsetEnd; + + mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders); + + for (j = 0; j < mdS->numShaders; j++, matCount++) + { + size_t len = strlen(mdShader[j].name); + mdShader[j].name[len-1] = 'z'; + mdShader[j].name[len-2] = 'u'; + mdShader[j].name[len-3] = 'b'; + + // Load material +/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE); + + if (!systemSucks) + { + // Check for a normal map...?? + char openfilename[1024]; + char normalMapName[1024]; + strcpy(normalMapName, mdShader[j].name); + len = strlen(normalMapName); + char *ptr = &normalMapName[len]; + ptr--; // z + ptr--; // u + ptr--; // b + ptr--; // . + *ptr++ = '_'; + *ptr++ = 'n'; + *ptr++ = '.'; + *ptr++ = 'b'; + *ptr++ = 'u'; + *ptr++ = 'z'; + *ptr++ = '\0'; + + sprintf(openfilename, "%s/%s", "textures", normalMapName); + // Convert backslashes to forward slashes + for (int k = 0; k < 1024; k++) + { + if (openfilename[k] == '\0') + break; + + if (openfilename[k] == '\\') + openfilename[k] = '/'; + } + + Resource::resource_t *res = Resource::Open(openfilename); + if (res) + { + Resource::Close(res); + retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE); + } + }*/ + } + + retModel->meshes[i].numFrames = mdS->numFrames; + retModel->meshes[i].numTriangles = mdS->numTriangles; + + if (!useFloat) // 'tinyframe' mode with indices + { + float tempNormal[3]; + float *uvptr; + md3TexCoord *mdST; + unsigned short *indexptr; + md3Triangle *mdT; + + retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0); + retModel->meshes[i].numVertices = mdS->numVerts; + retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0); + for (j = 0; j < mdS->numFrames; j++) + { + short *vertptr; + char *normptr; + // char *tanptr; + int k; + md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex))); + retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0); + retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0); + +// if (retModel->materials[0].lightmap) +// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag); + retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0); + vertptr = retModel->meshes[i].tinyframes[j].vertices; + normptr = retModel->meshes[i].tinyframes[j].normals; + +// tanptr = retModel->meshes[i].tinyframes[j].tangents; + retModel->meshes[i].tinyframes[j].material = &retModel->materials[i]; + + for (k = 0; k < mdS->numVerts; k++) + { + // Vertex + *vertptr = mdV[k].x; + vertptr++; + *vertptr = mdV[k].z; + vertptr++; + *vertptr = 1.0f - mdV[k].y; + vertptr++; + + // Normal + GetNormalFromLatLong(mdV[k].n, tempNormal); + *normptr = (char)(tempNormal[0] * 127); + normptr++; + *normptr = (char)(tempNormal[2] * 127); + normptr++; + *normptr = (char)(tempNormal[1] * 127); + normptr++; + } + } + + uvptr = (float*)retModel->meshes[i].uvs; + mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); + for (j = 0; j < mdS->numVerts; j++) + { + *uvptr = mdST[j].st[0]; + uvptr++; + *uvptr = mdST[j].st[1]; + uvptr++; + } + + indexptr = retModel->meshes[i].indices; + mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + for (j = 0; j < mdS->numTriangles; j++, mdT++) + { + // Indices + *indexptr = (unsigned short)mdT->index[0]; + indexptr++; + *indexptr = (unsigned short)mdT->index[1]; + indexptr++; + *indexptr = (unsigned short)mdT->index[2]; + indexptr++; + } + } + else // Traditional full-float loading method + { + float dataScale = 0.015624f * WUNITS; + float tempNormal[3]; + md3TexCoord *mdST; + md3Triangle *mdT; + float *uvptr; + int k; + + retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts; + retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0); + retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0); + + for (j = 0; j < mdS->numFrames; j++) + { + float *vertptr; + float *normptr; + md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex))); + retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0); + retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0); +// if (retModel->materials[i].lightmap) +// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag); + vertptr = retModel->meshes[i].frames[j].vertices; + normptr = retModel->meshes[i].frames[j].normals; + retModel->meshes[i].frames[j].material = &retModel->materials[i]; + + mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + + for (k = 0; k < mdS->numTriangles; k++) + { + // Vertex 1 + *vertptr = mdV[mdT->index[0]].x * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[0]].z * dataScale; + vertptr++; + *vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal); + *normptr = tempNormal[0]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[1]; + normptr++; + + // Vertex 2 + *vertptr = mdV[mdT->index[1]].x * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[1]].z * dataScale; + vertptr++; + *vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal); + *normptr = tempNormal[0]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[1]; + normptr++; + + // Vertex 3 + *vertptr = mdV[mdT->index[2]].x * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[2]].z * dataScale; + vertptr++; + *vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal); + *normptr = tempNormal[0]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[1]; + normptr++; + + mdT++; // Advance to next triangle + } + } + + mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); + uvptr = (float*)retModel->meshes[i].uvs; + mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + + for (k = 0; k < mdS->numTriangles; k++) + { + *uvptr = mdST[mdT->index[0]].st[0]; + uvptr++; + *uvptr = mdST[mdT->index[0]].st[1]; + uvptr++; + + *uvptr = mdST[mdT->index[1]].st[0]; + uvptr++; + *uvptr = mdST[mdT->index[1]].st[1]; + uvptr++; + + *uvptr = mdST[mdT->index[2]].st[0]; + uvptr++; + *uvptr = mdST[mdT->index[2]].st[1]; + uvptr++; + + mdT++; // Advance to next triangle + } + } + } + /* + // Tags? + retModel->numTags = mdh->numTags; + retModel->maxNumFrames = mdh->numFrames; + retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag); + md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags]; + tag_t *curTag = retModel->tags; + for (i = 0; i < mdh->numFrames; i++) + { + int j; + for (j = 0; j < retModel->numTags; j++, mdTag++) + { + strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char)); + curTag->transform.m[0][0] = mdTag->axis[0]; + curTag->transform.m[0][1] = mdTag->axis[1]; + curTag->transform.m[0][2] = mdTag->axis[2]; + curTag->transform.m[1][0] = mdTag->axis[3]; + curTag->transform.m[1][1] = mdTag->axis[4]; + curTag->transform.m[1][2] = mdTag->axis[5]; + curTag->transform.m[2][0] = mdTag->axis[6]; + curTag->transform.m[2][1] = mdTag->axis[7]; + curTag->transform.m[2][2] = mdTag->axis[8]; + curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS; + curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS; + curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS; + curTag->transform.m[3][3] = 1.0f; + + Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis); + curTag++; + } + }*/ + + + free(buffer); + + return retModel; +} diff --git a/src/hardware/hw_md3load.h b/src/hardware/hw_md3load.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e0522ff6bf2e6e43c96021ab758ca64ae7b45b --- /dev/null +++ b/src/hardware/hw_md3load.h @@ -0,0 +1,19 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#ifndef _HW_MD3LOAD_H_ +#define _HW_MD3LOAD_H_ + +#include "hw_model.h" +#include "../doomtype.h" + +// Load the Model +model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat); + +#endif diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c new file mode 100644 index 0000000000000000000000000000000000000000..ac73f8acac4b577f1ca18bd077e8bba837f320d8 --- /dev/null +++ b/src/hardware/hw_model.c @@ -0,0 +1,737 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#include "../doomdef.h" +#include "../doomtype.h" +#include "../info.h" +#include "../z_zone.h" +#include "hw_model.h" +#include "hw_md2load.h" +#include "hw_md3load.h" +#include "hw_md2.h" +#include "u_list.h" +#include <string.h> + +static float PI = (3.1415926535897932384626433832795f); +static float U_Deg2Rad(float deg) +{ + return deg * ((float)PI / 180.0f); +} + +vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f }; +vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f }; +vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f }; + +void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle) +{ + float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca; + + angle = U_Deg2Rad(angle); + + // Rotate the point (x,y,z) around the vector (u,v,w) + ux = axisVec->x * rotVec->x; + uy = axisVec->x * rotVec->y; + uz = axisVec->x * rotVec->z; + vx = axisVec->y * rotVec->x; + vy = axisVec->y * rotVec->y; + vz = axisVec->y * rotVec->z; + wx = axisVec->z * rotVec->x; + wy = axisVec->z * rotVec->y; + wz = axisVec->z * rotVec->z; + sa = sinf(angle); + ca = cosf(angle); + + rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa; + rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa; + rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa; +} + +void UnloadModel(model_t *model) +{ + // Wouldn't it be great if C just had destructors? + int i; + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < mesh->numFrames; j++) + { + if (mesh->frames[j].normals) + Z_Free(mesh->frames[j].normals); + + if (mesh->frames[j].tangents) + Z_Free(mesh->frames[j].tangents); + + if (mesh->frames[j].vertices) + Z_Free(mesh->frames[j].vertices); + + if (mesh->frames[j].colors) + Z_Free(mesh->frames[j].colors); + } + + Z_Free(mesh->frames); + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < mesh->numFrames; j++) + { + if (mesh->tinyframes[j].normals) + Z_Free(mesh->tinyframes[j].normals); + + if (mesh->tinyframes[j].tangents) + Z_Free(mesh->tinyframes[j].tangents); + + if (mesh->tinyframes[j].vertices) + Z_Free(mesh->tinyframes[j].vertices); + } + + if (mesh->indices) + Z_Free(mesh->indices); + + Z_Free(mesh->tinyframes); + } + + if (mesh->uvs) + Z_Free(mesh->uvs); + + if (mesh->lightuvs) + Z_Free(mesh->lightuvs); + } + + if (model->meshes) + Z_Free(model->meshes); + + if (model->tags) + Z_Free(model->tags); + + if (model->materials) + Z_Free(model->materials); + + DeleteVBOs(model); + Z_Free(model); +} + +tag_t *GetTagByName(model_t *model, char *name, int frame) +{ + if (frame < model->maxNumFrames) + { + tag_t *iterator = &model->tags[frame * model->numTags]; + + int i; + for (i = 0; i < model->numTags; i++) + { + if (!stricmp(iterator[i].name, name)) + return &iterator[i]; + } + } + + return NULL; +} + +// +// LoadModel +// +// Load a model and +// convert it to the +// internal format. +// +model_t *LoadModel(const char *filename, int ztag) +{ + model_t *model; + + // What type of file? + const char *extension = NULL; + int i; + for (i = (int)strlen(filename)-1; i >= 0; i--) + { + if (filename[i] != '.') + continue; + + extension = &filename[i]; + break; + } + + if (!extension) + { + CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename); + return NULL; + } + + if (!strcmp(extension, ".md3")) + { + if (!(model = MD3_LoadModel(filename, ztag, false))) + return NULL; + } + else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats + { + if (!(model = MD3_LoadModel(filename, ztag, true))) + return NULL; + } + else if (!strcmp(extension, ".md2")) + { + if (!(model = MD2_LoadModel(filename, ztag, false))) + return NULL; + } + else if (!strcmp(extension, ".md2s")) + { + if (!(model = MD2_LoadModel(filename, ztag, true))) + return NULL; + } + else + { + CONS_Printf("Unknown model format: %s\n", extension); + return NULL; + } + + model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0); + strcpy(model->mdlFilename, filename); + + Optimize(model); + GeneratePolygonNormals(model, ztag); + LoadModelSprite2(model); + if (!model->spr2frames) + LoadModelInterpolationSettings(model); + + // Default material properties + for (i = 0 ; i < model->numMaterials; i++) + { + material_t *material = &model->materials[i]; + material->ambient[0] = 0.7686f; + material->ambient[1] = 0.7686f; + material->ambient[2] = 0.7686f; + material->ambient[3] = 1.0f; + material->diffuse[0] = 0.5863f; + material->diffuse[1] = 0.5863f; + material->diffuse[2] = 0.5863f; + material->diffuse[3] = 1.0f; + material->specular[0] = 0.4902f; + material->specular[1] = 0.4902f; + material->specular[2] = 0.4902f; + material->specular[3] = 1.0f; + material->shininess = 25.0f; + } + + return model; +} + +void HWR_ReloadModels(void) +{ + size_t i; + INT32 s; + + for (s = 0; s < MAXSKINS; s++) + { + if (md2_playermodels[s].model) + LoadModelSprite2(md2_playermodels[s].model); + } + + for (i = 0; i < NUMSPRITES; i++) + { + if (md2_models[i].model) + LoadModelInterpolationSettings(md2_models[i].model); + } +} + +void LoadModelInterpolationSettings(model_t *model) +{ + INT32 i; + INT32 numframes = model->meshes[0].numFrames; + char *framename = model->framenames; + + if (!framename) + return; + + #define GET_OFFSET \ + memcpy(&interpolation_flag, framename + offset, 2); \ + model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)); + + for (i = 0; i < numframes; i++) + { + int offset = (strlen(framename) - 4); + char interpolation_flag[3]; + memset(&interpolation_flag, 0x00, 3); + + // find the +i on the frame name + // ANIM+i00 + // so the offset is (frame name length - 4) + GET_OFFSET; + + // maybe the frame had three digits? + // ANIM+i000 + // so the offset is (frame name length - 5) + if (!model->interpolate[i]) + { + offset--; + GET_OFFSET; + } + + framename += 16; + } + + #undef GET_OFFSET +} + +void LoadModelSprite2(model_t *model) +{ + INT32 i; + modelspr2frames_t *spr2frames = NULL; + INT32 numframes = model->meshes[0].numFrames; + char *framename = model->framenames; + + if (!framename) + return; + + for (i = 0; i < numframes; i++) + { + char prefix[6]; + char name[5]; + char interpolation_flag[3]; + char framechars[4]; + UINT8 frame = 0; + UINT8 spr2idx; + boolean interpolate = false; + + memset(&prefix, 0x00, 6); + memset(&name, 0x00, 5); + memset(&interpolation_flag, 0x00, 3); + memset(&framechars, 0x00, 4); + + if (strlen(framename) >= 9) + { + boolean super; + char *modelframename = framename; + memcpy(&prefix, modelframename, 5); + modelframename += 5; + memcpy(&name, modelframename, 4); + modelframename += 4; + // Oh look + memcpy(&interpolation_flag, modelframename, 2); + if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)) + { + interpolate = true; + modelframename += 2; + } + memcpy(&framechars, modelframename, 3); + + if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5))) + { + spr2idx = 0; + while (spr2idx < free_spr2) + { + if (!memcmp(spr2names[spr2idx], name, 4)) + { + if (!spr2frames) + spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); + if (super) + spr2idx |= FF_SPR2SUPER; + if (framechars[0]) + { + frame = atoi(framechars); + if (spr2frames[spr2idx].numframes < frame+1) + spr2frames[spr2idx].numframes = frame+1; + } + else + { + frame = spr2frames[spr2idx].numframes; + spr2frames[spr2idx].numframes++; + } + spr2frames[spr2idx].frames[frame] = i; + spr2frames[spr2idx].interpolate = interpolate; + break; + } + spr2idx++; + } + } + } + + framename += 16; + } + + if (model->spr2frames) + Z_Free(model->spr2frames); + model->spr2frames = spr2frames; +} + +// +// GenerateVertexNormals +// +// Creates a new normal for a vertex using the average of all of the polygons it belongs to. +// +void GenerateVertexNormals(model_t *model) +{ + int i; + for (i = 0; i < model->numMeshes; i++) + { + int j; + + mesh_t *mesh = &model->meshes[i]; + + if (!mesh->frames) + continue; + + for (j = 0; j < mesh->numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + int memTag = PU_STATIC; + float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0); + int k; + float *vertPtr = frame->vertices; + float *oldNormals; + + M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3); + +/* if (!systemSucks) + { + memTag = Z_GetTag(frame->tangents); + float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag); + M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3); + }*/ + + for (k = 0; k < mesh->numVertices; k++) + { + float x, y, z; + int vCount = 0; + vector_t normal; + int l; + float *testPtr = frame->vertices; + + x = *vertPtr++; + y = *vertPtr++; + z = *vertPtr++; + + normal.x = normal.y = normal.z = 0; + + for (l = 0; l < mesh->numVertices; l++) + { + float testX, testY, testZ; + testX = *testPtr++; + testY = *testPtr++; + testZ = *testPtr++; + + if (fabsf(x - testX) > FLT_EPSILON + || fabsf(y - testY) > FLT_EPSILON + || fabsf(z - testZ) > FLT_EPSILON) + continue; + + // Found a vertex match! Add it... + normal.x += frame->normals[3 * l + 0]; + normal.y += frame->normals[3 * l + 1]; + normal.z += frame->normals[3 * l + 2]; + vCount++; + } + + if (vCount > 1) + { +// Vector::Normalize(&normal); + newNormals[3 * k + 0] = (float)normal.x; + newNormals[3 * k + 1] = (float)normal.y; + newNormals[3 * k + 2] = (float)normal.z; + +/* if (!systemSucks) + { + Vector::vector_t tangent; + Vector::Tangent(&normal, &tangent); + newTangents[3 * k + 0] = tangent.x; + newTangents[3 * k + 1] = tangent.y; + newTangents[3 * k + 2] = tangent.z; + }*/ + } + } + + oldNormals = frame->normals; + frame->normals = newNormals; + Z_Free(oldNormals); + +/* if (!systemSucks) + { + float *oldTangents = frame->tangents; + frame->tangents = newTangents; + Z_Free(oldTangents); + }*/ + } + } +} + +typedef struct materiallist_s +{ + struct materiallist_s *next; + struct materiallist_s *prev; + material_t *material; +} materiallist_t; + +static boolean AddMaterialToList(materiallist_t **head, material_t *material) +{ + materiallist_t *node, *newMatNode; + for (node = *head; node; node = node->next) + { + if (node->material == material) + return false; + } + + // Didn't find it, so add to the list + newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0); + newMatNode->material = material; + ListAdd(newMatNode, (listitem_t**)head); + return true; +} + +// +// Optimize +// +// Groups triangles from meshes in the model +// Only works for models with 1 frame +// +void Optimize(model_t *model) +{ + int numMeshes = 0; + int i; + materiallist_t *matListHead = NULL; + int memTag; + mesh_t *newMeshes; + materiallist_t *node; + + if (model->numMeshes <= 1) + return; // No need + + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *curMesh = &model->meshes[i]; + + if (curMesh->numFrames > 1) + return; // Can't optimize models with > 1 frame + + if (!curMesh->frames) + return; // Don't optimize tinyframe models (no need) + + // We are condensing to 1 mesh per material, so + // the # of materials we use will be the new + // # of meshes + if (AddMaterialToList(&matListHead, curMesh->frames[0].material)) + numMeshes++; + } + + memTag = PU_STATIC; + newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0); + + i = 0; + for (node = matListHead; node; node = node->next) + { + material_t *curMat = node->material; + mesh_t *newMesh = &newMeshes[i]; + mdlframe_t *curFrame; + int uvCount; + int vertCount; + int colorCount; + + // Find all triangles with this material and count them + int numTriangles = 0; + int j; + for (j = 0; j < model->numMeshes; j++) + { + mesh_t *curMesh = &model->meshes[j]; + + if (curMesh->frames[0].material == curMat) + numTriangles += curMesh->numTriangles; + } + + newMesh->numFrames = 1; + newMesh->numTriangles = numTriangles; + newMesh->numVertices = numTriangles * 3; + newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0); +// if (node->material->lightmap) +// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0); + newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0); + curFrame = &newMesh->frames[0]; + + curFrame->material = curMat; + curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); +// if (!systemSucks) +// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); + curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); + curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0); + + // Now traverse the meshes of the model, adding in + // vertices/normals/uvs that match the current material + uvCount = 0; + vertCount = 0; + colorCount = 0; + for (j = 0; j < model->numMeshes; j++) + { + mesh_t *curMesh = &model->meshes[j]; + + if (curMesh->frames[0].material == curMat) + { + float *dest; + float *src; + char *destByte; + char *srcByte; + + M_Memcpy(&newMesh->uvs[uvCount], + curMesh->uvs, + sizeof(float)*2*curMesh->numTriangles*3); + +/* if (node->material->lightmap) + { + M_Memcpy(&newMesh->lightuvs[uvCount], + curMesh->lightuvs, + sizeof(float)*2*curMesh->numTriangles*3); + }*/ + uvCount += 2*curMesh->numTriangles*3; + + dest = (float*)newMesh->frames[0].vertices; + src = (float*)curMesh->frames[0].vertices; + M_Memcpy(&dest[vertCount], + src, + sizeof(float)*3*curMesh->numTriangles*3); + + dest = (float*)newMesh->frames[0].normals; + src = (float*)curMesh->frames[0].normals; + M_Memcpy(&dest[vertCount], + src, + sizeof(float)*3*curMesh->numTriangles*3); + +/* if (!systemSucks) + { + dest = (float*)newMesh->frames[0].tangents; + src = (float*)curMesh->frames[0].tangents; + M_Memcpy(&dest[vertCount], + src, + sizeof(float)*3*curMesh->numTriangles*3); + }*/ + + vertCount += 3 * curMesh->numTriangles * 3; + + destByte = (char*)newMesh->frames[0].colors; + srcByte = (char*)curMesh->frames[0].colors; + + if (srcByte) + { + M_Memcpy(&destByte[colorCount], + srcByte, + sizeof(char)*4*curMesh->numTriangles*3); + } + else + { + memset(&destByte[colorCount], + 255, + sizeof(char)*4*curMesh->numTriangles*3); + } + + colorCount += 4 * curMesh->numTriangles * 3; + } + } + + i++; + } + + CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes); + model->meshes = newMeshes; + model->numMeshes = numMeshes; +} + +void GeneratePolygonNormals(model_t *model, int ztag) +{ + int i; + for (i = 0; i < model->numMeshes; i++) + { + int j; + mesh_t *mesh = &model->meshes[i]; + + if (!mesh->frames) + continue; + + for (j = 0; j < mesh->numFrames; j++) + { + int k; + mdlframe_t *frame = &mesh->frames[j]; + const float *vertices = frame->vertices; + vector_t *polyNormals; + + frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0); + + polyNormals = frame->polyNormals; + + for (k = 0; k < mesh->numTriangles; k++) + { +// Vector::Normal(vertices, polyNormals); + vertices += 3 * 3; + polyNormals++; + } + } + } +} + +// +// Reload +// +// Reload VBOs +// +#if 0 +static void Reload(void) +{ +/* model_t *node; + for (node = modelHead; node; node = node->next) + { + int i; + for (i = 0; i < node->numMeshes; i++) + { + mesh_t *mesh = &node->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < mesh->numFrames; j++) + CreateVBO(mesh, &mesh->frames[j]); + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < mesh->numFrames; j++) + CreateVBO(mesh, &mesh->tinyframes[j]); + } + } + }*/ +} +#endif + +void DeleteVBOs(model_t *model) +{ + (void)model; +/* for (int i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + for (int j = 0; j < mesh->numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + if (!frame->vboID) + continue; + bglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + } + } + else if (mesh->tinyframes) + { + for (int j = 0; j < mesh->numFrames; j++) + { + tinyframe_t *frame = &mesh->tinyframes[j]; + if (!frame->vboID) + continue; + bglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + } + } + }*/ +} diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h new file mode 100644 index 0000000000000000000000000000000000000000..2a5240bdefbda6320fa2411b451a5bf86408124e --- /dev/null +++ b/src/hardware/hw_model.h @@ -0,0 +1,121 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#ifndef _HW_MODEL_H_ +#define _HW_MODEL_H_ + +#include "../doomtype.h" + +typedef struct +{ + float x, y, z; +} vector_t; + +extern vector_t vectorXaxis; +extern vector_t vectorYaxis; +extern vector_t vectorZaxis; + +void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle); + +typedef struct +{ + float ambient[4], diffuse[4], specular[4], emissive[4]; + float shininess; + boolean spheremap; +// Texture::texture_t *texture; +// Texture::texture_t *lightmap; +} material_t; + +typedef struct +{ + material_t *material; // Pointer to the allocated 'materials' list in model_t + float *vertices; + float *normals; + float *tangents; + char *colors; + unsigned int vboID; + vector_t *polyNormals; +} mdlframe_t; + +typedef struct +{ + material_t *material; + short *vertices; + char *normals; + char *tangents; + unsigned int vboID; +} tinyframe_t; + +// Equivalent to MD3's many 'surfaces' +typedef struct mesh_s +{ + int numVertices; + int numTriangles; + + float *uvs; + float *lightuvs; + + int numFrames; + mdlframe_t *frames; + tinyframe_t *tinyframes; + unsigned short *indices; +} mesh_t; + +typedef struct tag_s +{ + char name[64]; +// matrix_t transform; +} tag_t; + +#define MODEL_INTERPOLATION_FLAG "+i" + +typedef struct +{ + INT32 frames[256]; + UINT8 numframes; + boolean interpolate; +} modelspr2frames_t; + +typedef struct model_s +{ + int maxNumFrames; + + int numMaterials; + material_t *materials; + int numMeshes; + mesh_t *meshes; + int numTags; + tag_t *tags; + + char *mdlFilename; + boolean unloaded; + + char *framenames; + boolean interpolate[256]; + modelspr2frames_t *spr2frames; +} model_t; + +extern int numModels; +extern model_t *modelHead; + +void HWR_ReloadModels(void); + +tag_t *GetTagByName(model_t *model, char *name, int frame); +model_t *LoadModel(const char *filename, int ztag); +void UnloadModel(model_t *model); +void Optimize(model_t *model); +void LoadModelInterpolationSettings(model_t *model); +void LoadModelSprite2(model_t *model); +void GenerateVertexNormals(model_t *model); +void GeneratePolygonNormals(model_t *model, int ztag); +void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame); +void CreateVBO(mesh_t *mesh, mdlframe_t *frame); +void DeleteVBOs(model_t *model); + +#endif diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index eb9a31a7d7f1e909d72e88cc5bc3c166471b73ab..562afe9989e0908f046ece44abe2fcf22d2fa439 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -347,13 +347,6 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD; DBG_Printf("oglflags : 0x%X\n", oglflags); -#ifdef USE_PALETTED_TEXTURE - if (isExtAvailable("GL_EXT_paletted_texture",gl_extensions)) - glColorTableEXT = GetGLFunc("glColorTableEXT"); - else - glColorTableEXT = NULL; -#endif - #ifdef USE_WGL_SWAP if (isExtAvailable("WGL_EXT_swap_control",gl_extensions)) wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT"); @@ -582,19 +575,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma) myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255); myPaletteData[i].s.alpha = pal[i].s.alpha; } -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT) - { - for (i = 0; i < 256; i++) - { - palette_tex[3*i+0] = pal[i].s.red; - palette_tex[3*i+1] = pal[i].s.green; - palette_tex[3*i+2] = pal[i].s.blue; - } - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - } -#endif - // on a chang� de palette, il faut recharger toutes les textures + + // on a palette change, you have to reload all of the textures Flush(); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 0c856a60aec9cc6a1715cad93a311aa1b3814d4f..4388214ec686d515ae61bb09bec158e9bb3bc28e 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -29,13 +29,10 @@ #include <stdarg.h> #include <math.h> -#ifndef SHUFFLE -#define SHUFFLE -#endif #include "r_opengl.h" +#include "r_vbo.h" #if defined (HWRENDER) && !defined (NOROPENGL) -// for KOS: GL_TEXTURE_ENV, glAlphaFunc, glColorMask, glPolygonOffset, glReadPixels, GL_ALPHA_TEST, GL_POLYGON_OFFSET_FILL struct GLRGBAFloat { @@ -45,6 +42,7 @@ struct GLRGBAFloat GLfloat alpha; }; typedef struct GLRGBAFloat GLRGBAFloat; +static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== // CONSTANTS @@ -68,8 +66,10 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; static GLuint NextTexAvail = FIRST_TEX_AVAIL; static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; +#if 0 static GLuint pal_col = 0; static FRGBAFloat const_pal_col; +#endif static FBITFIELD CurrentPolyFlags; static FTextureInfo* gr_cachetail = NULL; @@ -90,26 +90,20 @@ static FTransform md2_transform; const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) -static GLdouble modelMatrix[16]; -static GLdouble projMatrix[16]; +static GLfloat modelMatrix[16]; +static GLfloat projMatrix[16]; static GLint viewport[4]; - -#ifdef USE_PALETTED_TEXTURE - PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; - GLubyte palette_tex[256*3]; -#endif - // Yay for arbitrary numbers! NextTexAvail is buggy for some reason. // Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing // flush all of the stored textures, leaving them unavailable at times such as between levels // These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs // can know when the textures aren't there, as textures are always considered resident in their virtual memory // TODO: Store them in a more normal way -#define SCRTEX_SCREENTEXTURE 65535 -#define SCRTEX_STARTSCREENWIPE 65534 -#define SCRTEX_ENDSCREENWIPE 65533 -#define SCRTEX_FINALSCREENTEXTURE 65532 +#define SCRTEX_SCREENTEXTURE 4294967295U +#define SCRTEX_STARTSCREENWIPE 4294967294U +#define SCRTEX_ENDSCREENWIPE 4294967293U +#define SCRTEX_FINALSCREENTEXTURE 4294967292U static GLuint screentexture = 0; static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; @@ -161,9 +155,6 @@ float byteasfloat(UINT8 fbyte) static I_Error_t I_Error_GL = NULL; -static boolean gl13 = false; // whether we can use opengl 1.3 functions - - // -----------------+ // DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing @@ -194,14 +185,14 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglAlphaFunc glAlphaFunc #define pglBlendFunc glBlendFunc #define pglCullFace glCullFace -#define pglPolygonMode glPolygonMode #define pglPolygonOffset glPolygonOffset #define pglScissor glScissor #define pglEnable glEnable #define pglDisable glDisable -#define pglGetDoublev glGetDoublev +#define pglGetFloatv glGetFloatv //glGetIntegerv //glGetString +#define pglHint glHint /* Depth Buffer */ #define pglClearDepth glClearDepth @@ -215,19 +206,26 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglPushMatrix glPushMatrix #define pglPopMatrix glPopMatrix #define pglLoadIdentity glLoadIdentity -#define pglMultMatrixd glMultMatrixd +#define pglMultMatrixf glMultMatrixf #define pglRotatef glRotatef #define pglScalef glScalef #define pglTranslatef glTranslatef /* Drawing Functions */ -#define pglBegin glBegin -#define pglEnd glEnd -#define pglVertex3f glVertex3f -#define pglNormal3f glNormal3f -#define pglColor4f glColor4f -#define pglColor4fv glColor4fv -#define pglTexCoord2f glTexCoord2f +#define pglColor4ubv glColor4ubv +#define pglVertexPointer glVertexPointer +#define pglNormalPointer glNormalPointer +#define pglTexCoordPointer glTexCoordPointer +#define pglColorPointer glColorPointer +#define pglDrawArrays glDrawArrays +#define pglDrawElements glDrawElements +#define pglEnableClientState glEnableClientState +#define pglDisableClientState glDisableClientState +#define pglClientActiveTexture glClientActiveTexture +#define pglGenBuffers glGenBuffers +#define pglBindBuffer glBindBuffer +#define pglBufferData glBufferData +#define pglDeleteBuffers glDeleteBuffers /* Lighting */ #define pglShadeModel glShadeModel @@ -271,8 +269,6 @@ typedef void (APIENTRY * PFNglBlendFunc) (GLenum sfactor, GLenum dfactor); static PFNglBlendFunc pglBlendFunc; typedef void (APIENTRY * PFNglCullFace) (GLenum mode); static PFNglCullFace pglCullFace; -typedef void (APIENTRY * PFNglPolygonMode) (GLenum face, GLenum mode); -static PFNglPolygonMode pglPolygonMode; typedef void (APIENTRY * PFNglPolygonOffset) (GLfloat factor, GLfloat units); static PFNglPolygonOffset pglPolygonOffset; typedef void (APIENTRY * PFNglScissor) (GLint x, GLint y, GLsizei width, GLsizei height); @@ -281,8 +277,8 @@ typedef void (APIENTRY * PFNglEnable) (GLenum cap); static PFNglEnable pglEnable; typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; -typedef void (APIENTRY * PFNglGetDoublev) (GLenum pname, GLdouble *params); -static PFNglGetDoublev pglGetDoublev; +typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); +static PFNglGetFloatv pglGetFloatv; //glGetIntegerv //glGetString @@ -307,8 +303,8 @@ typedef void (APIENTRY * PFNglPopMatrix) (void); static PFNglPopMatrix pglPopMatrix; typedef void (APIENTRY * PFNglLoadIdentity) (void); static PFNglLoadIdentity pglLoadIdentity; -typedef void (APIENTRY * PFNglMultMatrixd) (const GLdouble *m); -static PFNglMultMatrixd pglMultMatrixd; +typedef void (APIENTRY * PFNglMultMatrixf) (const GLfloat *m); +static PFNglMultMatrixf pglMultMatrixf; typedef void (APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); static PFNglRotatef pglRotatef; typedef void (APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z); @@ -317,20 +313,33 @@ typedef void (APIENTRY * PFNglTranslatef) (GLfloat x, GLfloat y, GLfloat z); static PFNglTranslatef pglTranslatef; /* Drawing Functions */ -typedef void (APIENTRY * PFNglBegin) (GLenum mode); -static PFNglBegin pglBegin; -typedef void (APIENTRY * PFNglEnd) (void); -static PFNglEnd pglEnd; -typedef void (APIENTRY * PFNglVertex3f) (GLfloat x, GLfloat y, GLfloat z); -static PFNglVertex3f pglVertex3f; -typedef void (APIENTRY * PFNglNormal3f) (GLfloat x, GLfloat y, GLfloat z); -static PFNglNormal3f pglNormal3f; -typedef void (APIENTRY * PFNglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -static PFNglColor4f pglColor4f; -typedef void (APIENTRY * PFNglColor4fv) (const GLfloat *v); -static PFNglColor4fv pglColor4fv; -typedef void (APIENTRY * PFNglTexCoord2f) (GLfloat s, GLfloat t); -static PFNglTexCoord2f pglTexCoord2f; +typedef void (APIENTRY * PFNglColor4ubv) (const GLubyte *v); +static PFNglColor4ubv pglColor4ubv; +typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglVertexPointer pglVertexPointer; +typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglNormalPointer pglNormalPointer; +typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglTexCoordPointer pglTexCoordPointer; +typedef void (APIENTRY * PFNglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglColorPointer pglColorPointer; +typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); +static PFNglDrawArrays pglDrawArrays; +typedef void (APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +static PFNglDrawElements pglDrawElements; +typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); +static PFNglEnableClientState pglEnableClientState; +typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); +static PFNglDisableClientState pglDisableClientState; +typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); +static PFNglGenBuffers pglGenBuffers; +typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); +static PFNglBindBuffer pglBindBuffer; +typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); +static PFNglBufferData pglBufferData; +typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); +static PFNglDeleteBuffers pglDeleteBuffers; + /* Lighting */ typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); @@ -383,6 +392,10 @@ typedef void (APIENTRY *PFNglActiveTexture) (GLenum); static PFNglActiveTexture pglActiveTexture; typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); static PFNglMultiTexCoord2f pglMultiTexCoord2f; +typedef void (APIENTRY *PFNglMultiTexCoord2fv) (GLenum target, const GLfloat *v); +static PFNglMultiTexCoord2fv pglMultiTexCoord2fv; +typedef void (APIENTRY *PFNglClientActiveTexture) (GLenum); +static PFNglClientActiveTexture pglClientActiveTexture; /* 1.2 Parms */ /* GL_CLAMP_TO_EDGE_EXT */ @@ -416,19 +429,18 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglClearColor, glClearColor) - GETOPENGLFUNC(pglClear , glClear) - GETOPENGLFUNC(pglColorMask , glColorMask) - GETOPENGLFUNC(pglAlphaFunc , glAlphaFunc) - GETOPENGLFUNC(pglBlendFunc , glBlendFunc) - GETOPENGLFUNC(pglCullFace , glCullFace) - GETOPENGLFUNC(pglPolygonMode , glPolygonMode) - GETOPENGLFUNC(pglPolygonOffset , glPolygonOffset) - GETOPENGLFUNC(pglScissor , glScissor) - GETOPENGLFUNC(pglEnable , glEnable) - GETOPENGLFUNC(pglDisable , glDisable) - GETOPENGLFUNC(pglGetDoublev , glGetDoublev) - GETOPENGLFUNC(pglGetIntegerv , glGetIntegerv) - GETOPENGLFUNC(pglGetString , glGetString) + GETOPENGLFUNC(pglClear, glClear) + GETOPENGLFUNC(pglColorMask, glColorMask) + GETOPENGLFUNC(pglAlphaFunc, glAlphaFunc) + GETOPENGLFUNC(pglBlendFunc, glBlendFunc) + GETOPENGLFUNC(pglCullFace, glCullFace) + GETOPENGLFUNC(pglPolygonOffset, glPolygonOffset) + GETOPENGLFUNC(pglScissor, glScissor) + GETOPENGLFUNC(pglEnable, glEnable) + GETOPENGLFUNC(pglDisable, glDisable) + GETOPENGLFUNC(pglGetFloatv, glGetFloatv) + GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) + GETOPENGLFUNC(pglGetString, glGetString) GETOPENGLFUNC(pglClearDepth , glClearDepth) GETOPENGLFUNC(pglDepthFunc , glDepthFunc) @@ -440,18 +452,20 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglPushMatrix , glPushMatrix) GETOPENGLFUNC(pglPopMatrix , glPopMatrix) GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) - GETOPENGLFUNC(pglMultMatrixd , glMultMatrixd) + GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) GETOPENGLFUNC(pglRotatef , glRotatef) GETOPENGLFUNC(pglScalef , glScalef) GETOPENGLFUNC(pglTranslatef , glTranslatef) - GETOPENGLFUNC(pglBegin , glBegin) - GETOPENGLFUNC(pglEnd , glEnd) - GETOPENGLFUNC(pglVertex3f , glVertex3f) - GETOPENGLFUNC(pglNormal3f , glNormal3f) - GETOPENGLFUNC(pglColor4f , glColor4f) - GETOPENGLFUNC(pglColor4fv , glColor4fv) - GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) + GETOPENGLFUNC(pglColor4ubv, glColor4ubv) + GETOPENGLFUNC(pglVertexPointer, glVertexPointer) + GETOPENGLFUNC(pglNormalPointer, glNormalPointer) + GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) + GETOPENGLFUNC(pglColorPointer, glColorPointer) + GETOPENGLFUNC(pglDrawArrays, glDrawArrays) + GETOPENGLFUNC(pglDrawElements, glDrawElements) + GETOPENGLFUNC(pglEnableClientState, glEnableClientState) + GETOPENGLFUNC(pglDisableClientState, glDisableClientState) GETOPENGLFUNC(pglShadeModel , glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) @@ -483,42 +497,18 @@ boolean SetupGLfunc(void) } // This has to be done after the context is created so the version number can be obtained +// This is stupid -- even some of the oldest usable OpenGL hardware today supports 1.3-level featureset. boolean SetupGLFunc13(void) { - const GLubyte *version = pglGetString(GL_VERSION); - int glmajor, glminor; - - gl13 = false; - // Parse the GL version - if (version != NULL) - { - if (sscanf((const char*)version, "%d.%d", &glmajor, &glminor) == 2) - { - // Look, we gotta prepare for the inevitable arrival of GL 2.0 code... - if (glmajor == 1 && glminor >= 3) - gl13 = true; - else if (glmajor > 1) - gl13 = true; - } - } - - if (gl13) - { - pglActiveTexture = GetGLFunc("glActiveTexture"); - pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); - } - else if (isExtAvailable("GL_ARB_multitexture", gl_extensions)) - { - // Get the functions - pglActiveTexture = GetGLFunc("glActiveTextureARB"); - pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2fARB"); + pglActiveTexture = GetGLFunc("glActiveTexture"); + pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); + pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); + pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); + pglGenBuffers = GetGLFunc("glGenBuffers"); + pglBindBuffer = GetGLFunc("glBindBuffer"); + pglBufferData = GetGLFunc("glBufferData"); + pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); - gl13 = true; // This is now true, so the new fade mask stuff can be done, if OpenGL version is less than 1.3, it still uses the old fade stuff. - DBG_Printf("GL_ARB_multitexture support: enabled\n"); - - } - else - DBG_Printf("GL_ARB_multitexture support: disabled\n"); return true; } @@ -535,39 +525,40 @@ static void SetNoTexture(void) } } -static void GLPerspective(GLdouble fovy, GLdouble aspect) +static void GLPerspective(GLfloat fovy, GLfloat aspect) { - GLdouble m[4][4] = + GLfloat m[4][4] = { { 1.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f,-1.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}, }; - const GLdouble zNear = NEAR_CLIPPING_PLANE; - const GLdouble zFar = FAR_CLIPPING_PLANE; - const GLdouble radians = (GLdouble)(fovy / 2.0f * M_PIl / 180.0f); - const GLdouble sine = sin(radians); - const GLdouble deltaZ = zFar - zNear; - GLdouble cotangent; + const GLfloat zNear = NEAR_CLIPPING_PLANE; + const GLfloat zFar = FAR_CLIPPING_PLANE; + const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); + const GLfloat sine = sinf(radians); + const GLfloat deltaZ = zFar - zNear; + GLfloat cotangent; if ((fabsf((float)deltaZ) < 1.0E-36f) || fpclassify(sine) == FP_ZERO || fpclassify(aspect) == FP_ZERO) { return; } - cotangent = cos(radians) / sine; + cotangent = cosf(radians) / sine; m[0][0] = cotangent / aspect; m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[3][2] = -2.0f * zNear * zFar / deltaZ; - pglMultMatrixd(&m[0][0]); + + pglMultMatrixf(&m[0][0]); } -static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ, - GLdouble* winX, GLdouble* winY, GLdouble* winZ) +static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, + GLfloat* winX, GLfloat* winY, GLfloat* winZ) { - GLdouble in[4], out[4]; + GLfloat in[4], out[4]; int i; for (i=0; i<4; i++) @@ -634,7 +625,7 @@ void SetModelView(GLint w, GLint h) // added for new coronas' code (without depth buffer) pglGetIntegerv(GL_VIEWPORT, viewport); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); } @@ -659,9 +650,11 @@ void SetStates(void) //pglShadeModel(GL_FLAT); pglEnable(GL_TEXTURE_2D); // two-dimensional texturing + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglAlphaFunc(GL_NOTEQUAL, 0.0f); + //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) pglEnable(GL_BLEND); // enable color blending @@ -694,8 +687,6 @@ void SetStates(void) //pglEnable(GL_CULL_FACE); //pglCullFace(GL_FRONT); - //pglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //pglPolygonMode(GL_FRONT, GL_LINE); //glFogi(GL_FOG_MODE, GL_EXP); //pglHint(GL_FOG_HINT, GL_FASTEST); @@ -711,7 +702,7 @@ void SetStates(void) // bp : when no t&l :) pglLoadIdentity(); pglScalef(1.0f, 1.0f, -1.0f); - pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } @@ -877,7 +868,7 @@ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, f // added for new coronas' code (without depth buffer) pglGetIntegerv(GL_VIEWPORT, viewport); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); } @@ -911,6 +902,8 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, SetBlend(DepthMask ? PF_Occlude | CurrentPolyFlags : CurrentPolyFlags&~PF_Occlude); pglClear(ClearMask); + pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too } @@ -921,26 +914,35 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - GLRGBAFloat c; - // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); + GLfloat p[12]; + GLfloat dx, dy; + GLfloat angle; // BP: we should reflect the new state in our variable //SetBlend(PF_Modulated|PF_NoTexture); pglDisable(GL_TEXTURE_2D); - c.red = byte2float[Color.s.red]; - c.green = byte2float[Color.s.green]; - c.blue = byte2float[Color.s.blue]; - c.alpha = byte2float[Color.s.alpha]; + // This is the preferred, 'modern' way of rendering lines -- creating a polygon. + if (fabsf(v2->x - v1->x) > FLT_EPSILON) + angle = (float)atan((v2->y-v1->y)/(v2->x-v1->x)); + else + angle = (float)N_PI_DEMI; + dx = (float)sin(angle) / (float)screen_width; + dy = (float)cos(angle) / (float)screen_height; + + p[0] = v1->x - dx; p[1] = -(v1->y + dy); p[2] = 1; + p[3] = v2->x - dx; p[4] = -(v2->y + dy); p[5] = 1; + p[6] = v2->x + dx; p[7] = -(v2->y - dy); p[8] = 1; + p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; - pglColor4fv(&c.red); // is in RGBA float format - pglBegin(GL_LINES); - pglVertex3f(v1->x, -v1->y, 1.0f); - pglVertex3f(v2->x, -v2->y, 1.0f); - pglEnd(); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglColor4ubv((GLubyte*)&Color.s); + pglVertexPointer(3, GL_FLOAT, 0, p); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglEnable(GL_TEXTURE_2D); } @@ -985,7 +987,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) break; case PF_Substractive & PF_Blending: // good for shadow - // not realy but what else ? + // not really but what else ? pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); pglAlphaFunc(GL_NOTEQUAL, 0.0f); break; @@ -1050,7 +1052,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) if (oglflags & GLF_NOTEXENV) { if (!(PolyFlags & PF_Modulated)) - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + pglColor4ubv(white); } else #endif @@ -1125,15 +1127,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) w = pTexInfo->width; h = pTexInfo->height; -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - // do nothing here. - } - else -#endif if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) { @@ -1233,17 +1226,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); } -#ifdef USE_PALETTED_TEXTURE - //Hurdler: not really supported and not tested recently - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - pglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, w, h, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, pTexInfo->grInfo.data); - } - else -#endif if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) { //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1328,7 +1310,6 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, { FUINT i; FUINT j; - GLRGBAFloat c = {0,0,0,0}; if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) PolyFlags &= ~(PF_NoDepthTest|PF_Corona); @@ -1337,24 +1318,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, // If Modulated, mix the surface colour to the texture if ((CurrentPolyFlags & PF_Modulated) && pSurf) - { - if (pal_col) - { // hack for non-palettized mode - c.red = (const_pal_col.red +byte2float[pSurf->FlatColor.s.red]) /2.0f; - c.green = (const_pal_col.green+byte2float[pSurf->FlatColor.s.green])/2.0f; - c.blue = (const_pal_col.blue +byte2float[pSurf->FlatColor.s.blue]) /2.0f; - c.alpha = byte2float[pSurf->FlatColor.s.alpha]; - } - else - { - c.red = byte2float[pSurf->FlatColor.s.red]; - c.green = byte2float[pSurf->FlatColor.s.green]; - c.blue = byte2float[pSurf->FlatColor.s.blue]; - c.alpha = byte2float[pSurf->FlatColor.s.alpha]; - } - - pglColor4fv(&c.red); // is in RGBA float format - } + pglColor4ubv((GLubyte*)&pSurf->FlatColor.s); // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster @@ -1362,10 +1326,14 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, { //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value GLfloat buf[8][8]; - GLdouble cx, cy, cz; - GLdouble px = 0.0f, py = 0.0f, pz = -1.0f; + GLfloat cx, cy, cz; + GLfloat px = 0.0f, py = 0.0f, pz = -1.0f; GLfloat scalef = 0.0f; + GLubyte c[4]; + + float alpha; + cx = (pOutVerts[0].x + pOutVerts[2].x) / 2.0f; // we should change the coronas' ... cy = (pOutVerts[0].y + pOutVerts[2].y) / 2.0f; // ... code so its only done once. cz = pOutVerts[0].z; @@ -1401,21 +1369,20 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, if (scalef < 0.05f) return; - c.alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) - pglColor4fv(&c.red); - } - if (PolyFlags & PF_MD2) - return; + // GLubyte c[4]; + c[0] = pSurf->FlatColor.s.red; + c[1] = pSurf->FlatColor.s.green; + c[2] = pSurf->FlatColor.s.blue; - pglBegin(GL_TRIANGLE_FAN); - for (i = 0; i < iNumPts; i++) - { - pglTexCoord2f(pOutVerts[i].sow, pOutVerts[i].tow); - //Hurdler: test code: -pOutVerts[i].z => pOutVerts[i].z - pglVertex3f(pOutVerts[i].x, pOutVerts[i].y, pOutVerts[i].z); - //pglVertex3f(pOutVerts[i].x, pOutVerts[i].y, -pOutVerts[i].z); + alpha = byte2float[pSurf->FlatColor.s.alpha]; + alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) + c[3] = (unsigned char)(alpha * 255); + pglColor4ubv(c); } - pglEnd(); + + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); + pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); if (PolyFlags & PF_RemoveYWrap) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -1444,13 +1411,20 @@ typedef struct typedef struct { - int id; + unsigned int id; int rows, columns; int loopcount; GLSkyLoopDef *loops; vbo_vertex_t *data; } GLSkyVBO; +static const boolean gl_ext_arb_vertex_buffer_object = true; + +#define NULL_VBO_VERTEX ((vbo_vertex_t*)NULL) +#define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &vbo->data[0].x) +#define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &vbo->data[0].u) +#define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &vbo->data[0].r) + // The texture offset to be applied to the texture coordinates in SkyVertex(). static int rows, columns; static boolean yflip; @@ -1587,20 +1561,55 @@ static void gld_BuildSky(int row_count, int col_count) static void RenderDome(INT32 skytexture) { int i, j; + int vbosize; GLSkyVBO *vbo = &sky_vbo; - pglRotatef(270.0f, 0.0f, 1.0f, 0.0f); - rows = 4; columns = 4 * gl_sky_detail; + vbosize = 2 * rows * (columns * 2 + 2) + columns * 2; + + // Build the sky dome! Yes! if (lasttex != skytexture) { + // delete VBO when already exists + if (gl_ext_arb_vertex_buffer_object) + { + if (vbo->id) + pglDeleteBuffers(1, &vbo->id); + } + lasttex = skytexture; gld_BuildSky(rows, columns); + + if (gl_ext_arb_vertex_buffer_object) + { + // generate a new VBO and get the associated ID + pglGenBuffers(1, &vbo->id); + + // bind VBO in order to use + pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + + // upload data to VBO + pglBufferData(GL_ARRAY_BUFFER, vbosize * sizeof(vbo->data[0]), vbo->data, GL_STATIC_DRAW); + } } + // bind VBO in order to use + if (gl_ext_arb_vertex_buffer_object) + pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + + // activate and specify pointers to arrays + pglVertexPointer(3, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_u); + pglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vbo->data[0]), sky_vbo_r); + + // activate color arrays + pglEnableClientState(GL_COLOR_ARRAY); + + // set transforms pglScalef(1.0f, (float)texh / 230.0f, 1.0f); + pglRotatef(270.0f, 0.0f, 1.0f, 0.0f); for (j = 0; j < 2; j++) { @@ -1610,25 +1619,20 @@ static void RenderDome(INT32 skytexture) if (j == 0 ? loop->use_texture : !loop->use_texture) continue; - else - { - int k; - pglBegin(loop->mode); - for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++) - { - vbo_vertex_t *v = &vbo->data[k]; - if (loop->use_texture) - pglTexCoord2f(v->u, v->v); - pglColor4f(v->r, v->g, v->b, v->a); - pglVertex3f(v->x, v->y, v->z); - } - pglEnd(); - } + + pglDrawArrays(loop->mode, loop->vertexindex, loop->vertexcount); } } pglScalef(1.0f, 1.0f, 1.0f); - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + pglColor4ubv(white); + + // bind with 0, so, switch back to normal pointer operation + if (gl_ext_arb_vertex_buffer_object) + pglBindBuffer(GL_ARRAY_BUFFER, 0); + + // deactivate color array + pglDisableClientState(GL_COLOR_ARRAY); } EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) @@ -1659,15 +1663,6 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } #endif - case HWD_SET_PALETTECOLOR: - { - pal_col = Value; - const_pal_col.blue = byte2float[((Value>>16)&0xff)]; - const_pal_col.green = byte2float[((Value>>8)&0xff)]; - const_pal_col.red = byte2float[((Value)&0xff)]; - break; - } - case HWD_SET_FOG_COLOR: { GLfloat fogcolor[4]; @@ -1709,13 +1704,6 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) pglDisable(GL_FOG); break; - case HWD_SET_POLYGON_SMOOTH: - if (Value) - pglEnable(GL_POLYGON_SMOOTH); - else - pglDisable(GL_POLYGON_SMOOTH); - break; - case HWD_SET_TEXTUREFILTERMODE: switch (Value) { @@ -1770,19 +1758,227 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } } -static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static float *vertBuffer = NULL; +static float *normBuffer = NULL; +static size_t lerpBufferSize = 0; +static short *vertTinyBuffer = NULL; +static char *normTinyBuffer = NULL; +static size_t lerpTinyBufferSize = 0; + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +static void AllocLerpBuffer(size_t size) +{ + if (lerpBufferSize >= size) + return; + + if (vertBuffer != NULL) + free(vertBuffer); + + if (normBuffer != NULL) + free(normBuffer); + + lerpBufferSize = size; + vertBuffer = malloc(lerpBufferSize); + normBuffer = malloc(lerpBufferSize); +} + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +static void AllocLerpTinyBuffer(size_t size) +{ + if (lerpTinyBufferSize >= size) + return; + + if (vertTinyBuffer != NULL) + free(vertTinyBuffer); + + if (normTinyBuffer != NULL) + free(normTinyBuffer); + + lerpTinyBufferSize = size; + vertTinyBuffer = malloc(lerpTinyBufferSize); + normTinyBuffer = malloc(lerpTinyBufferSize / 2); +} + +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif + +static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame) +{ + int bufferSize = sizeof(vbo64_t)*mesh->numTriangles * 3; + vbo64_t *buffer = (vbo64_t*)malloc(bufferSize); + vbo64_t *bufPtr = buffer; + + float *vertPtr = frame->vertices; + float *normPtr = frame->normals; + float *tanPtr = frame->tangents; + float *uvPtr = mesh->uvs; + float *lightPtr = mesh->lightuvs; + char *colorPtr = frame->colors; + + int i; + for (i = 0; i < mesh->numTriangles * 3; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr != NULL) + { + bufPtr->tan0 = *tanPtr++; + bufPtr->tan1 = *tanPtr++; + bufPtr->tan2 = *tanPtr++; + } + + if (lightPtr != NULL) + { + bufPtr->s1 = *lightPtr++; + bufPtr->t1 = *lightPtr++; + } + + if (colorPtr) + { + bufPtr->r = *colorPtr++; + bufPtr->g = *colorPtr++; + bufPtr->b = *colorPtr++; + bufPtr->a = *colorPtr++; + } + else + { + bufPtr->r = 255; + bufPtr->g = 255; + bufPtr->b = 255; + bufPtr->a = 255; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) +{ + int bufferSize = sizeof(vbotiny_t)*mesh->numTriangles * 3; + vbotiny_t *buffer = (vbotiny_t*)malloc(bufferSize); + vbotiny_t *bufPtr = buffer; + + short *vertPtr = frame->vertices; + char *normPtr = frame->normals; + float *uvPtr = mesh->uvs; + char *tanPtr = frame->tangents; + + int i; + for (i = 0; i < mesh->numVertices; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr) + { + bufPtr->tanx = *tanPtr++; + bufPtr->tany = *tanPtr++; + bufPtr->tanz = *tanPtr++; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); +} + +EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) +{ + int i; + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBO(mesh, frame); + } + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + tinyframe_t *frame = &mesh->tinyframes[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBOTiny(mesh, frame); + } + } + } +} + +#define BUFFER_OFFSET(i) ((char*)NULL + (i)) + +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { - INT32 val, count, pindex; - GLfloat s, t; GLfloat ambient[4]; GLfloat diffuse[4]; float pol = 0.0f; - float scalex = scale, scaley = scale, scalez = scale; + float scalex, scaley, scalez; + + boolean useTinyFrames; + + int i; // Because Otherwise, scaling the screen negatively vertically breaks the lighting GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; + // Affect input model scaling + scale *= 0.5f; + scalex = scale; + scaley = scale; + scalez = scale; + if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { UINT32 newtime = (duration - tics); // + 1; @@ -1816,7 +2012,21 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, } pglEnable(GL_CULL_FACE); + pglEnable(GL_NORMALIZE); +#ifdef USE_FTRANSFORM_MIRROR + // flipped is if the object is flipped + // pos->flip is if the screen is flipped vertically + // pos->mirror is if the screen is flipped horizontally + // XOR all the flips together to figure out what culling to use! + { + boolean reversecull = (flipped ^ pos->flip ^ pos->mirror); + if (reversecull) + pglCullFace(GL_FRONT); + else + pglCullFace(GL_BACK); + } +#else // pos->flip is if the screen is flipped too if (flipped != pos->flip) // If either are active, but not both, invert the model's culling { @@ -1826,6 +2036,7 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, { pglCullFace(GL_BACK); } +#endif pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); @@ -1848,109 +2059,158 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, pglTranslatef(pos->x, pos->z, pos->y); if (flipped) scaley = -scaley; + +#ifdef USE_FTRANSFORM_ANGLEZ + pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart +#endif pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); + pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); #ifdef ROTSPRITE - // rotsprite if (pos->roll) { pglTranslatef(pos->centerx, pos->centery, 0); - pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); + if (pos->nightsroll != 0) + pglRotatef(pos->rollangle, 0.0f, 0.0f, (1.0f * pos->nightsroll)); + else + pglRotatef(pos->rollangle, 1.0f, 0.0f, 0.0f); pglTranslatef(-pos->centerx, -pos->centery, 0); } - else #endif - pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); - val = *gl_cmd_buffer++; + pglScalef(scalex, scaley, scalez); + + useTinyFrames = model->meshes[0].tinyframes != NULL; - while (val != 0) + if (useTinyFrames) + pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); + + pglEnableClientState(GL_NORMAL_ARRAY); + + for (i = 0; i < model->numMeshes; i++) { - if (val < 0) - { - pglBegin(GL_TRIANGLE_FAN); - count = -val; - } - else - { - pglBegin(GL_TRIANGLE_STRIP); - count = val; - } + mesh_t *mesh = &model->meshes[i]; - while (count--) + if (useTinyFrames) { - s = *(float *) gl_cmd_buffer++; - t = *(float *) gl_cmd_buffer++; - pindex = *gl_cmd_buffer++; + tinyframe_t *frame = &mesh->tinyframes[frameIndex % mesh->numFrames]; + tinyframe_t *nextframe = NULL; - pglTexCoord2f(s, t); + if (nextFrameIndex != -1) + nextframe = &mesh->tinyframes[nextFrameIndex % mesh->numFrames]; if (!nextframe || fpclassify(pol) == FP_ZERO) { - pglNormal3f(frame->vertices[pindex].normal[0], - frame->vertices[pindex].normal[1], - frame->vertices[pindex].normal[2]); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); - pglVertex3f(frame->vertices[pindex].vertex[0]*scalex/2.0f, - frame->vertices[pindex].vertex[1]*scaley/2.0f, - frame->vertices[pindex].vertex[2]*scalez/2.0f); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); } else { - // Interpolate - float px1 = frame->vertices[pindex].vertex[0]*scalex/2.0f; - float px2 = nextframe->vertices[pindex].vertex[0]*scalex/2.0f; - float py1 = frame->vertices[pindex].vertex[1]*scaley/2.0f; - float py2 = nextframe->vertices[pindex].vertex[1]*scaley/2.0f; - float pz1 = frame->vertices[pindex].vertex[2]*scalez/2.0f; - float pz2 = nextframe->vertices[pindex].vertex[2]*scalez/2.0f; - float nx1 = frame->vertices[pindex].normal[0]; - float nx2 = nextframe->vertices[pindex].normal[0]; - float ny1 = frame->vertices[pindex].normal[1]; - float ny2 = nextframe->vertices[pindex].normal[1]; - float nz1 = frame->vertices[pindex].normal[2]; - float nz2 = nextframe->vertices[pindex].normal[2]; - - pglNormal3f((nx1 + pol * (nx2 - nx1)), - (ny1 + pol * (ny2 - ny1)), - (nz1 + pol * (nz2 - nz1))); - pglVertex3f((px1 + pol * (px2 - px1)), - (py1 + pol * (py2 - py1)), - (pz1 + pol * (pz2 - pz1))); + short *vertPtr; + char *normPtr; + int j; + + // Dangit, I soooo want to do this in a GLSL shader... + AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); + vertPtr = vertTinyBuffer; + normPtr = normTinyBuffer; + j = 0; + + for (j = 0; j < mesh->numVertices * 3; j++) + { + // Interpolate + *vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]))); + *normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); + } + + pglVertexPointer(3, GL_SHORT, 0, vertTinyBuffer); + pglNormalPointer(GL_BYTE, 0, normTinyBuffer); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); } } + else + { + mdlframe_t *frame = &mesh->frames[frameIndex % mesh->numFrames]; + mdlframe_t *nextframe = NULL; - pglEnd(); + if (nextFrameIndex != -1) + nextframe = &mesh->frames[nextFrameIndex % mesh->numFrames]; + + if (!nextframe || fpclassify(pol) == FP_ZERO) + { + // Zoom! Take advantage of just shoving the entire arrays to the GPU. +/* pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); + pglNormalPointer(GL_FLOAT, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);*/ + + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); + + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + // No tinyframes, no mesh indices + //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + float *vertPtr; + float *normPtr; + int j = 0; - val = *gl_cmd_buffer++; + // Dangit, I soooo want to do this in a GLSL shader... + AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); + vertPtr = vertBuffer; + normPtr = normBuffer; + //int j = 0; + + for (j = 0; j < mesh->numVertices * 3; j++) + { + // Interpolate + *vertPtr++ = frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j])); + *normPtr++ = frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j])); + } + + pglVertexPointer(3, GL_FLOAT, 0, vertBuffer); + pglNormalPointer(GL_FLOAT, 0, normBuffer); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numVertices); + } + } } + + pglDisableClientState(GL_NORMAL_ARRAY); + pglPopMatrix(); // should be the same as glLoadIdentity if (color) pglDisable(GL_LIGHTING); pglShadeModel(GL_FLAT); pglDisable(GL_CULL_FACE); + pglDisable(GL_NORMALIZE); } // -----------------+ // HWRAPI DrawMD2 : Draw an MD2 model with glcommands // -----------------+ -EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { - DrawMD2Ex(gl_cmd_buffer, frame, duration, tics, nextframe, pos, scale, flipped, color); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, color); } -EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale) -{ - DrawMD2Ex(gl_cmd_buffer, frame, 0, 0, NULL, pos, scale, false, NULL); -} - - // -----------------+ // SetTransform : // -----------------+ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { - static INT32 special_splitscreen; + static boolean special_splitscreen; pglLoadIdentity(); if (stransform) { @@ -1958,6 +2218,12 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) // keep a trace of the transformation for md2 memcpy(&md2_transform, stransform, sizeof (md2_transform)); +#ifdef USE_FTRANSFORM_MIRROR + // mirroring from Kart + if (stransform->mirror) + pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez); + else +#endif if (stransform->flip) pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez); else @@ -1972,10 +2238,10 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f; special_splitscreen = (stransform->splitscreen && fovx90); if (special_splitscreen) - GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) + GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) else GLPerspective(stransform->fovxangle, ASPECT_RATIO); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); } else @@ -1985,15 +2251,15 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); if (special_splitscreen) - GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) + GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) else //Hurdler: is "fov" correct? GLPerspective(fov, ASPECT_RATIO); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); } - pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } EXPORT INT32 HWRAPI(GetTextureUsed) (void) @@ -2014,7 +2280,6 @@ EXPORT INT32 HWRAPI(GetRenderVersion) (void) return VERSION; } -#ifdef SHUFFLE EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { INT32 x, y; @@ -2022,6 +2287,14 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) float xfix, yfix; INT32 texsize = 2048; + const float blackBack[16] = + { + -16.0f, -16.0f, 6.0f, + -16.0f, 16.0f, 6.0f, + 16.0f, 16.0f, 6.0f, + 16.0f, -16.0f, 6.0f + }; + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; @@ -2034,47 +2307,66 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); - pglBegin(GL_QUADS); - // Draw a black square behind the screen texture, - // so nothing shows through the edges - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - pglVertex3f(-16.0f, -16.0f, 6.0f); - pglVertex3f(-16.0f, 16.0f, 6.0f); - pglVertex3f(16.0f, 16.0f, 6.0f); - pglVertex3f(16.0f, -16.0f, 6.0f); + // const float blackBack[16] + + // Draw a black square behind the screen texture, + // so nothing shows through the edges + pglColor4ubv(white); - for(x=0;x<SCREENVERTS-1;x++) + pglVertexPointer(3, GL_FLOAT, 0, blackBack); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + for(x=0;x<SCREENVERTS-1;x++) + { + for(y=0;y<SCREENVERTS-1;y++) { - for(y=0;y<SCREENVERTS-1;y++) - { - // Used for texture coordinates - // Annoying magic numbers to scale the square texture to - // a non-square screen.. - float_x = (float)(x/(xfix)); - float_y = (float)(y/(yfix)); - float_nextx = (float)(x+1)/(xfix); - float_nexty = (float)(y+1)/(yfix); - - // Attach the squares together. - pglTexCoord2f( float_x, float_y); - pglVertex3f(points[x][y][0], points[x][y][1], 4.4f); - - pglTexCoord2f( float_x, float_nexty); - pglVertex3f(points[x][y+1][0], points[x][y+1][1], 4.4f); - - pglTexCoord2f( float_nextx, float_nexty); - pglVertex3f(points[x+1][y+1][0], points[x+1][y+1][1], 4.4f); - - pglTexCoord2f( float_nextx, float_y); - pglVertex3f(points[x+1][y][0], points[x+1][y][1], 4.4f); - } + float stCoords[8]; + float vertCoords[12]; + + // Used for texture coordinates + // Annoying magic numbers to scale the square texture to + // a non-square screen.. + float_x = (float)(x/(xfix)); + float_y = (float)(y/(yfix)); + float_nextx = (float)(x+1)/(xfix); + float_nexty = (float)(y+1)/(yfix); + + // float stCoords[8]; + stCoords[0] = float_x; + stCoords[1] = float_y; + stCoords[2] = float_x; + stCoords[3] = float_nexty; + stCoords[4] = float_nextx; + stCoords[5] = float_nexty; + stCoords[6] = float_nextx; + stCoords[7] = float_y; + + pglTexCoordPointer(2, GL_FLOAT, 0, stCoords); + + // float vertCoords[12]; + vertCoords[0] = points[x][y][0]; + vertCoords[1] = points[x][y][1]; + vertCoords[2] = 4.4f; + vertCoords[3] = points[x][y + 1][0]; + vertCoords[4] = points[x][y + 1][1]; + vertCoords[5] = 4.4f; + vertCoords[6] = points[x + 1][y + 1][0]; + vertCoords[7] = points[x + 1][y + 1][1]; + vertCoords[8] = 4.4f; + vertCoords[9] = points[x + 1][y][0]; + vertCoords[10] = points[x + 1][y][1]; + vertCoords[11] = 4.4f; + + pglVertexPointer(3, GL_FLOAT, 0, vertCoords); + + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - pglEnd(); + } + pglEnable(GL_DEPTH_TEST); pglEnable(GL_BLEND); } -#endif //SHUFFLE // Sryder: This needs to be called whenever the screen changes resolution in order to reset the screen textures to use // a new size @@ -2159,6 +2451,16 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) float xfix, yfix; INT32 texsize = 2048; + const float screenVerts[12] = + { + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f + }; + + float fix[8]; + if(screen_width <= 1024) texsize = 1024; if(screen_width <= 512) @@ -2167,41 +2469,56 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); - pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - pglBindTexture(GL_TEXTURE_2D, screentexture); - pglBegin(GL_QUADS); - - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - // Bottom left - pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-1.0f, -1.0f, 1.0f); + // const float screenVerts[12] - // Top left - pglTexCoord2f(0.0f, yfix); - pglVertex3f(-1.0f, 1.0f, 1.0f); + // float fix[8]; + fix[0] = 0.0f; + fix[1] = 0.0f; + fix[2] = 0.0f; + fix[3] = yfix; + fix[4] = xfix; + fix[5] = yfix; + fix[6] = xfix; + fix[7] = 0.0f; - // Top right - pglTexCoord2f(xfix, yfix); - pglVertex3f(1.0f, 1.0f, 1.0f); + pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - // Bottom right - pglTexCoord2f(xfix, 0.0f); - pglVertex3f(1.0f, -1.0f, 1.0f); + pglBindTexture(GL_TEXTURE_2D, screentexture); + pglColor4ubv(white); - pglEnd(); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); tex_downloaded = screentexture; } // Do screen fades! -EXPORT void HWRAPI(DoScreenWipe)(float alpha) +EXPORT void HWRAPI(DoScreenWipe)(void) { INT32 texsize = 2048; float xfix, yfix; INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set + const float screenVerts[12] = + { + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f + }; + + float fix[8]; + + const float defaultST[8] = + { + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f + }; + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; @@ -2211,101 +2528,60 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); + // const float screenVerts[12] + + // float fix[8]; + fix[0] = 0.0f; + fix[1] = 0.0f; + fix[2] = 0.0f; + fix[3] = yfix; + fix[4] = xfix; + fix[5] = yfix; + fix[6] = xfix; + fix[7] = 0.0f; + pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); + pglEnable(GL_TEXTURE_2D); // Draw the original screen pglBindTexture(GL_TEXTURE_2D, startScreenWipe); - pglBegin(GL_QUADS); - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + pglColor4ubv(white); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - // Bottom left - pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-1.0f, -1.0f, 1.0f); + SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); - // Top left - pglTexCoord2f(0.0f, yfix); - pglVertex3f(-1.0f, 1.0f, 1.0f); + // Draw the end screen that fades in + pglActiveTexture(GL_TEXTURE0); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - // Top right - pglTexCoord2f(xfix, yfix); - pglVertex3f(1.0f, 1.0f, 1.0f); + pglActiveTexture(GL_TEXTURE1); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); - // Bottom right - pglTexCoord2f(xfix, 0.0f); - pglVertex3f(1.0f, -1.0f, 1.0f); + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - pglEnd(); + // const float defaultST[8] - SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); + pglClientActiveTexture(GL_TEXTURE0); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglClientActiveTexture(GL_TEXTURE1); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if (gl13) - { - // Draw the end screen that fades in - pglActiveTexture(GL_TEXTURE0); - pglEnable(GL_TEXTURE_2D); - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - pglActiveTexture(GL_TEXTURE1); - pglEnable(GL_TEXTURE_2D); - pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); - - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - pglBegin(GL_QUADS); - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - // Bottom left - pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, 0.0f); - pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 1.0f); - pglVertex3f(-1.0f, -1.0f, 1.0f); - - // Top left - pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, yfix); - pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 0.0f); - pglVertex3f(-1.0f, 1.0f, 1.0f); - - // Top right - pglMultiTexCoord2f(GL_TEXTURE0, xfix, yfix); - pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 0.0f); - pglVertex3f(1.0f, 1.0f, 1.0f); - - // Bottom right - pglMultiTexCoord2f(GL_TEXTURE0, xfix, 0.0f); - pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 1.0f); - pglVertex3f(1.0f, -1.0f, 1.0f); - pglEnd(); - - pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit - pglActiveTexture(GL_TEXTURE0); - tex_downloaded = endScreenWipe; - } - else - { - // Draw the end screen that fades in - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); - pglBegin(GL_QUADS); - pglColor4f(1.0f, 1.0f, 1.0f, alpha); - - // Bottom left - pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-1.0f, -1.0f, 1.0f); - - // Top left - pglTexCoord2f(0.0f, yfix); - pglVertex3f(-1.0f, 1.0f, 1.0f); - - // Top right - pglTexCoord2f(xfix, yfix); - pglVertex3f(1.0f, 1.0f, 1.0f); - - // Bottom right - pglTexCoord2f(xfix, 0.0f); - pglVertex3f(1.0f, -1.0f, 1.0f); - pglEnd(); - tex_downloaded = endScreenWipe; - } + pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + pglActiveTexture(GL_TEXTURE0); + pglClientActiveTexture(GL_TEXTURE0); + tex_downloaded = endScreenWipe; } @@ -2368,7 +2644,6 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); tex_downloaded = finalScreenTexture; - } EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) @@ -2379,6 +2654,9 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) FRGBAFloat clearColour; INT32 texsize = 2048; + float off[12]; + float fix[8]; + if(screen_width <= 1024) texsize = 1024; if(screen_width <= 512) @@ -2400,33 +2678,43 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) yoff = newaspect / origaspect; } + // float off[12]; + off[0] = -xoff; + off[1] = -yoff; + off[2] = 1.0f; + off[3] = -xoff; + off[4] = yoff; + off[5] = 1.0f; + off[6] = xoff; + off[7] = yoff; + off[8] = 1.0f; + off[9] = xoff; + off[10] = -yoff; + off[11] = 1.0f; + + // float fix[8]; + fix[0] = 0.0f; + fix[1] = 0.0f; + fix[2] = 0.0f; + fix[3] = yfix; + fix[4] = xfix; + fix[5] = yfix; + fix[6] = xfix; + fix[7] = 0.0f; + pglViewport(0, 0, width, height); clearColour.red = clearColour.green = clearColour.blue = 0; clearColour.alpha = 1; ClearBuffer(true, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); - pglBegin(GL_QUADS); - - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - // Bottom left - pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-xoff, -yoff, 1.0f); - - // Top left - pglTexCoord2f(0.0f, yfix); - pglVertex3f(-xoff, yoff, 1.0f); - - // Top right - pglTexCoord2f(xfix, yfix); - pglVertex3f(xoff, yoff, 1.0f); - // Bottom right - pglTexCoord2f(xfix, 0.0f); - pglVertex3f(xoff, -yoff, 1.0f); + pglColor4ubv(white); - pglEnd(); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, off); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); tex_downloaded = finalScreenTexture; } diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index e6cf164bb088b72ae778bc40fa02814e7f96fcd9..1bb97c37c31aec5dcde5524b907bea8c5576f639 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -71,7 +71,6 @@ extern FILE *gllogstream; #endif #ifndef DRIVER_STRING -// #define USE_PALETTED_TEXTURE #define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails #endif @@ -89,10 +88,6 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth void SetModelView(GLint w, GLint h); void SetStates(void); FUNCMATH float byteasfloat(UINT8 fbyte); -#ifdef USE_PALETTED_TEXTURE -extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; -extern GLubyte palette_tex[256*3]; -#endif #ifndef GL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE @@ -118,6 +113,10 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params); extern PFNglGetIntegerv pglGetIntegerv; typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name); extern PFNglGetString pglGetString; +#if 0 +typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c +static PFNglEnableClientState pglEnableClientState; +#endif #endif // ========================================================================== diff --git a/src/hardware/r_opengl/r_vbo.h b/src/hardware/r_opengl/r_vbo.h new file mode 100644 index 0000000000000000000000000000000000000000..ca1a974dabbbe6cc296e0f237d2f7dacd1d2328b --- /dev/null +++ b/src/hardware/r_opengl/r_vbo.h @@ -0,0 +1,52 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ +#ifndef _R_VBO_H_ +#define _R_VBO_H_ + +typedef struct +{ + float x, y, z; // Vertex + float nx, ny, nz; // Normal + float s0, t0; // Texcoord0 +} vbo32_t; + +typedef struct +{ + float x, y, z; // Vertex + float s0, t0; // Texcoord0 + unsigned char r, g, b, a; // Color + float pad[2]; // Pad +} vbo2d32_t; + +typedef struct +{ + float x, y; // Vertex + float s0, t0; // Texcoord0 +} vbofont_t; + +typedef struct +{ + short x, y, z; // Vertex + char nx, ny, nz; // Normal + char tanx, tany, tanz; // Tangent + float s0, t0; // Texcoord0 +} vbotiny_t; + +typedef struct +{ + float x, y, z; // Vertex + float nx, ny, nz; // Normal + float s0, t0; // Texcoord0 + float s1, t1; // Texcoord1 + float s2, t2; // Texcoord2 + float tan0, tan1, tan2; // Tangent + unsigned char r, g, b, a; // Color +} vbo64_t; + +#endif diff --git a/src/hardware/u_list.c b/src/hardware/u_list.c new file mode 100644 index 0000000000000000000000000000000000000000..dc49a74e7f7ab1a0502fbf5fb5f13cbbad888275 --- /dev/null +++ b/src/hardware/u_list.c @@ -0,0 +1,230 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#include "u_list.h" +#include "../z_zone.h" + +// Utility for managing +// structures in a linked +// list. +// +// Struct must have "next" and "prev" pointers +// as its first two variables. +// + +// +// ListAdd +// +// Adds an item to the list +// +void ListAdd(void *pItem, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + + if (*itemHead == NULL) + { + *itemHead = item; + (*itemHead)->prev = (*itemHead)->next = NULL; + } + else + { + listitem_t *tail; + tail = *itemHead; + + while (tail->next != NULL) + tail = tail->next; + + tail->next = item; + + tail->next->prev = tail; + + item->next = NULL; + } +} + +// +// ListAddFront +// +// Adds an item to the front of the list +// (This is much faster) +// +void ListAddFront(void *pItem, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + + if (*itemHead == NULL) + { + *itemHead = item; + (*itemHead)->prev = (*itemHead)->next = NULL; + } + else + { + (*itemHead)->prev = item; + item->next = (*itemHead); + item->prev = NULL; + *itemHead = item; + } +} + +// +// ListAddBefore +// +// Adds an item before the item specified in the list +// +void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + listitem_t *spot = (listitem_t*)pSpot; + + listitem_t *prev = spot->prev; + + if (!prev) + ListAddFront(pItem, itemHead); + else + { + item->next = spot; + spot->prev = item; + item->prev = prev; + prev->next = item; + } +} + +// +// ListAddAfter +// +// Adds an item after the item specified in the list +// +void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + listitem_t *spot = (listitem_t*)pSpot; + + listitem_t *next = spot->next; + + if (!next) + ListAdd(pItem, itemHead); + else + { + item->prev = spot; + spot->next = item; + item->next = next; + next->prev = item; + } +} + +// +// ListRemove +// +// Take an item out of the list and free its memory. +// +void ListRemove(void *pItem, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + + if (item == *itemHead) // Start of list + { + *itemHead = item->next; + + if (*itemHead) + (*itemHead)->prev = NULL; + } + else if (item->next == NULL) // end of list + { + item->prev->next = NULL; + } + else // Somewhere in between + { + item->prev->next = item->next; + item->next->prev = item->prev; + } + + Z_Free (item); +} + +// +// ListRemoveAll +// +// Removes all items from the list, freeing their memory. +// +void ListRemoveAll(listitem_t **itemHead) +{ + listitem_t *item; + listitem_t *next; + for (item = *itemHead; item; item = next) + { + next = item->next; + ListRemove(item, itemHead); + } +} + +// +// ListRemoveNoFree +// +// Take an item out of the list, but don't free its memory. +// +void ListRemoveNoFree(void *pItem, listitem_t **itemHead) +{ + listitem_t *item = (listitem_t*)pItem; + + if (item == *itemHead) // Start of list + { + *itemHead = item->next; + + if (*itemHead) + (*itemHead)->prev = NULL; + } + else if (item->next == NULL) // end of list + { + item->prev->next = NULL; + } + else // Somewhere in between + { + item->prev->next = item->next; + item->next->prev = item->prev; + } +} + +// +// ListGetCount +// +// Counts the # of items in a list +// Should not be used in performance-minded code +// +unsigned int ListGetCount(void *itemHead) +{ + listitem_t *item = (listitem_t*)itemHead; + + unsigned int count = 0; + for (; item; item = item->next) + count++; + + return count; +} + +// +// ListGetByIndex +// +// Gets an item in the list by its index +// Should not be used in performance-minded code +// +listitem_t *ListGetByIndex(void *itemHead, unsigned int index) +{ + listitem_t *head = (listitem_t*)itemHead; + unsigned int count = 0; + listitem_t *node; + for (node = head; node; node = node->next) + { + if (count == index) + return node; + + count++; + } + + return NULL; +} diff --git a/src/hardware/u_list.h b/src/hardware/u_list.h new file mode 100644 index 0000000000000000000000000000000000000000..7e9a3cabd3bb9e5a9ded2c2d9f1d0f34b074ec3f --- /dev/null +++ b/src/hardware/u_list.h @@ -0,0 +1,29 @@ +/* + From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com ) + An experimental work-in-progress. + + Donated to Sonic Team Junior and adapted to work with + Sonic Robo Blast 2. The license of this code matches whatever + the licensing is for Sonic Robo Blast 2. +*/ + +#ifndef _U_LIST_H_ +#define _U_LIST_H_ + +typedef struct listitem_s +{ + struct listitem_s *next; + struct listitem_s *prev; +} listitem_t; + +void ListAdd(void *pItem, listitem_t **itemHead); +void ListAddFront(void *pItem, listitem_t **itemHead); +void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead); +void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead); +void ListRemove(void *pItem, listitem_t **itemHead); +void ListRemoveAll(listitem_t **itemHead); +void ListRemoveNoFree(void *pItem, listitem_t **itemHead); +unsigned int ListGetCount(void *itemHead); +listitem_t *ListGetByIndex(void *itemHead, unsigned int index); + +#endif diff --git a/src/info.c b/src/info.c index 612050d6524c25c922bfa866b526c3699fb4e94b..cf6380aab9daee601327d0c7b5f1741cad774832 100644 --- a/src/info.c +++ b/src/info.c @@ -1800,38 +1800,24 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic - {SPR_METL, 0, 35, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_STAND - {SPR_METL, 1, 8, {NULL}, 0, 0, S_METALSONIC_WAIT2}, // S_METALSONIC_WAIT1 - {SPR_METL, 2, 8, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_WAIT2 - {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_WALK2}, // S_METALSONIC_WALK1 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK3}, // S_METALSONIC_WALK2 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK4}, // S_METALSONIC_WALK3 - {SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK5}, // S_METALSONIC_WALK4 - {SPR_METL, 7, 4, {NULL}, 0, 0, S_METALSONIC_WALK6}, // S_METALSONIC_WALK5 - {SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK7}, // S_METALSONIC_WALK6 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK8}, // S_METALSONIC_WALK7 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK1}, // S_METALSONIC_WALK8 - {SPR_METL, 8, 2, {NULL}, 0, 0, S_METALSONIC_RUN2}, // S_METALSONIC_RUN1 - {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN3}, // S_METALSONIC_RUN2 - {SPR_METL, 10, 2, {NULL}, 0, 0, S_METALSONIC_RUN4}, // S_METALSONIC_RUN3 - {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4 + {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT - {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE - {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER - {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH - {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE - {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE - {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT - {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 13, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 - {SPR_METL, 13, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 - {SPR_METL, 13, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 - {SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 - {SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 + {SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR + {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN + {SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE + {SPR_METL, 18, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER + {SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH + {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_NULL}, // S_METALSONIC_BOUNCE + {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE + {SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT + {SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN + {SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 + {SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 + {SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 + {SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 + {SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 + {SPR_METL, 15, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1 {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2 @@ -2542,32 +2528,38 @@ state_t states[NUMSTATES] = {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT - // Trapgoyles - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE2}, // S_TRAPGOYLE_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE3}, // S_TRAPGOYLE_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE}, // S_TRAPGOYLE_FIRE3 - - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEUP_CHECK}, // S_TRAPGOYLEUP - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEUP_FIRE1}, // S_TRAPGOYLEUP_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE2}, // S_TRAPGOYLEUP_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE3}, // S_TRAPGOYLEUP_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP}, // S_TRAPGOYLEUP_FIRE3 - - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEDOWN_CHECK}, // S_TRAPGOYLEDOWN - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEDOWN_FIRE1}, // S_TRAPGOYLEDOWN_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE2}, // S_TRAPGOYLEDOWN_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE3}, // S_TRAPGOYLEDOWN_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN}, // S_TRAPGOYLEDOWN_FIRE3 - - {SPR_BGAR, 0, 135, {NULL}, 0, 0, S_TRAPGOYLELONG_CHECK}, // S_TRAPGOYLELONG - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLELONG_FIRE1}, // S_TRAPGOYLELONG_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE2}, // S_TRAPGOYLELONG_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE3}, // S_TRAPGOYLELONG_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE4}, // S_TRAPGOYLELONG_FIRE3 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE5}, // S_TRAPGOYLELONG_FIRE4 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG}, // S_TRAPGOYLELONG_FIRE5 + // Glaregoyles + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLE_CHARGE}, // S_GLAREGOYLE + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLE_BLINK}, // S_GLAREGOYLE_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLE_HOLD}, // S_GLAREGOYLE_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP}, // S_GLAREGOYLE_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN}, // S_GLAREGOYLE_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN + + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEUP_CHARGE}, // S_GLAREGOYLEUP + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEUP_BLINK}, // S_GLAREGOYLEUP_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEUP_HOLD}, // S_GLAREGOYLEUP_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE}, // S_GLAREGOYLEUP_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_LOOP}, // S_GLAREGOYLEUP_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEUP_FIRE, S_GLAREGOYLEUP_COOLDOWN}, // S_GLAREGOYLEUP_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_COOLDOWN + + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHARGE}, // S_GLAREGOYLEDOWN + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEDOWN_BLINK}, // S_GLAREGOYLEDOWN_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEDOWN_HOLD}, // S_GLAREGOYLEDOWN_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE}, // S_GLAREGOYLEDOWN_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_LOOP}, // S_GLAREGOYLEDOWN_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEDOWN_FIRE, S_GLAREGOYLEDOWN_COOLDOWN}, // S_GLAREGOYLEDOWN_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_COOLDOWN + + {SPR_BGAR, 0, 90, {NULL}, 0, 0, S_GLAREGOYLELONG_CHARGE}, // S_GLAREGOYLELONG + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLELONG_BLINK}, // S_GLAREGOYLELONG_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLELONG_HOLD}, // S_GLAREGOYLELONG_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE}, // S_GLAREGOYLELONG_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_LOOP}, // S_GLAREGOYLELONG_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 5, S_GLAREGOYLELONG_FIRE, S_GLAREGOYLELONG_COOLDOWN}, // S_GLAREGOYLELONG_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_COOLDOWN // Target/Red Crystal {SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE}, // S_TARGET_IDLE @@ -2579,6 +2571,9 @@ state_t states[NUMSTATES] = // Green flame {SPR_CFLM, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 3, S_GREENFLAME}, // S_GREENFLAME + // ATZ Blue Gargoyle + {SPR_BGAR, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEGARGOYLE + // Stalagmites {SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_STG0 {SPR_STLG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_STG1 @@ -3826,8 +3821,8 @@ state_t states[NUMSTATES] = {SPR_BUMB, 5, 120, {NULL}, 0, 0, S_BUMBLEBORE_DIE}, // S_BUMBLEBORE_STUCK2 {SPR_BUMB, 5, 0, {A_CryingToMomma}, 0, 0, S_XPLD1}, // S_BUMBLEBORE_DIE - {SPR_BBUZ, 0, 2, {NULL}, 0, 0, S_BBUZZFLY2}, // S_BBUZZFLY1 - {SPR_BBUZ, 1, 2, {NULL}, 0, 0, S_BBUZZFLY1}, // S_BBUZZFLY2 + {SPR_BBUZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUGGLEIDLE + {SPR_BBUZ, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_BUGGLEFLY {SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1}, // S_SMASHSPIKE_FLOAT {SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2}, // S_SMASHSPIKE_EASE1 @@ -6640,18 +6635,18 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_METALSONIC_RACE 207, // doomednum - S_METALSONIC_STAND, // spawnstate + S_METALSONIC_RACE, // spawnstate 8, // spawnhealth - S_METALSONIC_WALK1, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_METALSONIC_RUN1, // meleestate + S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_PLAY_DEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed @@ -6661,7 +6656,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -6711,7 +6706,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // speed 32*FRACUNIT, // radius 52*FRACUNIT, // height - 0, // display offset + 1, // display offset 0, // mass 0, // damage sfx_None, // activesound @@ -13544,9 +13539,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLE + { // MT_GLAREGOYLE 1500, // doomednum - S_TRAPGOYLE, // spawnstate + S_GLAREGOYLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13571,9 +13566,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLEUP + { // MT_GLAREGOYLEUP 1501, // doomednum - S_TRAPGOYLEUP, // spawnstate + S_GLAREGOYLEUP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13598,9 +13593,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLEDOWN + { // MT_GLAREGOYLEDOWN 1502, // doomednum - S_TRAPGOYLEDOWN,// spawnstate + S_GLAREGOYLEDOWN,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13625,9 +13620,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLELONG + { // MT_GLAREGOYLELONG 1503, // doomednum - S_TRAPGOYLELONG,// spawnstate + S_GLAREGOYLELONG,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13706,6 +13701,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BLUEGARGOYLE + 1506, // doomednum + S_BLUEGARGOYLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 21*FRACUNIT, // speed + 16*FRACUNIT, // radius + 40*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_statu2, // activesound + MF_SLIDEME|MF_SOLID|MF_PUSHABLE, // flags + S_NULL // raisestate + }, + { // MT_STALAGMITE0 1900, // doomednum S_STG0, // spawnstate @@ -20091,11 +20113,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BUBBLEBUZZ + { // MT_BUGGLE 124, // doomednum - S_BBUZZFLY1, // spawnstate + S_BUGGLEIDLE, // spawnstate 1, // spawnhealth - S_BBUZZFLY1, // seestate + S_BUGGLEFLY, // seestate sfx_None, // seesound 2, // reactiontime sfx_None, // attacksound diff --git a/src/info.h b/src/info.h index 9cc99982ceb48cfd4f38b2e1a51c3ffdaea6f2c0..98b4d914fca9f3a26850a2467b5366c2002cbe3f 100644 --- a/src/info.h +++ b/src/info.h @@ -1939,25 +1939,7 @@ typedef enum state S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic (Race) - // S_PLAY_STND - S_METALSONIC_STAND, - // S_PLAY_TAP1 - S_METALSONIC_WAIT1, - S_METALSONIC_WAIT2, - // S_PLAY_WALK - S_METALSONIC_WALK1, - S_METALSONIC_WALK2, - S_METALSONIC_WALK3, - S_METALSONIC_WALK4, - S_METALSONIC_WALK5, - S_METALSONIC_WALK6, - S_METALSONIC_WALK7, - S_METALSONIC_WALK8, - // S_PLAY_SPD1 - S_METALSONIC_RUN1, - S_METALSONIC_RUN2, - S_METALSONIC_RUN3, - S_METALSONIC_RUN4, + S_METALSONIC_RACE, // Metal Sonic (Battle) S_METALSONIC_FLOAT, S_METALSONIC_VECTOR, @@ -2300,7 +2282,7 @@ typedef enum state S_ARROW, S_ARROWBONK, - // Trapgoyle Demon fire + // Glaregoyle Demon fire S_DEMONFIRE, // GFZ flowers @@ -2668,29 +2650,35 @@ typedef enum state S_WALLVINE_LONG, S_WALLVINE_SHORT, - // Trapgoyles - S_TRAPGOYLE, - S_TRAPGOYLE_CHECK, - S_TRAPGOYLE_FIRE1, - S_TRAPGOYLE_FIRE2, - S_TRAPGOYLE_FIRE3, - S_TRAPGOYLEUP, - S_TRAPGOYLEUP_CHECK, - S_TRAPGOYLEUP_FIRE1, - S_TRAPGOYLEUP_FIRE2, - S_TRAPGOYLEUP_FIRE3, - S_TRAPGOYLEDOWN, - S_TRAPGOYLEDOWN_CHECK, - S_TRAPGOYLEDOWN_FIRE1, - S_TRAPGOYLEDOWN_FIRE2, - S_TRAPGOYLEDOWN_FIRE3, - S_TRAPGOYLELONG, - S_TRAPGOYLELONG_CHECK, - S_TRAPGOYLELONG_FIRE1, - S_TRAPGOYLELONG_FIRE2, - S_TRAPGOYLELONG_FIRE3, - S_TRAPGOYLELONG_FIRE4, - S_TRAPGOYLELONG_FIRE5, + // Glaregoyles + S_GLAREGOYLE, + S_GLAREGOYLE_CHARGE, + S_GLAREGOYLE_BLINK, + S_GLAREGOYLE_HOLD, + S_GLAREGOYLE_FIRE, + S_GLAREGOYLE_LOOP, + S_GLAREGOYLE_COOLDOWN, + S_GLAREGOYLEUP, + S_GLAREGOYLEUP_CHARGE, + S_GLAREGOYLEUP_BLINK, + S_GLAREGOYLEUP_HOLD, + S_GLAREGOYLEUP_FIRE, + S_GLAREGOYLEUP_LOOP, + S_GLAREGOYLEUP_COOLDOWN, + S_GLAREGOYLEDOWN, + S_GLAREGOYLEDOWN_CHARGE, + S_GLAREGOYLEDOWN_BLINK, + S_GLAREGOYLEDOWN_HOLD, + S_GLAREGOYLEDOWN_FIRE, + S_GLAREGOYLEDOWN_LOOP, + S_GLAREGOYLEDOWN_COOLDOWN, + S_GLAREGOYLELONG, + S_GLAREGOYLELONG_CHARGE, + S_GLAREGOYLELONG_BLINK, + S_GLAREGOYLELONG_HOLD, + S_GLAREGOYLELONG_FIRE, + S_GLAREGOYLELONG_LOOP, + S_GLAREGOYLELONG_COOLDOWN, // ATZ's Red Crystal/Target S_TARGET_IDLE, @@ -2702,6 +2690,9 @@ typedef enum state // ATZ's green flame S_GREENFLAME, + // ATZ Blue Gargoyle + S_BLUEGARGOYLE, + // Stalagmites S_STG0, S_STG1, @@ -3892,8 +3883,8 @@ typedef enum state S_BUMBLEBORE_STUCK2, S_BUMBLEBORE_DIE, - S_BBUZZFLY1, - S_BBUZZFLY2, + S_BUGGLEIDLE, + S_BUGGLEFLY, S_SMASHSPIKE_FLOAT, S_SMASHSPIKE_EASE1, @@ -4311,7 +4302,7 @@ typedef enum mobj_type MT_CANNONBALL, // Cannonball MT_CANNONBALLDECOR, // Decorative/still cannonball MT_ARROW, // Arrow - MT_DEMONFIRE, // Trapgoyle fire + MT_DEMONFIRE, // Glaregoyle fire // Greenflower Scenery MT_GFZFLOWER1, @@ -4474,12 +4465,13 @@ typedef enum mobj_type // Egg Rock Scenery // Azure Temple Scenery - MT_TRAPGOYLE, - MT_TRAPGOYLEUP, - MT_TRAPGOYLEDOWN, - MT_TRAPGOYLELONG, + MT_GLAREGOYLE, + MT_GLAREGOYLEUP, + MT_GLAREGOYLEDOWN, + MT_GLAREGOYLELONG, MT_TARGET, // AKA Red Crystal MT_GREENFLAME, + MT_BLUEGARGOYLE, // Stalagmites MT_STALAGMITE0, @@ -4754,7 +4746,7 @@ typedef enum mobj_type MT_HIVEELEMENTAL, MT_BUMBLEBORE, - MT_BUBBLEBUZZ, + MT_BUGGLE, MT_SMASHINGSPIKEBALL, MT_CACOLANTERN, diff --git a/src/m_fixed.c b/src/m_fixed.c index d45bb70bf572dabacef5f9874dfe84d3b9bdef32..5e78967396a4b9802dc29e301a14112f03b3168a 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -56,7 +56,7 @@ fixed_t FixedDiv2(fixed_t a, fixed_t b) if (b == 0) I_Error("FixedDiv: divide by zero"); - ret = (((INT64)a * FRACUNIT) ) / b; + ret = (((INT64)a * FRACUNIT)) / b; if ((ret > INT32_MAX) || (ret < INT32_MIN)) I_Error("FixedDiv: divide by zero"); @@ -117,7 +117,7 @@ fixed_t FixedHypot(fixed_t x, fixed_t y) yx = FixedDiv(y, x); // (x/y) } yx2 = FixedMul(yx, yx); // (x/y)^2 - yx1 = FixedSqrt(1*FRACUNIT + yx2); // (1 + (x/y)^2)^1/2 + yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2 return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2) } @@ -191,8 +191,8 @@ vector2_t *FV2_Divide(vector2_t *a_i, fixed_t a_c) // Vector Complex Math vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a_o) { - a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT); - a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT); + a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT); + a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT); a_o->x = a_1->x + a_o->x; a_o->y = a_1->y + a_o->y; return a_o; @@ -200,16 +200,16 @@ vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a fixed_t FV2_Distance(const vector2_t *p1, const vector2_t *p2) { - fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x); - fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y); - return FixedSqrt(xs+ys); + fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x); + fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y); + return FixedSqrt(xs + ys); } fixed_t FV2_Magnitude(const vector2_t *a_normal) { - fixed_t xs = FixedMul(a_normal->x,a_normal->x); - fixed_t ys = FixedMul(a_normal->y,a_normal->y); - return FixedSqrt(xs+ys); + fixed_t xs = FixedMul(a_normal->x, a_normal->x); + fixed_t ys = FixedMul(a_normal->y, a_normal->y); + return FixedSqrt(xs + ys); } // Also returns the magnitude @@ -240,7 +240,7 @@ vector2_t *FV2_Negate(vector2_t *a_1) boolean FV2_Equal(const vector2_t *a_1, const vector2_t *a_2) { - fixed_t Epsilon = FRACUNIT/FRACUNIT; + fixed_t Epsilon = FRACUNIT / FRACUNIT; if ((abs(a_2->x - a_1->x) > Epsilon) || (abs(a_2->y - a_1->y) > Epsilon)) @@ -261,7 +261,7 @@ fixed_t FV2_Dot(const vector2_t *a_1, const vector2_t *a_2) // // Given two points, create a vector between them. // -vector2_t *FV2_Point2Vec (const vector2_t *point1, const vector2_t *point2, vector2_t *a_o) +vector2_t *FV2_Point2Vec(const vector2_t *point1, const vector2_t *point2, vector2_t *a_o) { a_o->x = point1->x - point2->x; a_o->y = point1->y - point2->y; @@ -344,9 +344,9 @@ vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c) // Vector Complex Math vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o) { - a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT); - a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT); - a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT); + a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT); + a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT); + a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT); a_o->x = a_1->x + a_o->x; a_o->y = a_1->y + a_o->y; a_o->z = a_1->z + a_o->z; @@ -355,18 +355,18 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2) { - fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x); - fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y); - fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z); - return FixedSqrt(xs+ys+zs); + fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x); + fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y); + fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z); + return FixedSqrt(xs + ys + zs); } fixed_t FV3_Magnitude(const vector3_t *a_normal) { - fixed_t xs = FixedMul(a_normal->x,a_normal->x); - fixed_t ys = FixedMul(a_normal->y,a_normal->y); - fixed_t zs = FixedMul(a_normal->z,a_normal->z); - return FixedSqrt(xs+ys+zs); + fixed_t xs = FixedMul(a_normal->x, a_normal->x); + fixed_t ys = FixedMul(a_normal->y, a_normal->y); + fixed_t zs = FixedMul(a_normal->z, a_normal->z); + return FixedSqrt(xs + ys + zs); } // Also returns the magnitude @@ -399,7 +399,7 @@ vector3_t *FV3_Negate(vector3_t *a_1) boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2) { - fixed_t Epsilon = FRACUNIT/FRACUNIT; + fixed_t Epsilon = FRACUNIT / FRACUNIT; if ((abs(a_2->x - a_1->x) > Epsilon) || (abs(a_2->y - a_1->y) > Epsilon) || @@ -458,6 +458,20 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec return FV3_AddEx(&Line[0], &V, out); } +// +// ClosestPointOnVector +// +// Similar to ClosestPointOnLine, but uses a vector instead of two points. +// +void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out) +{ + fixed_t t = FV3_Dot(dir, p); + + // Return the point on the line closest + FV3_MulEx(dir, t, out); + return; +} + // // ClosestPointOnTriangle // @@ -465,7 +479,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec // the closest point on the edge of // the triangle is returned. // -void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, vector3_t *result) +void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result) { UINT8 i; fixed_t dist, closestdist; @@ -506,7 +520,7 @@ void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, v // // Given two points, create a vector between them. // -vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vector3_t *a_o) +vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o) { a_o->x = point1->x - point2->x; a_o->y = point1->y - point2->y; @@ -519,7 +533,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect // // Calculates the normal of a polygon. // -void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal) +fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal) { vector3_t a_1; vector3_t a_2; @@ -529,7 +543,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal) FV3_Cross(&a_1, &a_2, a_normal); - FV3_NormalizeEx(a_normal, a_normal); + return FV3_NormalizeEx(a_normal, a_normal); +} + +// +// Strength +// +// Measures the 'strength' of a vector in a particular direction. +// +fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir) +{ + vector3_t normal; + fixed_t dist = FV3_NormalizeEx(a_1, &normal); + fixed_t dot = FV3_Dot(&normal, dir); + + FV3_ClosestPointOnVector(dir, a_1, &normal); + + dist = FV3_Magnitude(&normal); + + if (dot < 0) // Not facing same direction, so negate result. + dist = -dist; + + return dist; } // @@ -550,11 +585,11 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin *originDistance = FV3_PlaneDistance(a_normal, &a_triangle[0]); - distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y) - + FixedMul(a_normal->z, a_line[0].z)) + *originDistance; + distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y) + + FixedMul(a_normal->z, a_line[0].z)) + *originDistance; - distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y) - + FixedMul(a_normal->z, a_line[1].z)) + *originDistance; + distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y) + + FixedMul(a_normal->z, a_line[1].z)) + *originDistance; // Positive or zero number means no intersection if (FixedMul(distance1, distance2) >= 0) @@ -575,8 +610,8 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector) { fixed_t d = -(FV3_Dot(pNormal, pOrigin)); - fixed_t number = FV3_Dot(pNormal,rOrigin) + d; - fixed_t denom = FV3_Dot(pNormal,rVector); + fixed_t number = FV3_Dot(pNormal, rOrigin) + d; + fixed_t denom = FV3_Dot(pNormal, rVector); return -FixedDiv(number, denom); } @@ -597,11 +632,11 @@ fixed_t FV3_IntersectRaySphere(const vector3_t *rO, const vector3_t *rV, const v c = FV3_Magnitude(&Q); v = FV3_Dot(&Q, rV); - d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v)); + d = FixedMul(sR, sR) - (FixedMul(c, c) - FixedMul(v, v)); // If there was no intersection, return -1 - if (d < 0*FRACUNIT) - return (-1*FRACUNIT); + if (d < 0 * FRACUNIT) + return (-1 * FRACUNIT); // Return the distance to the [first] intersecting point return (v - FixedSqrt(d)); @@ -629,9 +664,9 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin // Here I just chose a arbitrary point as the point to find that distance. You notice we negate that // distance. We negate the distance because we want to eventually go BACKWARDS from our point to the plane. // By doing this is will basically bring us back to the plane to find our intersection point. - Numerator = - (FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line - FixedMul(vNormal->y, vLine[0].y) + - FixedMul(vNormal->z, vLine[0].z) + distance); + Numerator = -(FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line + FixedMul(vNormal->y, vLine[0].y) + + FixedMul(vNormal->z, vLine[0].z) + distance); // 3) If we take the dot product between our line vector and the normal of the polygon, // this will give us the cosine of the angle between the 2 (since they are both normalized - length 1). @@ -643,7 +678,7 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin // on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)). // In this case, we should just return any point on the line. - if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero + if (Denominator == 0 * FRACUNIT) // Check so we don't divide by zero { ReturnVec->x = vLine[0].x; ReturnVec->y = vLine[0].y; @@ -686,8 +721,8 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin // UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line) { - fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x)); - fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y)); + fixed_t s1 = FixedMul((point->y - line[0].y), (line[1].x - line[0].x)); + fixed_t s2 = FixedMul((point->x - line[0].x), (line[1].y - line[0].y)); return (UINT8)(s1 - s2 < 0); } @@ -752,7 +787,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi matrix->m[0] = upcross.x; matrix->m[1] = upcross.y; matrix->m[2] = upcross.z; - matrix->m[3] = 0*FRACUNIT; + matrix->m[3] = 0 * FRACUNIT; matrix->m[4] = upx; matrix->m[5] = upy; @@ -764,9 +799,9 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi matrix->m[10] = anglez; matrix->m[11] = 0; - matrix->m[12] = x - FixedMul(upx,radius); - matrix->m[13] = y - FixedMul(upy,radius); - matrix->m[14] = z - FixedMul(upz,radius); + matrix->m[12] = x - FixedMul(upx, radius); + matrix->m[13] = y - FixedMul(upy, radius); + matrix->m[14] = z - FixedMul(upz, radius); matrix->m[15] = FRACUNIT; } @@ -778,20 +813,20 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out) { #define M(row,col) matrix->m[col * 4 + row] - out->x = FixedMul(vec->x,M(0, 0)) - + FixedMul(vec->y,M(0, 1)) - + FixedMul(vec->z,M(0, 2)) - + M(0, 3); - - out->y = FixedMul(vec->x,M(1, 0)) - + FixedMul(vec->y,M(1, 1)) - + FixedMul(vec->z,M(1, 2)) - + M(1, 3); - - out->z = FixedMul(vec->x,M(2, 0)) - + FixedMul(vec->y,M(2, 1)) - + FixedMul(vec->z,M(2, 2)) - + M(2, 3); + out->x = FixedMul(vec->x, M(0, 0)) + + FixedMul(vec->y, M(0, 1)) + + FixedMul(vec->z, M(0, 2)) + + M(0, 3); + + out->y = FixedMul(vec->x, M(1, 0)) + + FixedMul(vec->y, M(1, 1)) + + FixedMul(vec->z, M(1, 2)) + + M(1, 3); + + out->z = FixedMul(vec->x, M(2, 0)) + + FixedMul(vec->y, M(2, 1)) + + FixedMul(vec->z, M(2, 2)) + + M(2, 3); #undef M } @@ -811,7 +846,7 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme) for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) - R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j)); + R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j)); } M_Memcpy(dest, &result, sizeof(matrix_t)); @@ -869,8 +904,8 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z) static inline void M_print(INT64 a) { - const fixed_t w = (a>>FRACBITS); - fixed_t f = a%FRACUNIT; + const fixed_t w = (a >> FRACBITS); + fixed_t f = a % FRACUNIT; fixed_t d = FRACUNIT; if (f == 0) @@ -878,7 +913,7 @@ static inline void M_print(INT64 a) printf("%d", (fixed_t)w); return; } - else while (f != 1 && f/2 == f>>1) + else while (f != 1 && f / 2 == f >> 1) { d /= 2; f /= 2; @@ -892,7 +927,7 @@ static inline void M_print(INT64 a) FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b) { - return (fixed_t)((((INT64)a * b) ) / FRACUNIT); + return (fixed_t)((((INT64)a * b)) / FRACUNIT); } FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b) @@ -902,7 +937,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b) if (b == 0) I_Error("FixedDiv: divide by zero"); - ret = (((INT64)a * FRACUNIT) ) / b; + ret = (((INT64)a * FRACUNIT)) / b; if ((ret > INT32_MAX) || (ret < INT32_MIN)) I_Error("FixedDiv: divide by zero"); @@ -911,7 +946,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b) FUNCMATH FUNCINLINE static inline fixed_t FixedDivC(fixed_t a, fixed_t b) { - if ((abs(a) >> (FRACBITS-2)) >= abs(b)) + if ((abs(a) >> (FRACBITS - 2)) >= abs(b)) return (a^b) < 0 ? INT32_MIN : INT32_MAX; return FixedDivC2(a, b); @@ -938,43 +973,43 @@ int main(int argc, char** argv) #ifdef MULDIV_TEST for (a = 1; a <= INT32_MAX; a += FRACUNIT) - for (b = 0; b <= INT32_MAX; b += FRACUNIT) - { - c = FixedMul(a, b); - d = FixedMulC(a, b); - if (c != d) + for (b = 0; b <= INT32_MAX; b += FRACUNIT) { - printf("("); - M_print(a); - printf(") * ("); - M_print(b); - printf(") = ("); - M_print(c); - printf(") != ("); - M_print(d); - printf(") \n"); - n--; - printf("%d != %d\n", c, d); + c = FixedMul(a, b); + d = FixedMulC(a, b); + if (c != d) + { + printf("("); + M_print(a); + printf(") * ("); + M_print(b); + printf(") = ("); + M_print(c); + printf(") != ("); + M_print(d); + printf(") \n"); + n--; + printf("%d != %d\n", c, d); + } + c = FixedDiv(a, b); + d = FixedDivC(a, b); + if (c != d) + { + printf("("); + M_print(a); + printf(") / ("); + M_print(b); + printf(") = ("); + M_print(c); + printf(") != ("); + M_print(d); + printf(")\n"); + n--; + printf("%d != %d\n", c, d); + } + if (n <= 0) + exit(-1); } - c = FixedDiv(a, b); - d = FixedDivC(a, b); - if (c != d) - { - printf("("); - M_print(a); - printf(") / ("); - M_print(b); - printf(") = ("); - M_print(c); - printf(") != ("); - M_print(d); - printf(")\n"); - n--; - printf("%d != %d\n", c, d); - } - if (n <= 0) - exit(-1); - } #endif #ifdef SQRT_TEST @@ -982,7 +1017,7 @@ int main(int argc, char** argv) { c = FixedSqrt(a); d = FixedSqrtC(a); - b = abs(c-d); + b = abs(c - d); if (b > 1) { printf("sqrt("); diff --git a/src/m_fixed.h b/src/m_fixed.h index d8e722b13c8f0117f10098064973997cf0695df8..370633c1f6b0de4752f575bc3ab5929fd0a329cd 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -389,9 +389,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2); fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2); vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o); vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out); +void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out); void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result); vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o); -void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal); +fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal); +fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir); fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point); boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance); fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector); diff --git a/src/m_menu.c b/src/m_menu.c index aec4da32113cc8b2c0f2874c6733e62baa7c675b..f3528d8e5cb33874a58203e0f832020c7696514f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1295,18 +1295,21 @@ static menuitem_t OP_ColorOptionsMenu[] = #ifdef HWRENDER static menuitem_t OP_OpenGLOptionsMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 10}, - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 20}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 30}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,40}, + {IT_STRING|IT_CVAR, NULL, "Models", &cv_grmodels, 10}, + {IT_STRING|IT_CVAR, NULL, "Model interpolation", &cv_grmodelinterpolation, 20}, + + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 40}, + {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 50}, + {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 60}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,70}, #if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL))) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 80}, #endif #ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70}, + {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 100}, #endif - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 80}, - {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 90}, + {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 110}, + {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 120}, }; #ifdef ALAM_LIGHTING @@ -6560,7 +6563,7 @@ static void M_LevelSelectWarp(INT32 choice) if (W_CheckNumForName(G_BuildMapName(cv_nextmap.value)) == LUMPERROR) { -// CONS_Alert(CONS_WARNING, "Internal game map '%s' not found\n", G_BuildMapName(cv_nextmap.value)); + CONS_Alert(CONS_WARNING, "Internal game map '%s' not found\n", G_BuildMapName(cv_nextmap.value)); return; } @@ -7977,81 +7980,80 @@ static void M_SetupChoosePlayer(INT32 choice) char *and; (void)choice; - SP_PlayerMenu[0].status &= ~IT_DYBIGSPACE; // Correcting a hack that may be made below. - - for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks. + if (!(mapheaderinfo[startmap-1] + && (mapheaderinfo[startmap-1]->forcecharacter[0] != '\0' + || (mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS)) // remove this later when everyone gets their own nights sprites, maybe + )) { - if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. + for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks. { - and = strchr(description[i].skinname, '&'); - if (and) - { - char firstskin[SKINNAMESIZE+1]; - strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); - firstskin[(and - description[i].skinname)] = '\0'; - description[i].skinnum[0] = R_SkinAvailable(firstskin); - description[i].skinnum[1] = R_SkinAvailable(and+1); - } - else + if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { - description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); - description[i].skinnum[1] = -1; - } - skinnum = description[i].skinnum[0]; - if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) - { - // Handling order. - if (firstvalid == 255) - firstvalid = i; + and = strchr(description[i].skinname, '&'); + if (and) + { + char firstskin[SKINNAMESIZE+1]; + strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); + firstskin[(and - description[i].skinname)] = '\0'; + description[i].skinnum[0] = R_SkinAvailable(firstskin); + description[i].skinnum[1] = R_SkinAvailable(and+1); + } else { - description[i].prev = lastvalid; - description[lastvalid].next = i; + description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); + description[i].skinnum[1] = -1; } - lastvalid = i; + skinnum = description[i].skinnum[0]; + if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) + { + // Handling order. + if (firstvalid == 255) + firstvalid = i; + else + { + description[i].prev = lastvalid; + description[lastvalid].next = i; + } + lastvalid = i; - if (i == char_on) - allowed = true; + if (i == char_on) + allowed = true; - if (!(description[i].picname[0])) - { - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1) + if (!(description[i].picname[0])) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; - description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1) + { + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; + description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + } + else + description[i].charpic = W_CachePatchName("MISSING", PU_CACHE); } else - description[i].charpic = W_CachePatchName("MISSING", PU_CACHE); - } - else - description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE); + description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE); - if (description[i].nametag[0]) - { - const char *nametag = description[i].nametag; - description[i].namepic = NULL; - if (W_LumpExists(nametag)) - description[i].namepic = W_CachePatchName(nametag, PU_CACHE); + if (description[i].nametag[0]) + { + const char *nametag = description[i].nametag; + description[i].namepic = NULL; + if (W_LumpExists(nametag)) + description[i].namepic = W_CachePatchName(nametag, PU_CACHE); + } } + // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. } - // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. } } - if ((firstvalid != 255) - && !(mapheaderinfo[startmap-1] - && (mapheaderinfo[startmap-1]->forcecharacter[0] != '\0') - ) - ) + if (firstvalid != 255) { // One last bit of order we can't do in the iteration above. description[firstvalid].prev = lastvalid; description[lastvalid].next = firstvalid; } - else // We're being forced into a specific character, so might as well. + else // We're being forced into a specific character, so might as well just skip it. { - SP_PlayerMenu[0].status |= IT_DYBIGSPACE; // This is a dummy flag hack to make a non-IT_CALL character in slot 0 not softlock the game. - M_ChoosePlayer(0); + M_ChoosePlayer(-1); return; } @@ -8378,38 +8380,42 @@ static void M_DrawSetupChoosePlayerMenu(void) static void M_ChoosePlayer(INT32 choice) { boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); + UINT8 skinnum; // skip this if forcecharacter or no characters available - if (!(SP_PlayerMenu[0].status & IT_DYBIGSPACE)) + if (choice == -1) + { + skinnum = botskin = 0; + botingame = false; + } + // M_SetupChoosePlayer didn't call us directly, that means we've been properly set up. + else { - // M_SetupChoosePlayer didn't call us directly, that means we've been properly set up. char_scroll = 0; // finish scrolling the menu M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout // Is this a hack? charseltimer = 0; - } - M_ClearMenus(true); - if (description[choice].skinnum[1] != -1) { - // this character has a second skin - botingame = true; - botskin = (UINT8)(description[choice].skinnum[1]+1); - botcolor = skins[description[choice].skinnum[1]].prefcolor; - } - else - { - botingame = false; - botskin = 0; - botcolor = 0; + skinnum = description[choice].skinnum[0]; + + if ((botingame = (description[choice].skinnum[1] != -1))) { + // this character has a second skin + botskin = (UINT8)(description[choice].skinnum[1]+1); + botcolor = skins[description[choice].skinnum[1]].prefcolor; + } + else + botskin = botcolor = 0; } + M_ClearMenus(true); + if (startmap != spstage_start) cursaveslot = 0; //lastmapsaved = 0; gamecomplete = false; - G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)description[choice].skinnum[0], false, fromlevelselect); + G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this if (levelselect.rows) diff --git a/src/p_enemy.c b/src/p_enemy.c index 1f2cef211290f23a8d81b66bf102b82fde4d4e24..c0e3420ad19bb2fdd56e8a5cf78d6c3f5a0a9762 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3327,7 +3327,8 @@ void A_SkullAttack(mobj_t *actor) fixed_t oldradius = mobjinfo[MT_NULL].radius; fixed_t oldheight = mobjinfo[MT_NULL].height; mobj_t *check; - INT32 i, j, k; + INT32 i, j; + static INT32 k;/* static for (at least) GCC 9.1 weirdness */ boolean allow; angle_t testang; @@ -3936,11 +3937,15 @@ void A_BossDeath(mobj_t *mo) { // Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic. // So just park ourselves in the mapmus variables. - boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7); - strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7); - mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; - mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos; + // But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES). + boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7); + if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7)) + { + strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7); + mapmusname[6] = 0; + mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; + mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos; + } // don't change if we're in another tune // but in case we're in jingle, use our parked mapmus variables so the correct track restores @@ -9207,10 +9212,11 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/3; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, (filler->destscale = actor->scale/3)); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; + filler->color = SKINCOLOR_ICY; + filler->colorized = true; } else if (locvar1 == 3) // Boss 4 jet flame { diff --git a/src/p_inter.c b/src/p_inter.c index ee2c54dd7116a3de989a3dfee88b0c7e1fcad9b2..c65e6cc3604e4347ed18bbeca2d5e56ae8ac8497 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2372,7 +2372,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player && !target->player->spectator) { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! - G_StopMetalRecording(); + G_StopMetalRecording(true); if (gametype == GT_MATCH // note, no team match suicide penalty && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) { // Suicide penalty @@ -2617,7 +2617,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->fuse = target->info->damage; break; - case MT_BUBBLEBUZZ: + case MT_BUGGLE: if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it && P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough? && inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale) @@ -2763,6 +2763,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } break; + case MT_METALSONIC_RACE: + target->fuse = TICRATE*3; + target->momx = target->momy = target->momz = 0; + P_SetObjectMomZ(target, 14*FRACUNIT, false); + target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING); + break; default: break; } @@ -3617,11 +3623,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (inflictor && inflictor->flags & MF_MISSILE) return false; // Metal Sonic walk through flame !! - else + else if (!player->powers[pw_flashing]) { // Oh no! Metal Sonic is hit !! P_ShieldDamage(player, inflictor, source, damage, damagetype); return true; } + return false; } else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability { diff --git a/src/p_mobj.c b/src/p_mobj.c index 0f0f8305bc5efd164e58ba8a7c1a4754ebde7233..498cf897ef1a42a5e2d0c7b22617d2555974612e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2563,19 +2563,30 @@ static boolean P_ZMovement(mobj_t *mo) if (!mo->player && P_CheckDeathPitCollide(mo)) { - if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART) + switch (mo->type) { - // Kill enemies, bosses and minecarts that fall into death pits. - if (mo->health) - { - P_KillMobj(mo, NULL, NULL, 0); - return false; - } - } - else - { - P_RemoveMobj(mo); - return false; + case MT_GHOST: + case MT_METALSONIC_RACE: + case MT_EXPLODE: + case MT_BOSSEXPLODE: + case MT_SONIC3KBOSSEXPLODE: + break; + default: + if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART) + { + // Kill enemies, bosses and minecarts that fall into death pits. + if (mo->health) + { + P_KillMobj(mo, NULL, NULL, 0); + } + return false; + } + else + { + P_RemoveMobj(mo); + return false; + } + break; } } @@ -5567,9 +5578,9 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); mobj->momz -= gravity; - if (mobj->z < mobj->watertop) + if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT)) { - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->watertop = mobj->floorz + 32*FRACUNIT; P_SetMobjState(mobj, mobj->info->spawnstate); } return; @@ -5577,16 +5588,22 @@ static void P_Boss9Thinker(mobj_t *mobj) if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { - if (mobj->tracer) - P_RemoveMobj(mobj->tracer); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } P_BossTargetPlayer(mobj, false); if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first if (!mobj->target) // Still no target, aww. { // Reset the boss. - if (mobj->tracer) - P_RemoveMobj(mobj->tracer); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } P_SetMobjState(mobj, mobj->info->spawnstate); mobj->fuse = 0; mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); @@ -5600,7 +5617,7 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } else if (!mobj->fuse) - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; } // AI goes here. @@ -5627,16 +5644,18 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; // Alter your energy bubble's size/position - if (mobj->health > 3) + if (mobj->health > mobj->info->damage) { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - } + if (mobj->hprev) + { + mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); + P_SetScale(mobj->hprev, mobj->hprev->destscale); - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; + P_TeleportMove(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2); + mobj->hprev->momx = mobj->momx; + mobj->hprev->momy = mobj->momy; + mobj->hprev->momz = mobj->momz; + } // Firin' mah lazors - INDICATOR if (mobj->fuse > TICRATE/2) @@ -5724,6 +5743,7 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, sfx_s3kb3); } } + } // up... mobj->z += mobj->height/2; @@ -5750,12 +5770,12 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { P_SetScale(missile, FRACUNIT/3); - missile->color = SKINCOLOR_GOLD; // sonic cd electric power + missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } else { P_SetScale(missile, FRACUNIT/5); - missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + missile->color = SKINCOLOR_SUNSET; // sonic cd electric power } missile->destscale = missile->scale*2; missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; @@ -5774,8 +5794,10 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 - else + else if (mobj->target->floorz > mobj->floorz) mobj->watertop = mobj->target->floorz + 16*FRACUNIT; + else + mobj->watertop = mobj->floorz + 16*FRACUNIT; if (!(mobj->threshold%4)) { mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); @@ -5867,8 +5889,6 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } - P_SpawnGhostMobj(mobj); - // Pinball attack! if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { @@ -5883,20 +5903,20 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce mobj->threshold--; - P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce! S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->momz = 4*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; mobj->movecount = 0; P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + P_SetMobjState(mobj, mobj->state->nextstate); S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time @@ -5913,6 +5933,8 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } + P_SpawnGhostMobj(mobj)->colorized = false; + // Vector form dodge! mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); @@ -6009,7 +6031,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); - P_SetTarget(&mobj->tracer, shield); + P_SetTarget(&mobj->hprev, shield); P_SetTarget(&shield->target, mobj); // Attack 2: Energy shot! @@ -6040,14 +6062,15 @@ static void P_Boss9Thinker(mobj_t *mobj) } else { - mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); + /*mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); shield->height -= 20*FRACUNIT; // different offset... - P_SetMobjState(shield, S_MSSHIELD_F2); + P_SetMobjState(shield, S_MSSHIELD_F2);*/ + P_SetMobjState(mobj, S_METALSONIC_BOUNCE); //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... } - mobj->fuse = 4*TICRATE; + mobj->fuse = 3*TICRATE; mobj->flags |= MF_PAIN; if (mobj->info->attacksound) S_StartSound(mobj, mobj->info->attacksound); @@ -6058,14 +6081,14 @@ static void P_Boss9Thinker(mobj_t *mobj) case 2: { // We're all charged and ready now! Unleash the fury!! - mobj_t *removemobj = mobj->tracer; S_StopSound(mobj); - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } if (mobj->health <= mobj->info->damage) { - mobj_t *whoosh; - // Attack 1: Pinball dash! if (mobj->health == 1) mobj->movedir = 0; @@ -6078,9 +6101,13 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->threshold = 12; // bounce 12 times else mobj->threshold = 24; // bounce 24 times - mobj->watertop = mobj->target->floorz + 16*FRACUNIT; + if (mobj->floorz >= mobj->target->floorz) + mobj->watertop = mobj->floorz + 16*FRACUNIT; + else + mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); +#if 0 whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct whoosh->frame = FF_FULLBRIGHT; whoosh->sprite = SPR_ARMA; @@ -6088,9 +6115,13 @@ static void P_Boss9Thinker(mobj_t *mobj) whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); whoosh->height = 38*whoosh->scale; whoosh->fuse = 10; - whoosh->color = SKINCOLOR_MAGENTA; + whoosh->color = SKINCOLOR_SUNSET; whoosh->colorized = true; whoosh->flags |= MF_NOCLIPHEIGHT; +#endif + + P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); + P_SetScale(mobj->tracer, mobj->scale << 1); } else { @@ -6102,10 +6133,13 @@ static void P_Boss9Thinker(mobj_t *mobj) } case 3: // Return to idle. - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + if (mobj->floorz >= mobj->target->floorz) + mobj->watertop = mobj->floorz + 32*FRACUNIT; + else + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; P_SetMobjState(mobj, mobj->info->spawnstate); mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; break; } mobj->movecount++; @@ -8264,6 +8298,20 @@ void P_MobjThinker(mobj_t *mobj) P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); } break; + case MT_METALSONIC_RACE: + { + if (!(mobj->fuse % 8)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); + } default: break; } @@ -8399,7 +8447,7 @@ void P_MobjThinker(mobj_t *mobj) } } break; - case MT_BUBBLEBUZZ: + case MT_BUGGLE: mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn { if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 @@ -8413,6 +8461,9 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % mobj->info->painchance == 0) S_StartSound(mobj, mobj->info->activesound); + + if ((statenum_t)(mobj->state-states) != mobj->info->seestate) + P_SetMobjState(mobj, mobj->info->seestate); } else { @@ -8421,6 +8472,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->momx >>= 1; mobj->momy >>= 1; mobj->momz >>= 1; + if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) + P_SetMobjState(mobj, mobj->info->spawnstate); } } break; @@ -8706,11 +8759,17 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->fuse == 59) { + boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); P_UnsetThingPosition(mobj); mobj->x = jetx; mobj->y = jety; + mobj->destscale = mobj->target->scale; + if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE)) + { + mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; + } if (mobj->target->eflags & MFE_VERTICALFLIP) mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; else @@ -8718,6 +8777,14 @@ void P_MobjThinker(mobj_t *mobj) mobj->floorz = mobj->z; mobj->ceilingz = mobj->z+mobj->height; P_SetThingPosition(mobj); + if (dashmod) + { + mobj->color = SKINCOLOR_SUNSET; + if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) + P_SpawnGhostMobj(mobj); + } + else + mobj->color = SKINCOLOR_ICY; } mobj->fuse++; } @@ -10402,8 +10469,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (nummaprings >= 0) nummaprings++; break; - case MT_METALSONIC_BATTLE: case MT_METALSONIC_RACE: + mobj->skin = &skins[5]; + /* FALLTHRU */ + case MT_METALSONIC_BATTLE: + mobj->color = skins[5].prefcolor; sc = 5; break; case MT_FANG: @@ -10474,6 +10544,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (!(mobj->flags & MF_NOTHINK)) P_AddThinker(THINK_MOBJ, &mobj->thinker); + if (mobj->skin) // correct inadequecies above. + { + mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL); + mobj->frame &= ~FF_FRAMEMASK; + } + // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) { @@ -11256,6 +11332,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) } if (mthing->options & MTF_AMBUSH) P_SetPlayerMobjState(mobj, S_PLAY_FALL); + else if (metalrecording) + P_SetPlayerMobjState(mobj, S_PLAY_WAIT); } else z = floor; @@ -12444,10 +12522,10 @@ ML_EFFECT5 : Don't stop thinking when too far away if (mthing->extrainfo) mobj->extravalue1 = mthing->extrainfo; break; - case MT_TRAPGOYLE: - case MT_TRAPGOYLEUP: - case MT_TRAPGOYLEDOWN: - case MT_TRAPGOYLELONG: + case MT_GLAREGOYLE: + case MT_GLAREGOYLEUP: + case MT_GLAREGOYLEDOWN: + case MT_GLAREGOYLELONG: if (mthing->angle >= 360) mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay break; diff --git a/src/p_setup.c b/src/p_setup.c index 86beccd9b93f2f35310cc48f5b1fd395b37be690..c55dcec5e5bed970a29edde3208494f8c1e32263 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -76,6 +76,7 @@ #ifdef HWRENDER #include "hardware/hw_main.h" #include "hardware/hw_light.h" +#include "hardware/hw_model.h" #endif #ifdef ESLOPE @@ -548,52 +549,118 @@ size_t P_PrecacheLevelFlats(void) flatmemory = 0; for (i = 0; i < numlevelflats; i++) { - lump = levelflats[i].lumpnum; - if (devparm) - flatmemory += W_LumpLength(lump); - R_GetFlat(lump); + if (levelflats[i].type == LEVELFLAT_FLAT) + { + lump = levelflats[i].u.flat.lumpnum; + if (devparm) + flatmemory += W_LumpLength(lump); + R_GetFlat(lump); + } } return flatmemory; } -// Auxiliary function. Find a flat in the active wad files, -// allocate an id for it, and set the levelflat (to speedup search) -INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) +/* +levelflat refers to an array of level flats, +or NULL if we want to allocate it now. +*/ +static INT32 +Ploadflat (levelflat_t *levelflat, const char *flatname) { - size_t i; - - // Scan through the already found flats, break if it matches. - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name, flatname, 8) == 0) - break; + UINT8 buffer[8]; - // If there is no match, make room for a new flat. - if (i == numlevelflats) - { - // Store the name. - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); + lumpnum_t flatnum; + int texturenum; - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - levelflat->texturenum = R_CheckTextureNumForName(flatname); - levelflat->lasttexturenum = levelflat->texturenum; + size_t i; - levelflat->baselumpnum = LUMPERROR; - levelflat->basetexturenum = -1; + if (levelflat) + { + // Scan through the already found flats, return if it matches. + for (i = 0; i < numlevelflats; i++) + { + if (strnicmp(levelflat[i].name, flatname, 8) == 0) + return i; + } + } #ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); + CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); #endif - numlevelflats++; + if (numlevelflats >= MAXLEVELFLATS) + I_Error("Too many flats in level\n"); - if (numlevelflats >= MAXLEVELFLATS) - I_Error("Too many flats in level\n"); + if (levelflat) + levelflat += numlevelflats; + else + { + // allocate new flat memory + levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); + levelflat = levelflats + numlevelflats; } - // level flat id - return (INT32)i; + // Store the name. + strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); + strupr(levelflat->name); + + /* If we can't find a flat, try looking for a texture! */ + if (( flatnum = R_GetFlatNumForName(flatname) ) == LUMPERROR) + { + if (( texturenum = R_CheckTextureNumForName(flatname) ) == -1) + { + // check for REDWALL + if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1) + goto texturefound; + // check for REDFLR + else if (( flatnum = R_GetFlatNumForName("REDFLR") ) != LUMPERROR) + goto flatfound; + // nevermind + levelflat->type = LEVELFLAT_NONE; + } + else + { +texturefound: + levelflat->type = LEVELFLAT_TEXTURE; + levelflat->u.texture. num = texturenum; + levelflat->u.texture.lastnum = texturenum; + /* start out unanimated */ + levelflat->u.texture.basenum = -1; + } + } + else + { +flatfound: + /* This could be a flat, patch, or PNG. */ + if (R_CheckIfPatch(flatnum)) + levelflat->type = LEVELFLAT_PATCH; + else + { +#ifndef NO_PNG_LUMPS + /* + Only need eight bytes for PNG headers. + FIXME: Put this elsewhere. + */ + W_ReadLumpHeader(flatnum, buffer, 8, 0); + if (R_IsLumpPNG(buffer, W_LumpLength(flatnum))) + levelflat->type = LEVELFLAT_PNG; + else +#endif/*NO_PNG_LUMPS*/ + levelflat->type = LEVELFLAT_FLAT;/* phew */ + } + + levelflat->u.flat. lumpnum = flatnum; + levelflat->u.flat.baselumpnum = LUMPERROR; + } + + return ( numlevelflats++ ); +} + +// Auxiliary function. Find a flat in the active wad files, +// allocate an id for it, and set the levelflat (to speedup search) +INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) +{ + return Ploadflat(levelflat, flatname); } // help function for Lua and $$$.sav reading @@ -602,44 +669,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // INT32 P_AddLevelFlatRuntime(const char *flatname) { - size_t i; - levelflat_t *levelflat = levelflats; - - // - // first scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - // that flat was already found in the level, return the id - if (i == numlevelflats) - { - // allocate new flat memory - levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); - levelflat = levelflats+i; - - // store the name - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - levelflat->texturenum = R_CheckTextureNumForName(flatname); - levelflat->lasttexturenum = levelflat->texturenum; - - levelflat->baselumpnum = LUMPERROR; - levelflat->basetexturenum = -1; - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; - } - - // level flat id - return (INT32)i; + return Ploadflat(0, flatname); } // help function for $$$.sav checking @@ -3476,6 +3506,10 @@ boolean P_AddWadFile(const char *wadfilename) R_LoadSpriteInfoLumps(wadnum, numlumps); +#ifdef HWRENDER + HWR_ReloadModels(); +#endif + // reload status bar (warning should have valid player!) if (gamestate == GS_LEVEL) ST_Start(); diff --git a/src/p_setup.h b/src/p_setup.h index 7e3a149eb882965e436dbc4ff4327d0fcefa8a00..d8787073b08c823630e4cc41d1484f3ec8bd2c3b 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -30,20 +30,51 @@ extern boolean levelloading; extern UINT8 levelfadecol; extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame + +/* for levelflat type */ +enum +{ + LEVELFLAT_NONE,/* HOM time my friend */ + LEVELFLAT_FLAT, + LEVELFLAT_PATCH, +#ifndef NO_PNG_LUMPS + LEVELFLAT_PNG, +#endif + LEVELFLAT_TEXTURE, +}; + // // MAP used flats lookup table // typedef struct { char name[9]; // resource name from wad - lumpnum_t lumpnum; // lump number of the flat - INT32 texturenum, lasttexturenum; // texture number of the flat + + UINT8 type; + union + { + struct + { + lumpnum_t lumpnum; // lump number of the flat + // for flat animation + lumpnum_t baselumpnum; + } + flat; + struct + { + INT32 num; + INT32 lastnum; // texture number of the flat + // for flat animation + INT32 basenum; + } + texture; + } + u; + UINT16 width, height; fixed_t topoffset, leftoffset; // for flat animation - lumpnum_t baselumpnum; - INT32 basetexturenum; INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; diff --git a/src/p_spec.c b/src/p_spec.c index 366377bedbf926228dc5253173ece07678f8dccd..d6a8cb48e4979f2d14ecb29bbbe6b5549ad0e0f0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -464,11 +464,11 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1) - && ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum)) + if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) + && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) { - foundflats->basetexturenum = startflatnum; - foundflats->animseq = foundflats->texturenum - startflatnum; + foundflats->u.texture.basenum = startflatnum; + foundflats->animseq = foundflats->u.texture.num - startflatnum; foundflats->numpics = endflatnum - startflatnum + 1; foundflats->speed = anims[animnum].speed; @@ -476,10 +476,10 @@ static inline void P_FindAnimatedFlat(INT32 animnum) atoi(sizeu1(i)), foundflats->name, foundflats->animseq, foundflats->numpics,foundflats->speed); } - else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) + else if (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum) { - foundflats->baselumpnum = startflatnum; - foundflats->animseq = foundflats->lumpnum - startflatnum; + foundflats->u.flat.baselumpnum = startflatnum; + foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; foundflats->numpics = endflatnum - startflatnum + 1; foundflats->speed = anims[animnum].speed; @@ -5589,11 +5589,11 @@ void P_UpdateSpecials(void) if (foundflats->speed) // it is an animated flat { // update the levelflat texture number - if (foundflats->basetexturenum != -1) - foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + if (foundflats->type == LEVELFLAT_TEXTURE) + foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number - else if (foundflats->baselumpnum != LUMPERROR) - foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) + foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } diff --git a/src/p_user.c b/src/p_user.c index d5d8c6ccdc5371afc50594a1dd2a96784a29f5b0..216ca770b55eba9be3c226f5d602159859ecb63e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2050,8 +2050,7 @@ void P_SpawnThokMobj(player_t *player) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; + P_SetScale(mobj, (mobj->destscale = player->mo->scale)); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -2061,8 +2060,7 @@ void P_SpawnThokMobj(player_t *player) } P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do - if (demorecording) - G_GhostAddThok(); + G_GhostAddThok(); } // @@ -2265,7 +2263,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) else if (!player->skidtime) player->pflags &= ~PF_GLIDING; } - else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && (~player->pflags) & PF_SHIELDABILITY) + else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & PF_SHIELDABILITY) && player->mo->state-states == S_PLAY_FALL) { if (player->mo->state-states != S_PLAY_GLIDE_LANDING) { @@ -4576,8 +4574,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. { P_SpawnSpinMobj(player, player->revitem); - if (demorecording) - G_GhostAddRev(); + G_GhostAddRev(); } } @@ -5305,14 +5302,23 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // Now Knuckles-type abilities are checked. if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { - INT32 glidespeed = player->actionspd; + fixed_t glidespeed = FixedMul(player->actionspd, player->mo->scale); + fixed_t playerspeed = player->speed; + + if (player->mo->eflags & MFE_UNDERWATER) + { + glidespeed >>= 1; + playerspeed >>= 1; + player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; + } player->pflags |= PF_GLIDING|PF_THOKKED; player->glidetime = 0; P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); - if (player->speed < glidespeed) - P_Thrust(player->mo, player->mo->angle, glidespeed - player->speed); + if (playerspeed < glidespeed) + P_Thrust(player->mo, player->mo->angle, glidespeed - playerspeed); player->pflags &= ~(PF_SPINNING|PF_STARTDASH); } break; @@ -5972,7 +5978,12 @@ static void P_3dMovement(player_t *player) if (player->climbing) { if (cmd->forwardmove) - P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); + { + if (player->mo->eflags & MFE_UNDERWATER) + P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 10*FRACUNIT), false); + else + P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); + } } else if (!analogmove && cmd->forwardmove != 0 && !(player->pflags & PF_GLIDING || player->exiting @@ -6006,7 +6017,12 @@ static void P_3dMovement(player_t *player) } // Sideways movement if (player->climbing) - P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1)); + { + if (player->mo->eflags & MFE_UNDERWATER) + P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 10*FRACUNIT)); + else + P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1)); + } // Analog movement control else if (analogmove) { @@ -8361,8 +8377,7 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED)) { P_SpawnSpinMobj(player, player->spinitem); - if (demorecording) - G_GhostAddSpin(); + G_GhostAddSpin(); } @@ -11129,6 +11144,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) } fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it + fume->eflags = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity! // Finally, set its position @@ -11137,10 +11153,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_UnsetThingPosition(fume); fume->x = mo->x + P_ReturnThrustX(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); - if (fume->eflags & MFE_VERTICALFLIP) - fume->z = mo->z + ((mo->height + fume->height) >> 1); - else - fume->z = mo->z + ((mo->height - fume->height) >> 1); + fume->z = mo->z + ((mo->height - fume->height) >> 1); P_SetThingPosition(fume); } @@ -11532,7 +11545,7 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { - angle_t diff = 0; + angle_t oldang = player->drawangle, diff = 0; UINT8 factor; // Directionchar! // Camera angle stuff. @@ -11546,6 +11559,13 @@ void P_PlayerThink(player_t *player) player->drawangle = player->mo->angle; else if (P_PlayerInPain(player)) ; + else if (player->powers[pw_justsprung]) // restricted, potentially by lua + { +#ifdef SPRINGSPIN + if (player->powers[pw_justsprung] & (1<<15)) + player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1); +#endif + } else if (player->powers[pw_carry] && player->mo->tracer) // carry { switch (player->powers[pw_carry]) @@ -11583,13 +11603,6 @@ void P_PlayerThink(player_t *player) break; } } - else if (player->powers[pw_justsprung]) - { -#ifdef SPRINGSPIN - if (player->powers[pw_justsprung] & (1<<15)) - player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1); -#endif - } else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime) @@ -11650,6 +11663,22 @@ void P_PlayerThink(player_t *player) player->drawangle += diff; } + // reset from waiting to standing when turning on the spot + if (player->panim == PA_IDLE) + { + diff = player->drawangle - oldang; + if (diff > ANGLE_180) + diff = InvAngle(diff); + if (diff > ANG10/2) + { + statenum_t stat = player->mo->state-states; + if (stat == S_PLAY_WAIT) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + else if (stat == S_PLAY_STND && player->mo->tics != -1) + player->mo->tics++; + } + } + // Autobrake! check ST_drawInput if you modify this { boolean currentlyonground = P_IsObjectOnGround(player->mo); @@ -11888,8 +11917,8 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_SLIDING; #define dashmode player->dashmode - // Dash mode - thanks be to Iceman404 - if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. + // Dash mode - thanks be to VelocitOni + if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho. { boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale); boolean floating = (player->secondjump == 1); @@ -11899,12 +11928,16 @@ void P_PlayerThink(player_t *player) if (dashmode < DASHMODE_MAX) dashmode++; // Counter. Adds 1 to dash mode per tic in top speed. if (dashmode == DASHMODE_THRESHOLD) // This isn't in the ">=" equation because it'd cause the sound to play infinitely. - S_StartSound(player->mo, sfx_s3ka2); // If the player enters dashmode, play this sound on the the tic it starts. + S_StartSound(player->mo, (player->charflags & SF_MACHINE) ? sfx_kc4d : sfx_cdfm40); // If the player enters dashmode, play this sound on the the tic it starts. } else if ((!totallyradical || !floating) && !(player->pflags & PF_SPINNING)) { if (dashmode > 3) + { dashmode -= 3; // Rather than lose it all, it gently counts back down! + if ((dashmode+3) >= DASHMODE_THRESHOLD && dashmode < DASHMODE_THRESHOLD) + S_StartSound(player->mo, sfx_kc65); + } else dashmode = 0; } @@ -11935,6 +11968,7 @@ void P_PlayerThink(player_t *player) { player->normalspeed = skins[player->skin].normalspeed; player->jumpfactor = skins[player->skin].jumpfactor; + S_StartSound(player->mo, sfx_kc65); } dashmode = 0; } diff --git a/src/r_data.c b/src/r_data.c index 68fee3d64d6e47d3571e5ed44bfd42d190130dc2..d9d8a8f3054ee5ab1431a8e52ac86e1588264890 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -435,6 +435,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; + boolean dealloc = false; int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; @@ -466,10 +467,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - { - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); goto multipatch; - } #endif // Check the patch for holes. @@ -558,9 +556,14 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + dealloc = false; + #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + { realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); + dealloc = true; + } #endif x1 = patch->originx; @@ -598,6 +601,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height); } + + if (dealloc) + Z_Free(realpatch); } done: @@ -1429,48 +1435,6 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } - // Detect textures - if (lump == LUMPERROR) - { - // Scan wad files backwards so patched textures take preference. - for (i = numwadfiles - 1; i >= 0; i--) - { - switch (wadfiles[i]->type) - { - case RET_WAD: - if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) - continue; - break; - case RET_PK3: - if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) - continue; - break; - default: - continue; - } - - // Now find lump with specified name in that range. - lump = W_CheckNumForNamePwad(name, (UINT16)i, start); - if (lump < end) - { - lump += (i<<16); // found it, in our constraints - break; - } - lump = LUMPERROR; - } - } - - if (lump == LUMPERROR) - { - if (strcmp(name, SKYFLATNAME)) - CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name); - lump = W_CheckNumForName("REDFLR"); - } - return lump; } diff --git a/src/r_draw.c b/src/r_draw.c index bb70a319f0a5137d3f95740e10b77efda06eeed7..6fc8d65994e311780f76d29cd923c1fead9f44da 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -567,8 +567,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U else if (skinnum == TC_METALSONIC) { for (i = 0; i < 6; i++) + { dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i]; + } dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; + for (i = 0; i < 16; i++) + dest_colormap[96+i] = dest_colormap[Color_Index[SKINCOLOR_COBALT-1][i]]; } else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices { diff --git a/src/r_main.c b/src/r_main.c index 9d9d1c39a8c6826b2597070f5fb3d986183b438c..3ed509af568565c95c67a443ab76b5625ff4c840 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1208,7 +1208,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grgammared); CV_RegisterVar(&cv_grfovchange); CV_RegisterVar(&cv_grfog); - CV_RegisterVar(&cv_voodoocompatibility); CV_RegisterVar(&cv_grfogcolor); CV_RegisterVar(&cv_grsoftwarefog); #ifdef ALAM_LIGHTING @@ -1217,7 +1216,8 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grcoronas); CV_RegisterVar(&cv_grcoronasize); #endif - CV_RegisterVar(&cv_grmd2); + CV_RegisterVar(&cv_grmodelinterpolation); + CV_RegisterVar(&cv_grmodels); CV_RegisterVar(&cv_grspritebillboarding); CV_RegisterVar(&cv_grskydome); #endif diff --git a/src/r_plane.c b/src/r_plane.c index 1b4c23b00ab01d0e88ea478e88e797d4ed78b409..a3075c9d845ba4c3ddd74b3f1d9101cc74920d13 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -756,9 +756,9 @@ static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height) static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) { UINT8 *flat; - textureflat_t *texflat = &texflats[levelflat->texturenum]; + textureflat_t *texflat = &texflats[levelflat->u.texture.num]; patch_t *patch = NULL; - boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); + boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false); // Check if the texture changed. if (leveltexture && (!texturechanged)) @@ -780,12 +780,12 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo // Level texture if (leveltexture) { - texture_t *texture = textures[levelflat->texturenum]; + texture_t *texture = textures[levelflat->u.texture.num]; texflat->width = ds_flatwidth = texture->width; texflat->height = ds_flatheight = texture->height; texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight); - R_TextureToFlat(levelflat->texturenum, texflat->flat); + R_TextureToFlat(levelflat->u.texture.num, texflat->flat); flat = texflat->flat; levelflat->flatpatch = flat; @@ -799,7 +799,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo #ifndef NO_PNG_LUMPS if (ispng) { - levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum)); + levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->u.flat.lumpnum)); levelflat->topoffset = levelflat->leftoffset = 0; ds_flatwidth = levelflat->width; ds_flatheight = levelflat->height; @@ -829,7 +829,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo xoffs += levelflat->leftoffset; yoffs += levelflat->topoffset; - levelflat->lasttexturenum = levelflat->texturenum; + levelflat->u.texture.lastnum = levelflat->u.texture.num; return flat; } @@ -839,10 +839,9 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 light = 0; INT32 x; INT32 stop, angle; - size_t size; ffloor_t *rover; levelflat_t *levelflat; - boolean rawflat = false; + int type; if (!(pl->minx <= pl->maxx)) return; @@ -996,43 +995,45 @@ void R_DrawSinglePlane(visplane_t *pl) currentplane = pl; levelflat = &levelflats[pl->picnum]; - size = W_LumpLength(levelflat->lumpnum); - ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag - // Check if the flat is actually a wall texture. - if (levelflat->texturenum != 0 && levelflat->texturenum != -1) - flat = R_GetTextureFlat(levelflat, true, false); + /* :james: */ + type = levelflat->type; + switch (type) + { + case LEVELFLAT_NONE: + return; + case LEVELFLAT_FLAT: + ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); + R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); + // Raw flats always have dimensions that are powers-of-two numbers. + ds_powersoftwo = true; + break; + default: + switch (type) + { + case LEVELFLAT_TEXTURE: + /* Textures get cached differently and don't need ds_source */ + ds_source = R_GetTextureFlat(levelflat, true, false); + break; + default: + ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_STATIC); + flat = R_GetTextureFlat(levelflat, false, #ifndef NO_PNG_LUMPS - // Maybe it's a PNG?! - else if (R_IsLumpPNG(ds_source, size)) - flat = R_GetTextureFlat(levelflat, false, true); + ( type == LEVELFLAT_PNG ) +#else + false #endif - // Maybe it's just a patch, then? - else if (R_CheckIfPatch(levelflat->lumpnum)) - flat = R_GetTextureFlat(levelflat, false, false); - // It's a raw flat. - else - { - rawflat = true; - R_CheckFlatLength(size); - flat = ds_source; - } - - Z_ChangeTag(ds_source, PU_CACHE); - ds_source = flat; - - if (ds_source == NULL) - return; - - // Raw flats always have dimensions that are powers-of-two numbers. - if (rawflat) - ds_powersoftwo = true; - // Otherwise, check if this texture or patch has such dimensions. - else if (R_CheckPowersOfTwo()) - { - R_CheckFlatLength(ds_flatwidth * ds_flatheight); - if (spanfunc == basespanfunc) - spanfunc = mmxspanfunc; + ); + Z_ChangeTag(ds_source, PU_CACHE); + ds_source = flat; + } + // Check if this texture or patch has power-of-two dimensions. + if (R_CheckPowersOfTwo()) + { + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + if (spanfunc == basespanfunc) + spanfunc = mmxspanfunc; + } } if (light >= LIGHTLEVELS) diff --git a/src/r_things.c b/src/r_things.c index 872742d4acafa763e85fa9e3d96a04dc57fda84e..2df80b0c447967271207e5763adf255456214cac 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -520,7 +520,7 @@ void R_AddSpriteDefs(UINT16 wadnum) { #ifdef HWRENDER if (rendermode == render_opengl) - HWR_AddSpriteMD2(i); + HWR_AddSpriteModel(i); #endif // if a new sprite was added (not just replaced) addsprites++; @@ -846,10 +846,13 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); else if (!(vis->cut & SC_PRECIP) && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) + && (vis->mobj->player->charflags & SF_DASHMODE) && ((leveltime/2) & 1)) { - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + if (vis->mobj->player->charflags & SF_MACHINE) + dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); } else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> { @@ -874,10 +877,13 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); else if (!(vis->cut & SC_PRECIP) && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) + && (vis->mobj->player->charflags & SF_DASHMODE) && ((leveltime/2) & 1)) { - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + if (vis->mobj->player->charflags & SF_MACHINE) + dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); } else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { @@ -2686,7 +2692,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; - while (!(skin->sprites[spr2].numframes) + while (!skin->sprites[spr2].numframes && spr2 != SPR2_STND && ++i < 32) // recursion limiter { @@ -2827,6 +2833,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. + || (metalrecording && skinnum == 5) // Force 3. ); } @@ -3315,7 +3322,7 @@ next_token: #ifdef HWRENDER if (rendermode == render_opengl) - HWR_AddPlayerMD2(numskins); + HWR_AddPlayerModel(numskins); #endif numskins++; diff --git a/src/s_sound.c b/src/s_sound.c index 6134e338c2649f5114531364275c70ff518498df..8b87bd08328b9d00e0de2a0f0d4bbbc5b4f9d2e8 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -64,6 +64,8 @@ static void ModFilter_OnChange(void); static lumpnum_t S_GetMusicLumpNum(const char *mname); +static boolean S_CheckQueue(void); + // commands for music and sound servers #ifdef MUSSERV consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1613,13 +1615,14 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi if (!music_stacks) { music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL); - strncpy(music_stacks->musname, (status == JT_MASTER ? mname : mapmusname), 7); - music_stacks->musflags = (status == JT_MASTER ? mflags : mapmusflags); - music_stacks->looping = (status == JT_MASTER ? looping : true); - music_stacks->position = (status == JT_MASTER ? position : S_GetMusicPosition()); + strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7); + music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags)); + music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true)); + music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition())); music_stacks->tic = gametic; music_stacks->status = JT_MASTER; music_stacks->mlumpnum = S_GetMusicLumpNum(music_stacks->musname); + music_stacks->noposition = S_CheckQueue(); if (status == JT_MASTER) return; // we just added the user's entry here @@ -1638,6 +1641,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi new_mst->tic = gametic; new_mst->status = status; new_mst->mlumpnum = S_GetMusicLumpNum(new_mst->musname); + new_mst->noposition = false; mst->next = new_mst; new_mst->prev = mst; @@ -1745,11 +1749,23 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) entry->tic = gametic; entry->status = JT_MASTER; entry->mlumpnum = S_GetMusicLumpNum(entry->musname); + entry->noposition = false; // don't set this until we do the mapmuschanged check, below. Else, this breaks some resumes. } if (entry->status == JT_MASTER) { mapmuschanged = strnicmp(entry->musname, mapmusname, 7); + if (mapmuschanged) + { + strncpy(entry->musname, mapmusname, 7); + entry->musflags = mapmusflags; + entry->looping = true; + entry->position = mapmusposition; + entry->tic = gametic; + entry->status = JT_MASTER; + entry->mlumpnum = S_GetMusicLumpNum(entry->musname); + entry->noposition = true; + } S_ResetMusicStack(); } else if (!entry->status) @@ -1758,7 +1774,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) return false; } - if (!mapmuschanged && strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it + if (strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it { if (music_stack_fadeout) S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0); @@ -1766,7 +1782,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) { S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, 0, music_stack_fadein); - if (!music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize + if (!entry->noposition && !music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize { UINT32 poslapse = 0; @@ -1908,6 +1924,11 @@ static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UIN queue_fadeinms = fadeinms; } +static boolean S_CheckQueue(void) +{ + return queue_name[0]; +} + static void S_ClearQueue(void) { queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0; diff --git a/src/s_sound.h b/src/s_sound.h index 20b2489a5de6fdb75f0d8467b0b2058ee27d9324..c46c9fa089b40b02965c9dd142469543cf1f8fe2 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -220,6 +220,7 @@ typedef struct musicstack_s tic_t tic; UINT16 status; lumpnum_t mlumpnum; + boolean noposition; // force music stack resuming from zero (like music_stack_noposition) struct musicstack_s *prev; struct musicstack_s *next; diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 132661449a8455b76b13bac3990168483ecc45f8..0d1fa1a4b5df7947be1559b1663175c592a087d3 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -229,6 +229,10 @@ <ClInclude Include="..\hardware\hw_light.h" /> <ClInclude Include="..\hardware\hw_main.h" /> <ClInclude Include="..\hardware\hw_md2.h" /> + <ClInclude Include="..\hardware\hw_md2load.h" /> + <ClInclude Include="..\hardware\hw_md3load.h" /> + <ClInclude Include="..\hardware\hw_model.h" /> + <ClInclude Include="..\hardware\u_list.h" /> <ClInclude Include="..\hu_stuff.h" /> <ClInclude Include="..\info.h" /> <ClInclude Include="..\i_addrinfo.h" /> @@ -369,8 +373,12 @@ <ClCompile Include="..\hardware\hw_light.c" /> <ClCompile Include="..\hardware\hw_main.c" /> <ClCompile Include="..\hardware\hw_md2.c" /> + <ClCompile Include="..\hardware\hw_md2load.c" /> + <ClCompile Include="..\hardware\hw_md3load.c" /> + <ClCompile Include="..\hardware\hw_model.c" /> <ClCompile Include="..\hardware\hw_trick.c" /> <ClCompile Include="..\hardware\r_opengl\r_opengl.c" /> + <ClCompile Include="..\hardware\u_list.c" /> <ClCompile Include="..\hu_stuff.c" /> <ClCompile Include="..\info.c" /> <ClCompile Include="..\i_addrinfo.c"> diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 0123986d02c0d0cc2c934034ed50d5dbab871a13..cface637773be2167340011d7eec451d1f251042 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -246,6 +246,18 @@ <ClInclude Include="..\hardware\hw_md2.h"> <Filter>Hw_Hardware</Filter> </ClInclude> + <ClInclude Include="..\hardware\hw_md2load.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> + <ClInclude Include="..\hardware\hw_md3load.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> + <ClInclude Include="..\hardware\hw_model.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> + <ClInclude Include="..\hardware\u_list.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> <ClInclude Include="..\byteptr.h"> <Filter>I_Interface</Filter> </ClInclude> @@ -633,9 +645,21 @@ <ClCompile Include="..\hardware\hw_md2.c"> <Filter>Hw_Hardware</Filter> </ClCompile> + <ClCompile Include="..\hardware\hw_md2load.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> + <ClCompile Include="..\hardware\hw_md3load.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> + <ClCompile Include="..\hardware\hw_model.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> <ClCompile Include="..\hardware\hw_trick.c"> <Filter>Hw_Hardware</Filter> </ClCompile> + <ClCompile Include="..\hardware\u_list.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> <ClCompile Include="..\filesrch.c"> <Filter>I_Interface</Filter> </ClCompile> diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 103398405f1e98518b65157859f39a981836fca1..5f040023a8032e1086ebec70f8a28891a0b741e1 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -88,13 +88,11 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); GETFUNC(GetTextureUsed); - GETFUNC(DrawMD2); - GETFUNC(DrawMD2i); + GETFUNC(DrawModel); + GETFUNC(CreateModelVBOs); GETFUNC(SetTransform); GETFUNC(GetRenderVersion); -#ifdef SHUFFLE GETFUNC(PostImgRedraw); -#endif //SHUFFLE GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d7926e5b2e7ede6b2d1337be8513e8d72bdacd6e..e7f8f2e4f9529e69a243f30defd30e835e7fc514 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2181,7 +2181,7 @@ void I_Quit(void) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); I_ShutdownMusic(); @@ -2299,7 +2299,7 @@ void I_Error(const char *error, ...) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); I_ShutdownMusic(); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 57591af104922eecc821dea8d3973545b6db7775..fb0f4b2ba3eaea01e6881a77f2717672860cb21f 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1654,13 +1654,11 @@ void I_StartupGraphics(void) HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); HWD.pfnSetPalette = hwSym("SetPalette",NULL); HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL); - HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL); + HWD.pfnDrawModel = hwSym("DrawModel",NULL); + HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); -#ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); -#endif HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); diff --git a/src/sounds.c b/src/sounds.c index 8dc97b1e635f302c7b45eb32c00926b3cef68600..791a7571e432b23343fcb39b63ca5a6d9c86bd7f 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -693,7 +693,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, {"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, @@ -780,7 +780,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, @@ -804,7 +804,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Terrifying rumble"}, - {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power down"}, {"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/st_stuff.c b/src/st_stuff.c index 392cb1c03fe4d600a73f226a9d5eafd431ba4afa..139303fbbd41b0e07ca5006aa6a60c5a19edfbf4 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -837,7 +837,13 @@ static void ST_drawLivesArea(void) } // Lives number - if (G_GametypeUsesLives() || gametype == GT_RACE) + if (metalrecording) + { + if (((2*leveltime)/TICRATE) & 1) + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, + hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC"); + } + else if (G_GametypeUsesLives() || gametype == GT_RACE) { // x V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, diff --git a/src/v_video.c b/src/v_video.c index 34d64cb04bca5c1d33119ff767038965bf2cd665..7f99cfd326c8089b878e4624a90c9f0e295edf87 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -89,8 +89,8 @@ static void CV_Gammaxxx_ONChange(void); // but they won't do anything. static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; +static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; -consvar_t cv_voodoocompatibility = {"gr_voodoocompatibility", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -108,9 +108,9 @@ consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif -static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; -// console variables in development -consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grmodels = {"gr_models", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grmodelinterpolation = {"gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif diff --git a/src/w_wad.c b/src/w_wad.c index 5d2d74ef5e1556ecde9bae6ff56d797362327e0a..c9a476508e59e33caffbc6214c55961e6de336dc 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1665,12 +1665,12 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) { char actualmd5text[2*MD5_LEN+1]; PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text); -#ifdef _DEBUG +/*#ifdef _DEBUG CONS_Printf #else I_Error #endif - (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); + (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);*/ } #endif } diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index b4ad5a7b96ca0454682781a6010f4d79aa627871..7a79861b3899f9fffcdd4da9248556c54e9e7bba 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -231,7 +231,11 @@ <ClCompile Include="..\hardware\hw_light.c" /> <ClCompile Include="..\hardware\hw_main.c" /> <ClCompile Include="..\hardware\hw_md2.c" /> + <ClCompile Include="..\hardware\hw_md2load.c" /> + <ClCompile Include="..\hardware\hw_md3load.c" /> + <ClCompile Include="..\hardware\hw_model.c" /> <ClCompile Include="..\hardware\hw_trick.c" /> + <ClCompile Include="..\hardware\u_list.c" /> <ClCompile Include="..\hu_stuff.c" /> <ClCompile Include="..\info.c" /> <ClCompile Include="..\i_addrinfo.c"> @@ -397,6 +401,10 @@ <ClInclude Include="..\hardware\hw_light.h" /> <ClInclude Include="..\hardware\hw_main.h" /> <ClInclude Include="..\hardware\hw_md2.h" /> + <ClInclude Include="..\hardware\hw_md2load.h" /> + <ClInclude Include="..\hardware\hw_md3load.h" /> + <ClInclude Include="..\hardware\hw_model.h" /> + <ClInclude Include="..\hardware\u_list.h" /> <ClInclude Include="..\hu_stuff.h" /> <ClInclude Include="..\info.h" /> <ClInclude Include="..\i_addrinfo.h" /> diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index e1b30dcf926292f22c26672458ad543e46e7143b..3d5c021d4b915f1950b831d2f67ec2a6a3ac78ba 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -453,6 +453,18 @@ <ClCompile Include="..\string.c"> <Filter>M_Misc</Filter> </ClCompile> + <ClCompile Include="..\hardware\hw_md2load.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> + <ClCompile Include="..\hardware\hw_md3load.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> + <ClCompile Include="..\hardware\hw_model.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> + <ClCompile Include="..\hardware\u_list.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> <ClCompile Include="..\hardware\hw_clip.c"> <Filter>Hw_Hardware</Filter> </ClCompile> @@ -516,6 +528,15 @@ <ClInclude Include="..\hardware\hw_md2.h"> <Filter>Hw_Hardware</Filter> </ClInclude> + <ClInclude Include="..\hardware\hw_md2load.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> + <ClInclude Include="..\hardware\hw_md3load.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> + <ClInclude Include="..\hardware\hw_model.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> <ClInclude Include="..\hardware\hw3dsdrv.h"> <Filter>Hw_Hardware</Filter> </ClInclude> @@ -525,6 +546,9 @@ <ClInclude Include="..\hardware\hws_data.h"> <Filter>Hw_Hardware</Filter> </ClInclude> + <ClInclude Include="..\hardware\u_list.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> <ClInclude Include="..\blua\lapi.h"> <Filter>BLUA</Filter> </ClInclude> diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 4ea792a250d353596a20dfb67b006b9ada06ad7f..5378bb52f645bc10abc0c58dcf27d38f15d9b85a 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -110,8 +110,7 @@ static loadfunc_t hwdFuncTable[] = { {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, {"SetSpecialState@8", &hwdriver.pfnSetSpecialState}, - {"DrawMD2@16", &hwdriver.pfnDrawMD2}, - {"DrawMD2i@36", &hwdriver.pfnDrawMD2i}, + {"DrawModel@16", &hwdriver.pfnDrawModel}, {"SetTransform@4", &hwdriver.pfnSetTransform}, {"GetTextureUsed@0", &hwdriver.pfnGetTextureUsed}, {"GetRenderVersion@0", &hwdriver.pfnGetRenderVersion}, @@ -142,8 +141,7 @@ static loadfunc_t hwdFuncTable[] = { {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, {"SetSpecialState", &hwdriver.pfnSetSpecialState}, - {"DrawMD2", &hwdriver.pfnDrawMD2}, - {"DrawMD2i", &hwdriver.pfnDrawMD2i}, + {"DrawModel", &hwdriver.pfnDrawModel}, {"SetTransform", &hwdriver.pfnSetTransform}, {"GetTextureUsed", &hwdriver.pfnGetTextureUsed}, {"GetRenderVersion", &hwdriver.pfnGetRenderVersion}, diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 93b3ff52381998528099495a738236c918351498..c9fdb1c9742fa87a803aed9e88fb1578aceac904 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -647,7 +647,7 @@ void I_Error(const char *error, ...) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); @@ -733,7 +733,7 @@ void I_Quit(void) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET