Commit 6e5f71dd by Jaime Ita Passos

Refactor patch rotation

parent b15bbd50
......@@ -129,6 +129,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_things.c
r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c
r_portal.c
......
......@@ -519,6 +519,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_textures.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_patchrotation.o \
$(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
......
......@@ -4754,7 +4754,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
float gz, gzt;
spritedef_t *sprdef;
spriteframe_t *sprframe;
#ifdef ROTSPRITE
spriteinfo_t *sprinfo;
#endif
md2_t *md2;
size_t lumpoff;
unsigned rot;
......@@ -4824,12 +4826,16 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->skin && thing->sprite == SPR_PLAY)
{
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2];
#ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2];
#endif
}
else
{
sprdef = &sprites[thing->sprite];
sprinfo = NULL;
#ifdef ROTSPRITE
sprinfo = &spriteinfo[thing->sprite];
#endif
}
if (rot >= sprdef->numframes)
......@@ -4839,7 +4845,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
sprinfo = NULL;
#ifdef ROTSPRITE
sprinfo = &spriteinfo[thing->sprite];
#endif
rot = thing->frame&FF_FRAMEMASK;
thing->state->sprite = thing->sprite;
thing->state->frame = thing->frame;
......@@ -4901,9 +4909,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->rollangle)
{
rollangle = R_GetRollAngle(thing->rollangle);
if (sprframe->rotsprite.patch[rot][rollangle] == NULL)
R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, rollangle, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle);
if (rotsprite != NULL)
{
spr_width = SHORT(rotsprite->width) << FRACBITS;
......
......@@ -458,9 +458,8 @@ static int libd_getSpritePatch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (sprframe->rotsprite.patch[angle][rot] == NULL)
R_CacheRotSprite(i, frame, NULL, sprframe, angle, rot, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &spriteinfo[i], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
......@@ -571,9 +570,8 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (sprframe->rotsprite.patch[angle][rot] == NULL)
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, rot, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i].sprinfo[j], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
......
......@@ -4091,7 +4091,7 @@ boolean P_LoadLevel(boolean fromnetsave)
R_FlushTranslationColormapCache();
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
Patch_FreeTag(PU_SPRITE_ROTATED);
Patch_FreeTag(PU_PATCH_ROTATED);
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
#if defined (WALLSPLATS) || defined (FLOORSPLATS)
......@@ -4479,7 +4479,7 @@ boolean P_AddWadFile(const char *wadfilename)
// search for sprite replacements
//
Patch_FreeTag(PU_SPRITE);
Patch_FreeTag(PU_SPRITE_ROTATED);
Patch_FreeTag(PU_PATCH_ROTATED);
R_AddSpriteDefs(wadnum);
// Reload it all anyway, just in case they
......
......@@ -652,6 +652,14 @@ typedef enum
RGBA32 = 4, // 32 bit rgba
} pic_mode_t;
#ifdef ROTSPRITE
typedef struct
{
INT32 angles;
void **patches;
} rotsprite_t;
#endif
// Patches.
// A patch holds one or more columns.
// Patches are used for sprites and all masked pictures, and we compose
......@@ -666,6 +674,10 @@ typedef struct
UINT8 *columns; // Software column data
void *hardware; // OpenGL patch, allocated whenever necessary
#ifdef ROTSPRITE
rotsprite_t *rotated; // Rotated patches
#endif
} patch_t;
#if defined(_MSC_VER)
......@@ -706,14 +718,6 @@ typedef struct
#pragma pack()
#endif
// rotsprite
#ifdef ROTSPRITE
typedef struct
{
patch_t *patch[16][ROTANGLES];
} rotsprite_t;
#endif/*ROTSPRITE*/
typedef enum
{
SRF_SINGLE = 0, // 0-angle for all rotations
......@@ -755,7 +759,7 @@ typedef struct
UINT16 flip;
#ifdef ROTSPRITE
rotsprite_t rotsprite;
rotsprite_t *rotated[16]; // Rotated patches
#endif
} spriteframe_t;
......
......@@ -37,7 +37,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
patch->height = source->height;
patch->leftoffset = source->leftoffset;
patch->topoffset = source->topoffset;
patch->columnofs = Z_Calloc(size, PU_PATCH, NULL);
patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL);
for (col = 0; col < source->width; col++)
{
......@@ -53,7 +53,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
if (colsize <= 0)
I_Error("R_CreatePatch: no column data!");
patch->columns = Z_Calloc(colsize, PU_PATCH, NULL);
patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL);
M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize);
}
......@@ -71,6 +71,23 @@ static void Patch_FreeData(patch_t *patch)
HWR_FreeTexture(patch);
#endif
#ifdef ROTSPRITE
if (patch->rotated)
{
rotsprite_t *rotsprite = patch->rotated;
INT32 i = 0;
for (; i < rotsprite->angles; i++)
{
if (rotsprite->patches[i])
Patch_Free(rotsprite->patches[i]);
}
Z_Free(rotsprite->patches);
Z_Free(rotsprite);
}
#endif
if (patch->columnofs)
Z_Free(patch->columnofs);
if (patch->columns)
......
......@@ -27,4 +27,12 @@ void *Patch_AllocateHardwarePatch(patch_t *patch);
void *Patch_CreateGL(patch_t *patch);
#endif
#ifdef ROTSPRITE
void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip);
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip);
patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle);INT32 R_GetRollAngle(angle_t rollangle);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
#endif
#endif // __R_PATCH__
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_patchrotation.c
/// \brief Patch rotation.
#include "r_patch.h"
#include "r_picformats.h"
#include "r_things.h" // FEETADJUST
#include "z_zone.h"
#include "w_wad.h"
#ifdef ROTSPRITE
static rotsprite_t *RotatedPatch_Create(INT32 numangles);
static void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip);
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
INT32 R_GetRollAngle(angle_t rollangle)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
{
rotsprite_t *rotsprite = patch->rotated;
if (rotsprite == NULL || angle < 1 || angle >= ROTANGLES)
return NULL;
if (flip)
angle += rotsprite->angles;
return rotsprite->patches[angle];
}
patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle)
{
rotsprite_t *rotsprite = sprite->rotated[spriteangle];
spriteinfo_t *sprinfo = (spriteinfo_t *)info;
INT32 idx = rotationangle;
if (rotationangle < 1 || rotationangle >= ROTANGLES)
return NULL;
if (rotsprite == NULL)
{
rotsprite = RotatedPatch_Create(ROTANGLES);
sprite->rotated[spriteangle] = rotsprite;
}
if (flip)
idx += rotsprite->angles;
if (rotsprite->patches[idx] == NULL)
{
patch_t *patch;
INT32 xpivot = 0, ypivot = 0;
lumpnum_t lump = sprite->lumppat[spriteangle];
if (lump == LUMPERROR)
return NULL;
patch = W_CachePatchNum(lump, PU_SPRITE);
if (sprinfo->available)
{
xpivot = sprinfo->pivot[frame].x;
ypivot = sprinfo->pivot[frame].y;
}
else
{
xpivot = patch->leftoffset;
ypivot = patch->height / 2;
}
RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip);
}
return rotsprite->patches[idx];
}
void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
{
if (patch->rotated == NULL)
patch->rotated = RotatedPatch_Create(ROTANGLES);
RotatedPatch_DoRotation(patch->rotated, patch, angle, xpivot, ypivot, flip);
}
rotsprite_t *RotatedPatch_Create(INT32 numangles)
{
rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL);
rotsprite->angles = numangles;
rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL);
return rotsprite;
}
void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
{
patch_t *rotated;
UINT16 *rawdst;
size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
INT32 width = patch->width;
INT32 height = patch->height;
INT32 leftoffset = patch->leftoffset;
INT32 newwidth, newheight;
INT32 dx, dy;
fixed_t ca = rollcosang[angle];
fixed_t sa = rollsinang[angle];
INT32 idx = angle;
// Don't cache angle = 0
if (angle < 1 || angle >= ROTANGLES)
return;
#define ROTSPRITE_XCENTER (newwidth / 2)
#define ROTSPRITE_YCENTER (newheight / 2)
if (flip)
idx += rotsprite->angles;
if (rotsprite->patches[idx])
return;
if (bflip)
{
xpivot = width - xpivot;
leftoffset = width - leftoffset;
}
// Find the dimensions of the rotated patch.
{
INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa));
INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa));
INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca));
INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
newwidth = max(width, max(w1, w2));
newheight = max(height, max(h1, h2));
}
// check boundaries
{
fixed_t top[2][2];
fixed_t bottom[2][2];
top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
top[0][0] >>= FRACBITS;
top[0][1] >>= FRACBITS;
top[1][0] >>= FRACBITS;
top[1][1] >>= FRACBITS;
bottom[0][0] >>= FRACBITS;
bottom[0][1] >>= FRACBITS;
bottom[1][0] >>= FRACBITS;
bottom[1][1] >>= FRACBITS;
#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width)
#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height)
#define BOUNDARYADJUST(x) x *= 2
// top left/right
if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1]))
BOUNDARYADJUST(newwidth);
// bottom left/right
else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1]))
BOUNDARYADJUST(newwidth);
// top left/right
if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1]))
BOUNDARYADJUST(newheight);
// bottom left/right
else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1]))
BOUNDARYADJUST(newheight);
#undef BOUNDARYWCHECK
#undef BOUNDARYHCHECK
#undef BOUNDARYADJUST
}
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
size = (width * height);
rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{
INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS;
INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS;
INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (xpivot << FRACBITS);
INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (ypivot << FRACBITS);
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip);
if (input != NULL)
rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input));
}
}
}
// make patch
rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0);
Z_ChangeTag(rotated, PU_PATCH_ROTATED);
Z_SetUser(rotated, (void **)(&rotsprite->patches[angle]));
rotated->leftoffset = (rotated->width / 2) + (leftoffset - xpivot);
rotated->topoffset = (rotated->height / 2) + (patch->topoffset - ypivot);
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
rotated->topoffset += FEETADJUST>>FRACBITS;
// free rotated image data
Z_Free(rawdst);
#undef ROTSPRITE_XCENTER
#undef ROTSPRITE_YCENTER
}
#endif
......@@ -17,11 +17,10 @@
#include "i_video.h"
#include "r_data.h"
#include "r_patch.h"
#include "r_textures.h"
#include "r_draw.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_textures.h"
#include "r_things.h"
#include "r_draw.h"
#include "v_video.h"
#include "z_zone.h"
#include "w_wad.h"
......@@ -1672,192 +1671,3 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps)
R_ParseSPRTINFOLump(wadnum, i);
}
}
#ifdef ROTSPRITE
//
// R_GetRollAngle
//
// Angles precalculated in R_InitSprites.
//
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
INT32 R_GetRollAngle(angle_t rollangle)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
//
// R_CacheRotSprite
//
// Create a rotated sprite.
//
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip)
{
patch_t *patch, *newpatch;
UINT16 *rawdst;
size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
// Don't cache angle = 0
if (angle < 1 || angle >= ROTANGLES)
return;
#define SPRITE_XCENTER (leftoffset)
#define SPRITE_YCENTER (height / 2)
#define ROTSPRITE_XCENTER (newwidth / 2)
#define ROTSPRITE_YCENTER (newheight / 2)
if (sprframe->rotsprite.patch[rot][angle] == NULL)
{
INT32 dx, dy;
INT32 px, py;
INT32 width, height, leftoffset;
INT32 newwidth, newheight;
fixed_t ca, sa;
lumpnum_t lump = sprframe->lumppat[rot];
if (lump == LUMPERROR)
return;
patch = (patch_t *)W_CachePatchNum(lump, PU_STATIC);
width = patch->width;
height = patch->height;
leftoffset = patch->leftoffset;
// rotation pivot
px = SPRITE_XCENTER;
py = SPRITE_YCENTER;
// get correct sprite info for sprite
if (sprinfo == NULL)
sprinfo = &spriteinfo[sprnum];
if (sprinfo->available)
{
px = sprinfo->pivot[frame].x;
py = sprinfo->pivot[frame].y;
}
if (bflip)
{
px = width - px;
leftoffset = width - leftoffset;
}
ca = rollcosang[angle];
sa = rollsinang[angle];
// Find the dimensions of the rotated patch.
{
INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa));
INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa));
INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca));
INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
newwidth = max(width, max(w1, w2));
newheight = max(height, max(h1, h2));
}
// check boundaries
{
fixed_t top[2][2];
fixed_t bottom[2][2];
top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[0][0] >>= FRACBITS;
top[0][1] >>= FRACBITS;
top[1][0] >>= FRACBITS;
top[1][1] >>= FRACBITS;
bottom[0][0] >>= FRACBITS;
bottom[0][1] >>= FRACBITS;
bottom[1][0] >>= FRACBITS;
bottom[1][1] >>= FRACBITS;
#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width)
#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height)
#define BOUNDARYADJUST(x) x *= 2
// top left/right
if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1]))
BOUNDARYADJUST(newwidth);
// bottom left/right
else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1]))
BOUNDARYADJUST(newwidth);
// top left/right
if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1]))
BOUNDARYADJUST(newheight);
// bottom left/right
else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1]))
BOUNDARYADJUST(newheight);
#undef BOUNDARYWCHECK
#undef BOUNDARYHCHECK
#undef BOUNDARYADJUST
}
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
size = (width * height);
rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{
INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS;
INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS;
INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS);
INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS);
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip);
if (input != NULL)
rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input));
}
}
}
// make patch
newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0);
Z_ChangeTag(newpatch, PU_SPRITE_ROTATED);
{
newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px);
newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py);
}
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (rendermode != render_none) // not for psprite
newpatch->topoffset += FEETADJUST>>FRACBITS;
// P_PrecacheLevel
if (devparm) spritememory += size;
Z_SetUser(newpatch, &sprframe->rotsprite.patch[rot][angle]);
// free rotated image data
Z_Free(rawdst);
}
#undef SPRITE_XCENTER
#undef SPRITE_YCENTER
#undef ROTSPRITE_XCENTER
#undef ROTSPRITE_YCENTER
}
#endif
......@@ -125,12 +125,4 @@ extern spriteinfo_t spriteinfo[NUMSPRITES];
void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps);
void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
#endif
#endif // __R_PICFORMATS__
......@@ -97,7 +97,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
{
char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging
INT32 r, ang;
INT32 r;
lumpnum_t lumppat = wad;
lumppat <<= 16;
lumppat += lump;
......@@ -105,14 +105,10 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (maxframe ==(size_t)-1 || frame > maxframe)
maxframe = frame;
// rotsprite
#ifdef ROTSPRITE
for (r = 0; r < 16; r++)
{
for (ang = 0; ang < ROTANGLES; ang++)
sprtemp[frame].rotsprite.patch[r][ang] = NULL;
}
#endif/*ROTSPRITE*/
sprtemp[frame].rotated[r] = NULL;
#endif
if (rotation == 0)
{
......@@ -1454,7 +1450,7 @@ static void R_ProjectSprite(mobj_t *thing)
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
#ifdef ROTSPRITE
sprinfo = NULL;