mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-03-17 00:11:05 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
34f9f794d4
36 changed files with 1575 additions and 1654 deletions
|
@ -507,7 +507,6 @@ set( PLAT_SDL_SOURCES
|
|||
posix/sdl/i_joystick.cpp
|
||||
posix/sdl/i_main.cpp
|
||||
posix/sdl/i_system.cpp
|
||||
posix/sdl/i_timer.cpp
|
||||
posix/sdl/sdlvideo.cpp
|
||||
posix/sdl/sdlglvideo.cpp
|
||||
posix/sdl/st_start.cpp )
|
||||
|
@ -525,7 +524,6 @@ set( PLAT_COCOA_SOURCES
|
|||
posix/cocoa/i_main.mm
|
||||
posix/cocoa/i_main_except.cpp
|
||||
posix/cocoa/i_system.mm
|
||||
posix/cocoa/i_timer.cpp
|
||||
posix/cocoa/i_video.mm
|
||||
posix/cocoa/st_console.mm
|
||||
posix/cocoa/st_start.mm )
|
||||
|
@ -653,6 +651,7 @@ file( GLOB HEADER_FILES
|
|||
posix/cocoa/*.h
|
||||
posix/sdl/*.h
|
||||
r_data/*.h
|
||||
r_data/models/*.h
|
||||
rapidjson/*.h
|
||||
resourcefiles/*.h
|
||||
sfmt/*.h
|
||||
|
@ -797,7 +796,6 @@ set( FASTMATH_SOURCES
|
|||
sound/oalsound.cpp
|
||||
sound/sndfile_decoder.cpp
|
||||
sound/mididevices/music_timiditypp_mididevice.cpp
|
||||
gl/data/gl_matrix.cpp
|
||||
gl/utility/gl_clock.cpp
|
||||
gl/renderer/gl_2ddrawer.cpp
|
||||
gl/hqnx/init.cpp
|
||||
|
@ -826,6 +824,8 @@ set( FASTMATH_SOURCES
|
|||
gl/dynlights/gl_dynlight1.cpp
|
||||
gl/system/gl_load.c
|
||||
gl/models/gl_models.cpp
|
||||
r_data/models/models.cpp
|
||||
r_data/matrix.cpp
|
||||
)
|
||||
|
||||
set (PCH_SOURCES
|
||||
|
@ -999,9 +999,6 @@ set (PCH_SOURCES
|
|||
gl/dynlights/gl_lightbuffer.cpp
|
||||
gl/dynlights/gl_aabbtree.cpp
|
||||
gl/dynlights/gl_shadowmap.cpp
|
||||
gl/models/gl_models_md3.cpp
|
||||
gl/models/gl_models_md2.cpp
|
||||
gl/models/gl_voxels.cpp
|
||||
gl/renderer/gl_quaddrawer.cpp
|
||||
gl/renderer/gl_renderer.cpp
|
||||
gl/renderer/gl_renderstate.cpp
|
||||
|
@ -1105,6 +1102,9 @@ set (PCH_SOURCES
|
|||
r_data/renderstyle.cpp
|
||||
r_data/r_interpolate.cpp
|
||||
r_data/r_vanillatrans.cpp
|
||||
r_data/models/models_md3.cpp
|
||||
r_data/models/models_md2.cpp
|
||||
r_data/models/models_voxel.cpp
|
||||
scripting/symbols.cpp
|
||||
scripting/types.cpp
|
||||
scripting/thingdef.cpp
|
||||
|
@ -1359,9 +1359,9 @@ source_group("Poly Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/po
|
|||
source_group("Poly Renderer\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/polyrenderer/math/.+")
|
||||
source_group("Poly Renderer\\Drawers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/polyrenderer/drawers/.+")
|
||||
source_group("Poly Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/polyrenderer/scene/.+")
|
||||
source_group("Render Data\\Resource Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.h$")
|
||||
source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.cpp$")
|
||||
source_group("Render Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+")
|
||||
source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+")
|
||||
source_group("Render Data\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/models/.+")
|
||||
source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
|
||||
source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+")
|
||||
source_group("Platforms\\POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
|
||||
|
|
|
@ -67,7 +67,7 @@ void ScanDirectory(TArray<FFileList> &list, const char *dirpath);
|
|||
|
||||
inline int Tics2Seconds(int tics)
|
||||
{
|
||||
return tics * TICRATE;
|
||||
return tics / TICRATE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "tarray.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "r_data/models/models.h"
|
||||
|
||||
struct vertex_t;
|
||||
struct secplane_t;
|
||||
|
@ -266,49 +267,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
#define VSO ((FSkyVertex*)NULL)
|
||||
|
||||
struct FModelVertex
|
||||
{
|
||||
float x, y, z; // world position
|
||||
float u, v; // texture coordinates
|
||||
unsigned packedNormal; // normal vector as GL_INT_2_10_10_10_REV.
|
||||
|
||||
void Set(float xx, float yy, float zz, float uu, float vv)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
z = zz;
|
||||
u = uu;
|
||||
v = vv;
|
||||
}
|
||||
|
||||
void SetNormal(float nx, float ny, float nz)
|
||||
{
|
||||
int inx = clamp(int(nx * 512), -512, 511);
|
||||
int iny = clamp(int(ny * 512), -512, 511);
|
||||
int inz = clamp(int(nz * 512), -512, 511);
|
||||
int inw = 0;
|
||||
packedNormal = (inw << 30) | ((inz & 1023) << 20) | ((iny & 1023) << 10) | (inx & 1023);
|
||||
}
|
||||
};
|
||||
|
||||
class FModelRenderer;
|
||||
|
||||
class IModelVertexBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~IModelVertexBuffer() { }
|
||||
|
||||
virtual FModelVertex *LockVertexBuffer(unsigned int size) = 0;
|
||||
virtual void UnlockVertexBuffer() = 0;
|
||||
|
||||
virtual unsigned int *LockIndexBuffer(unsigned int size) = 0;
|
||||
virtual void UnlockIndexBuffer() = 0;
|
||||
|
||||
virtual void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) = 0;
|
||||
};
|
||||
|
||||
class FModelVertexBuffer : public FVertexBuffer, public IModelVertexBuffer
|
||||
{
|
||||
int mIndexFrame[2];
|
||||
|
@ -330,7 +288,6 @@ public:
|
|||
void BindVBO() override;
|
||||
};
|
||||
|
||||
#define VMO ((FModelVertex*)NULL)
|
||||
|
||||
#define VSO ((FSkyVertex*)NULL)
|
||||
|
||||
#endif
|
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
** gl_models.cpp
|
||||
**
|
||||
** General model handling code
|
||||
** OpenGL renderer model handling code
|
||||
**
|
||||
**/
|
||||
|
||||
|
@ -48,238 +48,11 @@
|
|||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/utility/gl_geometric.h"
|
||||
#include "gl/utility/gl_convert.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
||||
CVAR(Bool, gl_interpolate_model_frames, true, CVAR_ARCHIVE)
|
||||
CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE)
|
||||
EXTERN_CVAR(Int, gl_fogmode)
|
||||
|
||||
extern TDeletingArray<FVoxel *> Voxels;
|
||||
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
||||
|
||||
DeletingModelArray Models;
|
||||
|
||||
void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
|
||||
{
|
||||
// Setup transformation.
|
||||
|
||||
int translation = 0;
|
||||
if (!(smf->flags & MDL_IGNORETRANSLATION))
|
||||
translation = actor->Translation;
|
||||
|
||||
// y scale for a sprite means height, i.e. z in the world!
|
||||
float scaleFactorX = actor->Scale.X * smf->xscale;
|
||||
float scaleFactorY = actor->Scale.X * smf->yscale;
|
||||
float scaleFactorZ = actor->Scale.Y * smf->zscale;
|
||||
float pitch = 0;
|
||||
float roll = 0;
|
||||
double rotateOffset = 0;
|
||||
float angle = actor->Angles.Yaw.Degrees;
|
||||
|
||||
// [BB] Workaround for the missing pitch information.
|
||||
if ((smf->flags & MDL_PITCHFROMMOMENTUM))
|
||||
{
|
||||
const double x = actor->Vel.X;
|
||||
const double y = actor->Vel.Y;
|
||||
const double z = actor->Vel.Z;
|
||||
|
||||
if (actor->Vel.LengthSquared() > EQUAL_EPSILON)
|
||||
{
|
||||
// [BB] Calculate the pitch using spherical coordinates.
|
||||
if (z || x || y) pitch = float(atan(z / sqrt(x*x + y*y)) / M_PI * 180);
|
||||
|
||||
// Correcting pitch if model is moving backwards
|
||||
if (fabs(x) > EQUAL_EPSILON || fabs(y) > EQUAL_EPSILON)
|
||||
{
|
||||
if ((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1;
|
||||
}
|
||||
else pitch = fabs(pitch);
|
||||
}
|
||||
}
|
||||
|
||||
if (smf->flags & MDL_ROTATING)
|
||||
{
|
||||
const double time = smf->rotationSpeed*GetTimeFloat() / 200.;
|
||||
rotateOffset = double((time - xs_FloorToInt(time)) *360.);
|
||||
}
|
||||
|
||||
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
|
||||
// If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch.
|
||||
if (smf->flags & MDL_USEACTORPITCH)
|
||||
{
|
||||
double d = actor->Angles.Pitch.Degrees;
|
||||
if (smf->flags & MDL_BADROTATION) pitch += d;
|
||||
else pitch -= d;
|
||||
}
|
||||
if (smf->flags & MDL_USEACTORROLL) roll += actor->Angles.Roll.Degrees;
|
||||
|
||||
VSMatrix objectToWorldMatrix;
|
||||
objectToWorldMatrix.loadIdentity();
|
||||
|
||||
// Model space => World space
|
||||
objectToWorldMatrix.translate(x, z, y);
|
||||
|
||||
// [Nash] take SpriteRotation into account
|
||||
angle += actor->SpriteRotation.Degrees;
|
||||
|
||||
if (actor->renderflags & RF_INTERPOLATEANGLES)
|
||||
{
|
||||
// [Nash] use interpolated angles
|
||||
DRotator Angles = actor->InterpolatedAngles(r_viewpoint.TicFrac);
|
||||
angle = Angles.Yaw.Degrees;
|
||||
}
|
||||
|
||||
// Applying model transformations:
|
||||
// 1) Applying actor angle, pitch and roll to the model
|
||||
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
|
||||
|
||||
// 2) Applying Doomsday like rotation of the weapon pickup models
|
||||
// The rotation angle is based on the elapsed time.
|
||||
|
||||
if (smf->flags & MDL_ROTATING)
|
||||
{
|
||||
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY, smf->rotationCenterZ);
|
||||
objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
|
||||
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY, -smf->rotationCenterZ);
|
||||
}
|
||||
|
||||
// 3) Scaling model.
|
||||
objectToWorldMatrix.scale(scaleFactorX, scaleFactorZ, scaleFactorY);
|
||||
|
||||
// 4) Aplying model offsets (model offsets do not depend on model scalings).
|
||||
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale);
|
||||
|
||||
// 5) Applying model rotations.
|
||||
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
|
||||
|
||||
// consider the pixel stretching. For non-voxels this must be factored out here
|
||||
float stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor() : 1.f) / level.info->pixelstretch;
|
||||
objectToWorldMatrix.scale(1, stretch, 1);
|
||||
|
||||
BeginDrawModel(actor, smf, objectToWorldMatrix);
|
||||
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), nullptr, translation);
|
||||
EndDrawModel(actor, smf);
|
||||
}
|
||||
|
||||
void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
|
||||
{
|
||||
AActor * playermo = players[consoleplayer].camera;
|
||||
FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false);
|
||||
|
||||
// [BB] No model found for this sprite, so we can't render anything.
|
||||
if (smf == nullptr)
|
||||
return;
|
||||
|
||||
// The model position and orientation has to be drawn independently from the position of the player,
|
||||
// but we need to position it correctly in the world for light to work properly.
|
||||
VSMatrix objectToWorldMatrix = GetViewToWorldMatrix();
|
||||
|
||||
// Scaling model (y scale for a sprite means height, i.e. z in the world!).
|
||||
objectToWorldMatrix.scale(smf->xscale, smf->zscale, smf->yscale);
|
||||
|
||||
// Aplying model offsets (model offsets do not depend on model scalings).
|
||||
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale);
|
||||
|
||||
// [BB] Weapon bob, very similar to the normal Doom weapon bob.
|
||||
objectToWorldMatrix.rotate(ofsX / 4, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate((ofsY - WEAPONTOP) / -4., 1, 0, 0);
|
||||
|
||||
// [BB] For some reason the jDoom models need to be rotated.
|
||||
objectToWorldMatrix.rotate(90.f, 0, 1, 0);
|
||||
|
||||
// Applying angleoffset, pitchoffset, rolloffset.
|
||||
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
|
||||
|
||||
BeginDrawHUDModel(playermo, objectToWorldMatrix);
|
||||
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0);
|
||||
EndDrawHUDModel(playermo);
|
||||
}
|
||||
|
||||
void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
|
||||
const FState *curState,
|
||||
const int curTics,
|
||||
const PClass *ti,
|
||||
Matrix3x4 *normaltransform,
|
||||
int translation)
|
||||
{
|
||||
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
||||
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
||||
FSpriteModelFrame * smfNext = nullptr;
|
||||
double inter = 0.;
|
||||
if (gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION))
|
||||
{
|
||||
FState *nextState = curState->GetNextState();
|
||||
if (curState != nextState && nextState)
|
||||
{
|
||||
// [BB] To interpolate at more than 35 fps we take tic fractions into account.
|
||||
float ticFraction = 0.;
|
||||
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
|
||||
if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN))
|
||||
{
|
||||
double time = GetTimeFloat();
|
||||
ticFraction = (time - static_cast<int>(time));
|
||||
}
|
||||
inter = static_cast<double>(curState->Tics - curTics - ticFraction) / static_cast<double>(curState->Tics);
|
||||
|
||||
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
|
||||
// In this case inter is negative and we need to set it to zero.
|
||||
if (inter < 0.)
|
||||
inter = 0.;
|
||||
else
|
||||
{
|
||||
// [BB] Workaround for actors that use the same frame twice in a row.
|
||||
// Most of the standard Doom monsters do this in their see state.
|
||||
if ((smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES))
|
||||
{
|
||||
const FState *prevState = curState - 1;
|
||||
if ((curState->sprite == prevState->sprite) && (curState->Frame == prevState->Frame))
|
||||
{
|
||||
inter /= 2.;
|
||||
inter += 0.5;
|
||||
}
|
||||
if ((curState->sprite == nextState->sprite) && (curState->Frame == nextState->Frame))
|
||||
{
|
||||
inter /= 2.;
|
||||
nextState = nextState->GetNextState();
|
||||
}
|
||||
}
|
||||
if (inter != 0.0)
|
||||
smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<MAX_MODELS_PER_FRAME; i++)
|
||||
{
|
||||
if (smf->modelIDs[i] != -1)
|
||||
{
|
||||
FModel * mdl = Models[smf->modelIDs[i]];
|
||||
FTexture *tex = smf->skinIDs[i].isValid() ? TexMan(smf->skinIDs[i]) : nullptr;
|
||||
mdl->BuildVertexBuffer(this);
|
||||
SetVertexBuffer(mdl->mVBuf);
|
||||
|
||||
mdl->PushSpriteMDLFrame(smf, i);
|
||||
|
||||
if (smfNext && smf->modelframes[i] != smfNext->modelframes[i])
|
||||
mdl->RenderFrame(this, tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation);
|
||||
else
|
||||
mdl->RenderFrame(this, tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation);
|
||||
|
||||
ResetVertexBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern int modellightindex;
|
||||
|
||||
|
@ -363,23 +136,23 @@ void FGLModelRenderer::SetInterpolation(double inter)
|
|||
gl_RenderState.SetInterpolationFactor((float)inter);
|
||||
}
|
||||
|
||||
void FGLModelRenderer::SetMaterial(FTexture *skin, int clampmode, int translation)
|
||||
void FGLModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int translation)
|
||||
{
|
||||
FMaterial * tex = FMaterial::ValidateTexture(skin, false);
|
||||
gl_RenderState.SetMaterial(tex, clampmode, translation, -1, false);
|
||||
gl_RenderState.SetMaterial(tex, clampNoFilter ? CLAMP_NOFILTER : CLAMP_NONE, translation, -1, false);
|
||||
|
||||
gl_RenderState.Apply();
|
||||
if (modellightindex != -1) gl_RenderState.ApplyLightIndex(modellightindex);
|
||||
}
|
||||
|
||||
void FGLModelRenderer::DrawArrays(int primitiveType, int start, int count)
|
||||
void FGLModelRenderer::DrawArrays(int start, int count)
|
||||
{
|
||||
glDrawArrays(primitiveType, start, count);
|
||||
glDrawArrays(GL_TRIANGLES, start, count);
|
||||
}
|
||||
|
||||
void FGLModelRenderer::DrawElements(int primitiveType, int numIndices, int elementType, size_t offset)
|
||||
void FGLModelRenderer::DrawElements(int numIndices, size_t offset)
|
||||
{
|
||||
glDrawElements(primitiveType, numIndices, elementType, (void*)(intptr_t)offset);
|
||||
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, (void*)(intptr_t)offset);
|
||||
}
|
||||
|
||||
double FGLModelRenderer::GetTimeFloat()
|
||||
|
@ -387,26 +160,6 @@ double FGLModelRenderer::GetTimeFloat()
|
|||
return (float)I_msTime() * (float)TICRATE / 1000.0f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void gl_LoadModels()
|
||||
{
|
||||
/*
|
||||
for (int i = Models.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
Models[i]->BuildVertexBuffer();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void gl_FlushModels()
|
||||
{
|
||||
for (int i = Models.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
Models[i]->DestroyVertexBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Uses a hardware buffer if either single frame (i.e. no interpolation needed)
|
||||
|
@ -600,583 +353,6 @@ void FModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FModel::~FModel
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FModel::~FModel()
|
||||
{
|
||||
if (mVBuf != nullptr) delete mVBuf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static TArray<FSpriteModelFrame> SpriteModelFrames;
|
||||
static int * SpriteModelHash;
|
||||
//TArray<FStateModelFrame> StateModelFrames;
|
||||
|
||||
static void DeleteModelHash()
|
||||
{
|
||||
if (SpriteModelHash != nullptr) delete [] SpriteModelHash;
|
||||
SpriteModelHash = nullptr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FindGFXFile
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static int FindGFXFile(FString & fn)
|
||||
{
|
||||
int lump = Wads.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below.
|
||||
if (lump != -1) return lump;
|
||||
|
||||
int best = -1;
|
||||
int dot = fn.LastIndexOf('.');
|
||||
int slash = fn.LastIndexOf('/');
|
||||
if (dot > slash) fn.Truncate(dot);
|
||||
|
||||
static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", nullptr };
|
||||
|
||||
for (const char ** extp=extensions; *extp; extp++)
|
||||
{
|
||||
int lump = Wads.CheckNumForFullName(fn + *extp);
|
||||
if (lump >= best) best = lump;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// LoadSkin
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FTextureID LoadSkin(const char * path, const char * fn)
|
||||
{
|
||||
FString buffer;
|
||||
|
||||
buffer.Format("%s%s", path, fn);
|
||||
|
||||
int texlump = FindGFXFile(buffer);
|
||||
const char * const texname = texlump < 0 ? fn : Wads.GetLumpFullName(texlump);
|
||||
return TexMan.CheckForTexture(texname, FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ModelFrameHash
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static int ModelFrameHash(FSpriteModelFrame * smf)
|
||||
{
|
||||
const uint32_t *table = GetCRCTable ();
|
||||
uint32_t hash = 0xffffffff;
|
||||
|
||||
const char * s = (const char *)(&smf->type); // this uses type, sprite and frame for hashing
|
||||
const char * se= (const char *)(&smf->hashnext);
|
||||
|
||||
for (; s<se; s++)
|
||||
{
|
||||
hash = CRC1 (hash, *s, table);
|
||||
}
|
||||
return hash ^ 0xffffffff;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FindModel
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static unsigned FindModel(const char * path, const char * modelfile)
|
||||
{
|
||||
FModel * model = nullptr;
|
||||
FString fullname;
|
||||
|
||||
fullname.Format("%s%s", path, modelfile);
|
||||
int lump = Wads.CheckNumForFullName(fullname);
|
||||
|
||||
if (lump<0)
|
||||
{
|
||||
Printf("FindModel: '%s' not found\n", fullname.GetChars());
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i< Models.Size(); i++)
|
||||
{
|
||||
if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
|
||||
}
|
||||
|
||||
int len = Wads.LumpLength(lump);
|
||||
FMemLump lumpd = Wads.ReadLump(lump);
|
||||
char * buffer = (char*)lumpd.GetMem();
|
||||
|
||||
if (!memcmp(buffer, "DMDM", 4))
|
||||
{
|
||||
model = new FDMDModel;
|
||||
}
|
||||
else if (!memcmp(buffer, "IDP2", 4))
|
||||
{
|
||||
model = new FMD2Model;
|
||||
}
|
||||
else if (!memcmp(buffer, "IDP3", 4))
|
||||
{
|
||||
model = new FMD3Model;
|
||||
}
|
||||
|
||||
if (model != nullptr)
|
||||
{
|
||||
if (!model->Load(path, lump, buffer, len))
|
||||
{
|
||||
delete model;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// try loading as a voxel
|
||||
FVoxel *voxel = R_LoadKVX(lump);
|
||||
if (voxel != nullptr)
|
||||
{
|
||||
model = new FVoxelModel(voxel, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
|
||||
model->mFileName = fullname;
|
||||
return Models.Push(model);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_InitModels
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void gl_InitModels()
|
||||
{
|
||||
int Lump, lastLump;
|
||||
FString path;
|
||||
int index, surface;
|
||||
int i;
|
||||
|
||||
FSpriteModelFrame smf;
|
||||
|
||||
lastLump = 0;
|
||||
|
||||
for(unsigned i=0;i<Models.Size();i++)
|
||||
{
|
||||
delete Models[i];
|
||||
}
|
||||
Models.Clear();
|
||||
SpriteModelFrames.Clear();
|
||||
DeleteModelHash();
|
||||
|
||||
// First, create models for each voxel
|
||||
for (unsigned i = 0; i < Voxels.Size(); i++)
|
||||
{
|
||||
FVoxelModel *md = new FVoxelModel(Voxels[i], false);
|
||||
Voxels[i]->VoxelIndex = Models.Push(md);
|
||||
}
|
||||
// now create GL model frames for the voxeldefs
|
||||
for (unsigned i = 0; i < VoxelDefs.Size(); i++)
|
||||
{
|
||||
FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex];
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
|
||||
smf.skinIDs[0] = md->GetPaletteTexture();
|
||||
smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale;
|
||||
smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees;
|
||||
if (VoxelDefs[i]->PlacedSpin != 0)
|
||||
{
|
||||
smf.yrotate = 1.f;
|
||||
smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f;
|
||||
smf.flags |= MDL_ROTATING;
|
||||
}
|
||||
VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf);
|
||||
if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin)
|
||||
{
|
||||
if (VoxelDefs[i]->DroppedSpin != 0)
|
||||
{
|
||||
smf.yrotate = 1.f;
|
||||
smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f;
|
||||
smf.flags |= MDL_ROTATING;
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.yrotate = 0;
|
||||
smf.rotationSpeed = 0;
|
||||
smf.flags &= ~MDL_ROTATING;
|
||||
}
|
||||
SpriteModelFrames.Push(smf);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
|
||||
{
|
||||
FScanner sc(Lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("model"))
|
||||
{
|
||||
path = "";
|
||||
sc.MustGetString();
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
smf.xscale=smf.yscale=smf.zscale=1.f;
|
||||
|
||||
smf.type = PClass::FindClass(sc.String);
|
||||
if (!smf.type || smf.type->Defaults == nullptr)
|
||||
{
|
||||
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
|
||||
}
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("path"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
path = sc.String;
|
||||
if (path[(int)path.Len()-1]!='/') path+='/';
|
||||
}
|
||||
else if (sc.Compare("model"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index = sc.Number;
|
||||
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
|
||||
if (smf.modelIDs[index] == -1)
|
||||
{
|
||||
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("scale"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xscale = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yscale = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zscale = sc.Float;
|
||||
}
|
||||
// [BB] Added zoffset reading.
|
||||
// Now it must be considered deprecated.
|
||||
else if (sc.Compare("zoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.zoffset=sc.Float;
|
||||
}
|
||||
// Offset reading.
|
||||
else if (sc.Compare("offset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xoffset = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yoffset = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zoffset = sc.Float;
|
||||
}
|
||||
// angleoffset, pitchoffset and rolloffset reading.
|
||||
else if (sc.Compare("angleoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.angleoffset = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("pitchoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.pitchoffset = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rolloffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rolloffset = sc.Float;
|
||||
}
|
||||
// [BB] Added model flags reading.
|
||||
else if (sc.Compare("ignoretranslation"))
|
||||
{
|
||||
smf.flags |= MDL_IGNORETRANSLATION;
|
||||
}
|
||||
else if (sc.Compare("pitchfrommomentum"))
|
||||
{
|
||||
smf.flags |= MDL_PITCHFROMMOMENTUM;
|
||||
}
|
||||
else if (sc.Compare("inheritactorpitch"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
|
||||
}
|
||||
else if (sc.Compare("inheritactorroll"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORROLL;
|
||||
}
|
||||
else if (sc.Compare("useactorpitch"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORPITCH;
|
||||
}
|
||||
else if (sc.Compare("useactorroll"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORROLL;
|
||||
}
|
||||
else if (sc.Compare("rotating"))
|
||||
{
|
||||
smf.flags |= MDL_ROTATING;
|
||||
smf.xrotate = 0.;
|
||||
smf.yrotate = 1.;
|
||||
smf.zrotate = 0.;
|
||||
smf.rotationCenterX = 0.;
|
||||
smf.rotationCenterY = 0.;
|
||||
smf.rotationCenterZ = 0.;
|
||||
smf.rotationSpeed = 1.;
|
||||
}
|
||||
else if (sc.Compare("rotation-speed"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rotationSpeed = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rotation-vector"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xrotate = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yrotate = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zrotate = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rotation-center"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterX = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterY = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterZ = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("interpolatedoubledframes"))
|
||||
{
|
||||
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
|
||||
}
|
||||
else if (sc.Compare("nointerpolation"))
|
||||
{
|
||||
smf.flags |= MDL_NOINTERPOLATION;
|
||||
}
|
||||
else if (sc.Compare("skin"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index=sc.Number;
|
||||
if (index<0 || index>=MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
if (sc.Compare(""))
|
||||
{
|
||||
smf.skinIDs[index]=FNullTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
|
||||
if (!smf.skinIDs[index].isValid())
|
||||
{
|
||||
Printf("Skin '%s' not found in '%s'\n",
|
||||
sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("surfaceskin"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index = sc.Number;
|
||||
sc.MustGetNumber();
|
||||
surface = sc.Number;
|
||||
|
||||
if (index<0 || index >= MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
if (surface<0 || surface >= MD3_MAX_SURFACES)
|
||||
{
|
||||
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
if (sc.Compare(""))
|
||||
{
|
||||
smf.surfaceskinIDs[index][surface] = FNullTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
|
||||
if (!smf.surfaceskinIDs[index][surface].isValid())
|
||||
{
|
||||
Printf("Surface Skin '%s' not found in '%s'\n",
|
||||
sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("frameindex") || sc.Compare("frame"))
|
||||
{
|
||||
bool isframe=!!sc.Compare("frame");
|
||||
|
||||
sc.MustGetString();
|
||||
smf.sprite = -1;
|
||||
for (i = 0; i < (int)sprites.Size (); ++i)
|
||||
{
|
||||
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
|
||||
{
|
||||
if (sprites[i].numframes==0)
|
||||
{
|
||||
//sc.ScriptError("Sprite %s has no frames", sc.String);
|
||||
}
|
||||
smf.sprite = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (smf.sprite==-1)
|
||||
{
|
||||
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
sc.MustGetString();
|
||||
FString framechars = sc.String;
|
||||
|
||||
sc.MustGetNumber();
|
||||
index=sc.Number;
|
||||
if (index<0 || index>=MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
if (isframe)
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (smf.modelIDs[index] != -1)
|
||||
{
|
||||
FModel *model = Models[smf.modelIDs[index]];
|
||||
smf.modelframes[index] = model->FindFrame(sc.String);
|
||||
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
else smf.modelframes[index] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
smf.modelframes[index] = sc.Number;
|
||||
}
|
||||
|
||||
for(i=0; framechars[i]>0; i++)
|
||||
{
|
||||
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int c = toupper(framechars[i])-'A';
|
||||
|
||||
if (c<0 || c>=29)
|
||||
{
|
||||
sc.ScriptError("Invalid frame character %c found", c+'A');
|
||||
}
|
||||
if (map[c]) continue;
|
||||
smf.frame=c;
|
||||
SpriteModelFrames.Push(smf);
|
||||
GetDefaultByType(smf.type)->hasmodel = true;
|
||||
map[c]=1;
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("dontcullbackfaces"))
|
||||
{
|
||||
smf.flags |= MDL_DONTCULLBACKFACES;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a hash table for quick access
|
||||
SpriteModelHash = new int[SpriteModelFrames.Size ()];
|
||||
atterm(DeleteModelHash);
|
||||
memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int));
|
||||
|
||||
for (i = 0; i < (int)SpriteModelFrames.Size (); i++)
|
||||
{
|
||||
int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size ();
|
||||
|
||||
SpriteModelFrames[i].hashnext = SpriteModelHash[j];
|
||||
SpriteModelHash[j]=i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_FindModelFrame
|
||||
//
|
||||
//===========================================================================
|
||||
EXTERN_CVAR (Bool, r_drawvoxels)
|
||||
|
||||
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
|
||||
{
|
||||
if (GetDefaultByType(ti)->hasmodel)
|
||||
{
|
||||
FSpriteModelFrame smf;
|
||||
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.type=ti;
|
||||
smf.sprite=sprite;
|
||||
smf.frame=frame;
|
||||
|
||||
int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()];
|
||||
|
||||
while (hash>=0)
|
||||
{
|
||||
FSpriteModelFrame * smff = &SpriteModelFrames[hash];
|
||||
if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff;
|
||||
hash=smff->hashnext;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for voxel replacements
|
||||
if (r_drawvoxels)
|
||||
{
|
||||
spritedef_t *sprdef = &sprites[sprite];
|
||||
if (frame < sprdef->numframes)
|
||||
{
|
||||
spriteframe_t *sprframe = &SpriteFrames[sprdef->spriteframes + frame];
|
||||
if (sprframe->Voxel != nullptr)
|
||||
{
|
||||
int index = sprframe->Voxel->VoxeldefIndex;
|
||||
if (dropped && sprframe->Voxel->DroppedSpin !=sprframe->Voxel->PlacedSpin) index++;
|
||||
return &SpriteModelFrames[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_RenderModel
|
||||
|
@ -1200,25 +376,3 @@ void gl_RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
|
|||
FGLModelRenderer renderer;
|
||||
renderer.RenderHUDModel(psp, ofsX, ofsY);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_IsHUDModelForPlayerAvailable
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool gl_IsHUDModelForPlayerAvailable (player_t * player)
|
||||
{
|
||||
if (player == nullptr || player->ReadyWeapon == nullptr)
|
||||
return false;
|
||||
|
||||
DPSprite *psp = player->FindPSprite(PSP_WEAPON);
|
||||
|
||||
if (psp == nullptr || psp->GetState() == nullptr)
|
||||
return false;
|
||||
|
||||
FState* state = psp->GetState();
|
||||
FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false);
|
||||
return ( smf != nullptr );
|
||||
}
|
||||
|
||||
|
|
|
@ -20,62 +20,15 @@
|
|||
//--------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#ifndef __GL_MODELS_H_
|
||||
#define __GL_MODELS_H_
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "gl/utility/gl_geometric.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "p_pspr.h"
|
||||
#include "r_data/voxels.h"
|
||||
#include "r_data/models/models.h"
|
||||
|
||||
|
||||
#define MAX_LODS 4
|
||||
|
||||
enum { VX, VZ, VY };
|
||||
|
||||
#define MD2_MAGIC 0x32504449
|
||||
#define DMD_MAGIC 0x4D444D44
|
||||
#define MD3_MAGIC 0x33504449
|
||||
#define NUMVERTEXNORMALS 162
|
||||
#define MD3_MAX_SURFACES 32
|
||||
|
||||
FTextureID LoadSkin(const char * path, const char * fn);
|
||||
|
||||
// [JM] Necessary forward declaration
|
||||
typedef struct FSpriteModelFrame FSpriteModelFrame;
|
||||
|
||||
class FModelRenderer
|
||||
{
|
||||
public:
|
||||
virtual ~FModelRenderer() { }
|
||||
|
||||
void RenderModel(float x, float y, float z, FSpriteModelFrame *modelframe, AActor *actor);
|
||||
void RenderHUDModel(DPSprite *psp, float ofsx, float ofsy);
|
||||
|
||||
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0;
|
||||
virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0;
|
||||
|
||||
virtual IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) = 0;
|
||||
|
||||
virtual void SetVertexBuffer(IModelVertexBuffer *buffer) = 0;
|
||||
virtual void ResetVertexBuffer() = 0;
|
||||
|
||||
virtual VSMatrix GetViewToWorldMatrix() = 0;
|
||||
|
||||
virtual void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) = 0;
|
||||
virtual void EndDrawHUDModel(AActor *actor) = 0;
|
||||
|
||||
virtual void SetInterpolation(double interpolation) = 0;
|
||||
virtual void SetMaterial(FTexture *skin, int clampmode, int translation) = 0;
|
||||
virtual void DrawArrays(int primitiveType, int start, int count) = 0;
|
||||
virtual void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) = 0;
|
||||
|
||||
virtual double GetTimeFloat() = 0;
|
||||
|
||||
private:
|
||||
void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation);
|
||||
};
|
||||
class GLSprite;
|
||||
|
||||
class FGLModelRenderer : public FModelRenderer
|
||||
{
|
||||
|
@ -89,388 +42,11 @@ public:
|
|||
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
|
||||
void EndDrawHUDModel(AActor *actor) override;
|
||||
void SetInterpolation(double interpolation) override;
|
||||
void SetMaterial(FTexture *skin, int clampmode, int translation) override;
|
||||
void DrawArrays(int primitiveType, int start, int count) override;
|
||||
void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override;
|
||||
void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override;
|
||||
void DrawArrays(int start, int count) override;
|
||||
void DrawElements(int numIndices, size_t offset) override;
|
||||
double GetTimeFloat() override;
|
||||
};
|
||||
|
||||
class FModel
|
||||
{
|
||||
public:
|
||||
|
||||
FModel()
|
||||
{
|
||||
mVBuf = NULL;
|
||||
}
|
||||
virtual ~FModel();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
|
||||
virtual int FindFrame(const char * name) = 0;
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0;
|
||||
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
|
||||
virtual void AddSkins(uint8_t *hitlist) = 0;
|
||||
void DestroyVertexBuffer()
|
||||
{
|
||||
delete mVBuf;
|
||||
mVBuf = NULL;
|
||||
}
|
||||
virtual float getAspectFactor() { return 1.f; }
|
||||
|
||||
const FSpriteModelFrame *curSpriteMDLFrame;
|
||||
int curMDLIndex;
|
||||
void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; };
|
||||
|
||||
IModelVertexBuffer *mVBuf;
|
||||
FString mFileName;
|
||||
};
|
||||
|
||||
class FDMDModel : public FModel
|
||||
{
|
||||
protected:
|
||||
|
||||
struct FTriangle
|
||||
{
|
||||
unsigned short vertexIndices[3];
|
||||
unsigned short textureIndices[3];
|
||||
};
|
||||
|
||||
|
||||
struct DMDHeader
|
||||
{
|
||||
int magic;
|
||||
int version;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct DMDModelVertex
|
||||
{
|
||||
float xyz[3];
|
||||
};
|
||||
|
||||
struct FTexCoord
|
||||
{
|
||||
short s, t;
|
||||
};
|
||||
|
||||
struct FGLCommandVertex
|
||||
{
|
||||
float s, t;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct DMDInfo
|
||||
{
|
||||
int skinWidth;
|
||||
int skinHeight;
|
||||
int frameSize;
|
||||
int numSkins;
|
||||
int numVertices;
|
||||
int numTexCoords;
|
||||
int numFrames;
|
||||
int numLODs;
|
||||
int offsetSkins;
|
||||
int offsetTexCoords;
|
||||
int offsetFrames;
|
||||
int offsetLODs;
|
||||
int offsetEnd;
|
||||
};
|
||||
|
||||
struct ModelFrame
|
||||
{
|
||||
char name[16];
|
||||
unsigned int vindex;
|
||||
};
|
||||
|
||||
struct ModelFrameVertexData
|
||||
{
|
||||
DMDModelVertex *vertices;
|
||||
DMDModelVertex *normals;
|
||||
};
|
||||
|
||||
struct DMDLoDInfo
|
||||
{
|
||||
int numTriangles;
|
||||
int numGlCommands;
|
||||
int offsetTriangles;
|
||||
int offsetGlCommands;
|
||||
};
|
||||
|
||||
struct DMDLoD
|
||||
{
|
||||
FTriangle * triangles;
|
||||
};
|
||||
|
||||
|
||||
int mLumpNum;
|
||||
DMDHeader header;
|
||||
DMDInfo info;
|
||||
FTextureID * skins;
|
||||
ModelFrame * frames;
|
||||
bool allowTexComp; // Allow texture compression with this.
|
||||
|
||||
// Temp data only needed for buffer construction
|
||||
FTexCoord * texCoords;
|
||||
ModelFrameVertexData *framevtx;
|
||||
DMDLoDInfo lodInfo[MAX_LODS];
|
||||
DMDLoD lods[MAX_LODS];
|
||||
|
||||
public:
|
||||
FDMDModel()
|
||||
{
|
||||
mLumpNum = -1;
|
||||
frames = NULL;
|
||||
skins = NULL;
|
||||
for (int i = 0; i < MAX_LODS; i++)
|
||||
{
|
||||
lods[i].triangles = NULL;
|
||||
}
|
||||
info.numLODs = 0;
|
||||
texCoords = NULL;
|
||||
framevtx = NULL;
|
||||
}
|
||||
virtual ~FDMDModel();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
virtual void LoadGeometry();
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
|
||||
void UnloadGeometry();
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
|
||||
};
|
||||
|
||||
// This uses the same internal representation as DMD
|
||||
class FMD2Model : public FDMDModel
|
||||
{
|
||||
public:
|
||||
FMD2Model() {}
|
||||
virtual ~FMD2Model();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual void LoadGeometry();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FMD3Model : public FModel
|
||||
{
|
||||
struct MD3Tag
|
||||
{
|
||||
// Currently I have no use for this
|
||||
};
|
||||
|
||||
struct MD3TexCoord
|
||||
{
|
||||
float s,t;
|
||||
};
|
||||
|
||||
struct MD3Vertex
|
||||
{
|
||||
float x,y,z;
|
||||
float nx,ny,nz;
|
||||
};
|
||||
|
||||
struct MD3Triangle
|
||||
{
|
||||
int VertIndex[3];
|
||||
};
|
||||
|
||||
struct MD3Surface
|
||||
{
|
||||
int numVertices;
|
||||
int numTriangles;
|
||||
int numSkins;
|
||||
|
||||
FTextureID * skins;
|
||||
MD3Triangle * tris;
|
||||
MD3TexCoord * texcoords;
|
||||
MD3Vertex * vertices;
|
||||
|
||||
unsigned int vindex; // contains numframes arrays of vertices
|
||||
unsigned int iindex;
|
||||
|
||||
MD3Surface()
|
||||
{
|
||||
tris=NULL;
|
||||
vertices=NULL;
|
||||
texcoords=NULL;
|
||||
vindex = iindex = UINT_MAX;
|
||||
}
|
||||
|
||||
~MD3Surface()
|
||||
{
|
||||
if (skins) delete [] skins;
|
||||
UnloadGeometry();
|
||||
}
|
||||
|
||||
void UnloadGeometry()
|
||||
{
|
||||
if (tris) delete [] tris;
|
||||
if (vertices) delete [] vertices;
|
||||
if (texcoords) delete [] texcoords;
|
||||
tris = NULL;
|
||||
vertices = NULL;
|
||||
texcoords = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
struct MD3Frame
|
||||
{
|
||||
// The bounding box information is of no use in the Doom engine
|
||||
// That will still be done with the actor's size information.
|
||||
char Name[16];
|
||||
float origin[3];
|
||||
};
|
||||
|
||||
int numFrames;
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
int mLumpNum;
|
||||
|
||||
MD3Frame * frames;
|
||||
MD3Surface * surfaces;
|
||||
|
||||
public:
|
||||
FMD3Model() { }
|
||||
virtual ~FMD3Model();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
void LoadGeometry();
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
};
|
||||
|
||||
struct FVoxelVertexHash
|
||||
{
|
||||
// Returns the hash value for a key.
|
||||
hash_t Hash(const FModelVertex &key)
|
||||
{
|
||||
int ix = xs_RoundToInt(key.x);
|
||||
int iy = xs_RoundToInt(key.y);
|
||||
int iz = xs_RoundToInt(key.z);
|
||||
return (hash_t)(ix + (iy<<9) + (iz<<18));
|
||||
}
|
||||
|
||||
// Compares two keys, returning zero if they are the same.
|
||||
int Compare(const FModelVertex &left, const FModelVertex &right)
|
||||
{
|
||||
return left.x != right.x || left.y != right.y || left.z != right.z || left.u != right.u || left.v != right.v;
|
||||
}
|
||||
};
|
||||
|
||||
struct FIndexInit
|
||||
{
|
||||
void Init(unsigned int &value)
|
||||
{
|
||||
value = 0xffffffff;
|
||||
}
|
||||
};
|
||||
|
||||
typedef TMap<FModelVertex, unsigned int, FVoxelVertexHash, FIndexInit> FVoxelMap;
|
||||
|
||||
|
||||
class FVoxelModel : public FModel
|
||||
{
|
||||
protected:
|
||||
FVoxel *mVoxel;
|
||||
bool mOwningVoxel; // if created through MODELDEF deleting this object must also delete the voxel object
|
||||
FTextureID mPalette;
|
||||
unsigned int mNumIndices;
|
||||
TArray<FModelVertex> mVertices;
|
||||
TArray<unsigned int> mIndices;
|
||||
|
||||
void MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &check);
|
||||
void AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, uint8_t color, FVoxelMap &check);
|
||||
unsigned int AddVertex(FModelVertex &vert, FVoxelMap &check);
|
||||
|
||||
public:
|
||||
FVoxelModel(FVoxel *voxel, bool owned);
|
||||
~FVoxelModel();
|
||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
void Initialize();
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
FTextureID GetPaletteTexture() const { return mPalette; }
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
float getAspectFactor();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_MODELS_PER_FRAME 4
|
||||
|
||||
//
|
||||
// [BB] Model rendering flags.
|
||||
//
|
||||
enum
|
||||
{
|
||||
// [BB] Color translations for the model skin are ignored. This is
|
||||
// useful if the skin texture is not using the game palette.
|
||||
MDL_IGNORETRANSLATION = 1,
|
||||
MDL_PITCHFROMMOMENTUM = 2,
|
||||
MDL_ROTATING = 4,
|
||||
MDL_INTERPOLATEDOUBLEDFRAMES = 8,
|
||||
MDL_NOINTERPOLATION = 16,
|
||||
MDL_USEACTORPITCH = 32,
|
||||
MDL_USEACTORROLL = 64,
|
||||
MDL_BADROTATION = 128,
|
||||
MDL_DONTCULLBACKFACES = 256,
|
||||
};
|
||||
|
||||
struct FSpriteModelFrame
|
||||
{
|
||||
int modelIDs[MAX_MODELS_PER_FRAME];
|
||||
FTextureID skinIDs[MAX_MODELS_PER_FRAME];
|
||||
FTextureID surfaceskinIDs[MAX_MODELS_PER_FRAME][MD3_MAX_SURFACES];
|
||||
int modelframes[MAX_MODELS_PER_FRAME];
|
||||
float xscale, yscale, zscale;
|
||||
// [BB] Added zoffset, rotation parameters and flags.
|
||||
// Added xoffset, yoffset
|
||||
float xoffset, yoffset, zoffset;
|
||||
float xrotate, yrotate, zrotate;
|
||||
float rotationCenterX, rotationCenterY, rotationCenterZ;
|
||||
float rotationSpeed;
|
||||
unsigned int flags;
|
||||
const PClass * type;
|
||||
short sprite;
|
||||
short frame;
|
||||
FState * state; // for later!
|
||||
int hashnext;
|
||||
float angleoffset;
|
||||
// added pithoffset, rolloffset.
|
||||
float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float.
|
||||
};
|
||||
|
||||
class GLSprite;
|
||||
|
||||
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
|
||||
|
||||
void gl_RenderModel(GLSprite * spr);
|
||||
// [BB] HUD weapon model rendering functions.
|
||||
void gl_RenderHUDModel(DPSprite *psp, float ofsx, float ofsy);
|
||||
bool gl_IsHUDModelForPlayerAvailable (player_t * player);
|
||||
|
||||
|
||||
class DeletingModelArray : public TArray<FModel *>
|
||||
{
|
||||
public:
|
||||
|
||||
~DeletingModelArray()
|
||||
{
|
||||
for (unsigned i = 0; i<Size(); i++)
|
||||
{
|
||||
delete (*this)[i];
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
extern DeletingModelArray Models;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <string.h>
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "c_cvars.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
|
||||
/*
|
||||
** For handling of dynamically created quads when no persistently mapped
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "v_video.h"
|
||||
#include "vectors.h"
|
||||
#include "r_renderer.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/dynlights/gl_shadowmap.h"
|
||||
|
||||
struct particle_t;
|
||||
|
|
|
@ -50,6 +50,11 @@ CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
|
|||
static VSMatrix identityMatrix(1);
|
||||
TArray<VSMatrix> gl_MatrixStack;
|
||||
|
||||
static void matrixToGL(const VSMatrix &mat, int loc)
|
||||
{
|
||||
glUniformMatrix4fv(loc, 1, false, (float*)&mat);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -273,28 +278,28 @@ bool FRenderState::ApplyShader()
|
|||
}
|
||||
if (mTextureMatrixEnabled)
|
||||
{
|
||||
mTextureMatrix.matrixToGL(activeShader->texturematrix_index);
|
||||
matrixToGL(mTextureMatrix, activeShader->texturematrix_index);
|
||||
activeShader->currentTextureMatrixState = true;
|
||||
}
|
||||
else if (activeShader->currentTextureMatrixState)
|
||||
{
|
||||
activeShader->currentTextureMatrixState = false;
|
||||
identityMatrix.matrixToGL(activeShader->texturematrix_index);
|
||||
matrixToGL(identityMatrix, activeShader->texturematrix_index);
|
||||
}
|
||||
|
||||
if (mModelMatrixEnabled)
|
||||
{
|
||||
mModelMatrix.matrixToGL(activeShader->modelmatrix_index);
|
||||
matrixToGL(mModelMatrix, activeShader->modelmatrix_index);
|
||||
VSMatrix norm;
|
||||
norm.computeNormalMatrix(mModelMatrix);
|
||||
norm.matrixToGL(activeShader->normalmodelmatrix_index);
|
||||
matrixToGL(norm, activeShader->normalmodelmatrix_index);
|
||||
activeShader->currentModelMatrixState = true;
|
||||
}
|
||||
else if (activeShader->currentModelMatrixState)
|
||||
{
|
||||
activeShader->currentModelMatrixState = false;
|
||||
identityMatrix.matrixToGL(activeShader->modelmatrix_index);
|
||||
identityMatrix.matrixToGL(activeShader->normalmodelmatrix_index);
|
||||
matrixToGL(identityMatrix, activeShader->modelmatrix_index);
|
||||
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <string.h>
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "c_cvars.h"
|
||||
#include "r_defs.h"
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/utility/gl_templates.h"
|
||||
#include "gl/utility/gl_geometric.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/utility/gl_geometric.h"
|
||||
#include "gl/utility/gl_templates.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include <cstring> // needed for memcpy on linux, which is needed by VSMatrix copy ctor
|
||||
#include "tarray.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
|
||||
|
||||
|
|
|
@ -83,103 +83,4 @@ protected:
|
|||
float m_d;
|
||||
};
|
||||
|
||||
|
||||
class Matrix3x4 // used like a 4x4 matrix with the last row always being (0,0,0,1)
|
||||
{
|
||||
float m[3][4];
|
||||
|
||||
public:
|
||||
|
||||
void MakeIdentity()
|
||||
{
|
||||
memset(m, 0, sizeof(m));
|
||||
m[0][0] = m[1][1] = m[2][2] = 1.f;
|
||||
}
|
||||
|
||||
void Translate(float x, float y, float z)
|
||||
{
|
||||
m[0][3] = m[0][0]*x + m[0][1]*y + m[0][2]*z + m[0][3];
|
||||
m[1][3] = m[1][0]*x + m[1][1]*y + m[1][2]*z + m[1][3];
|
||||
m[2][3] = m[2][0]*x + m[2][1]*y + m[2][2]*z + m[2][3];
|
||||
}
|
||||
|
||||
void Scale(float x, float y, float z)
|
||||
{
|
||||
m[0][0] *=x;
|
||||
m[1][0] *=x;
|
||||
m[2][0] *=x;
|
||||
|
||||
m[0][1] *=y;
|
||||
m[1][1] *=y;
|
||||
m[2][1] *=y;
|
||||
|
||||
m[0][2] *=z;
|
||||
m[1][2] *=z;
|
||||
m[2][2] *=z;
|
||||
}
|
||||
|
||||
void Rotate(float ax, float ay, float az, float angle)
|
||||
{
|
||||
Matrix3x4 m1;
|
||||
|
||||
FVector3 axis(ax, ay, az);
|
||||
axis.MakeUnit();
|
||||
double c = cos(angle * M_PI/180.), s = sin(angle * M_PI/180.), t = 1 - c;
|
||||
double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z;
|
||||
double tx, ty, txx, tyy, u, v;
|
||||
|
||||
tx = t*axis.X;
|
||||
m1.m[0][0] = float( (txx=tx*axis.X) + c );
|
||||
m1.m[0][1] = float( (u=tx*axis.Y) - sz);
|
||||
m1.m[0][2] = float( (v=tx*axis.Z) + sy);
|
||||
|
||||
ty = t*axis.Y;
|
||||
m1.m[1][0] = float( u + sz);
|
||||
m1.m[1][1] = float( (tyy=ty*axis.Y) + c );
|
||||
m1.m[1][2] = float( (u=ty*axis.Z) - sx);
|
||||
|
||||
m1.m[2][0] = float( v - sy);
|
||||
m1.m[2][1] = float( u + sx);
|
||||
m1.m[2][2] = float( (t-txx-tyy) + c );
|
||||
|
||||
m1.m[0][3] = 0.f;
|
||||
m1.m[1][3] = 0.f;
|
||||
m1.m[2][3] = 0.f;
|
||||
|
||||
*this = (*this) * m1;
|
||||
}
|
||||
|
||||
Matrix3x4 operator *(const Matrix3x4 &other)
|
||||
{
|
||||
Matrix3x4 result;
|
||||
|
||||
result.m[0][0] = m[0][0]*other.m[0][0] + m[0][1]*other.m[1][0] + m[0][2]*other.m[2][0];
|
||||
result.m[0][1] = m[0][0]*other.m[0][1] + m[0][1]*other.m[1][1] + m[0][2]*other.m[2][1];
|
||||
result.m[0][2] = m[0][0]*other.m[0][2] + m[0][1]*other.m[1][2] + m[0][2]*other.m[2][2];
|
||||
result.m[0][3] = m[0][0]*other.m[0][3] + m[0][1]*other.m[1][3] + m[0][2]*other.m[2][3] + m[0][3];
|
||||
|
||||
result.m[1][0] = m[1][0]*other.m[0][0] + m[1][1]*other.m[1][0] + m[1][2]*other.m[2][0];
|
||||
result.m[1][1] = m[1][0]*other.m[0][1] + m[1][1]*other.m[1][1] + m[1][2]*other.m[2][1];
|
||||
result.m[1][2] = m[1][0]*other.m[0][2] + m[1][1]*other.m[1][2] + m[1][2]*other.m[2][2];
|
||||
result.m[1][3] = m[1][0]*other.m[0][3] + m[1][1]*other.m[1][3] + m[1][2]*other.m[2][3] + m[1][3];
|
||||
|
||||
result.m[2][0] = m[2][0]*other.m[0][0] + m[2][1]*other.m[1][0] + m[2][2]*other.m[2][0];
|
||||
result.m[2][1] = m[2][0]*other.m[0][1] + m[2][1]*other.m[1][1] + m[2][2]*other.m[2][1];
|
||||
result.m[2][2] = m[2][0]*other.m[0][2] + m[2][1]*other.m[1][2] + m[2][2]*other.m[2][2];
|
||||
result.m[2][3] = m[2][0]*other.m[0][3] + m[2][1]*other.m[1][3] + m[2][2]*other.m[2][3] + m[2][3];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FVector3 operator *(const FVector3 &vec)
|
||||
{
|
||||
FVector3 result;
|
||||
|
||||
result.X = vec.X*m[0][0] + vec.Y*m[0][1] + vec.Z*m[0][2] + m[0][3];
|
||||
result.Y = vec.X*m[1][0] + vec.Y*m[1][1] + vec.Z*m[1][2] + m[1][3];
|
||||
result.Z = vec.X*m[2][0] + vec.Y*m[2][1] + vec.Z*m[2][2] + m[2][3];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -130,11 +130,22 @@ int I_WaitForTic(int prevtic)
|
|||
int time;
|
||||
while ((time = I_GetTime()) <= prevtic)
|
||||
{
|
||||
// Windows-specific note:
|
||||
// The minimum amount of time a thread can sleep is controlled by timeBeginPeriod.
|
||||
// We set this to 1 ms in DoMain.
|
||||
uint64_t sleepTime = NSToMS(FirstFrameStartTime + TicToNS(prevtic + 1) - I_nsTime());
|
||||
if (sleepTime > 2)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2));
|
||||
|
||||
const uint64_t next = FirstFrameStartTime + TicToNS(prevtic + 1);
|
||||
const uint64_t now = I_nsTime();
|
||||
|
||||
if (next > now)
|
||||
{
|
||||
const uint64_t sleepTime = NSToMS(next - now);
|
||||
|
||||
if (sleepTime > 2)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2));
|
||||
}
|
||||
}
|
||||
|
||||
I_SetFrameTime();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "polyrenderer/poly_renderthread.h"
|
||||
#include "r_data/r_vanillatrans.h"
|
||||
#include "actorinlines.h"
|
||||
#include "i_time.h"
|
||||
|
||||
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
|
||||
{
|
||||
|
@ -102,12 +103,12 @@ void PolyModelRenderer::SetInterpolation(double interpolation)
|
|||
InterpolationFactor = (float)interpolation;
|
||||
}
|
||||
|
||||
void PolyModelRenderer::SetMaterial(FTexture *skin, int clampmode, int translation)
|
||||
void PolyModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int translation)
|
||||
{
|
||||
SkinTexture = skin;
|
||||
}
|
||||
|
||||
void PolyModelRenderer::DrawArrays(int primitiveType, int start, int count)
|
||||
void PolyModelRenderer::DrawArrays(int start, int count)
|
||||
{
|
||||
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
|
||||
|
@ -141,7 +142,7 @@ void PolyModelRenderer::DrawArrays(int primitiveType, int start, int count)
|
|||
args.DrawArray(Thread, VertexBuffer + start, count);
|
||||
}
|
||||
|
||||
void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elementType, size_t offset)
|
||||
void PolyModelRenderer::DrawElements(int numIndices, size_t offset)
|
||||
{
|
||||
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
|
||||
|
@ -177,7 +178,7 @@ void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elem
|
|||
|
||||
double PolyModelRenderer::GetTimeFloat()
|
||||
{
|
||||
return 0.0f; // (float)gl_frameMS * (float)TICRATE / 1000.0f;
|
||||
return (float)I_msTime() * (float)TICRATE / 1000.0f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "polyrenderer/drawers/poly_triangle.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
|
||||
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor);
|
||||
|
@ -43,9 +43,9 @@ public:
|
|||
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
|
||||
void EndDrawHUDModel(AActor *actor) override;
|
||||
void SetInterpolation(double interpolation) override;
|
||||
void SetMaterial(FTexture *skin, int clampmode, int translation) override;
|
||||
void DrawArrays(int primitiveType, int start, int count) override;
|
||||
void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override;
|
||||
void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override;
|
||||
void DrawArrays(int start, int count) override;
|
||||
void DrawElements(int numIndices, size_t offset) override;
|
||||
double GetTimeFloat() override;
|
||||
|
||||
PolyRenderThread *Thread = nullptr;
|
||||
|
|
|
@ -84,9 +84,6 @@ void SetLanguageIDs()
|
|||
}
|
||||
|
||||
|
||||
void I_InitTimer();
|
||||
void I_ShutdownTimer();
|
||||
|
||||
double PerfToSec, PerfToMillisec;
|
||||
|
||||
static void CalculateCPUSpeed()
|
||||
|
@ -114,7 +111,6 @@ void I_Init(void)
|
|||
|
||||
atterm(I_ShutdownSound);
|
||||
I_InitSound();
|
||||
I_InitTimer();
|
||||
}
|
||||
|
||||
static int has_exited;
|
||||
|
@ -129,8 +125,6 @@ void I_Quit()
|
|||
}
|
||||
|
||||
C_DeinitConsole();
|
||||
|
||||
I_ShutdownTimer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
** i_timer.cpp
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2012-2015 Alexey Lysiuk
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
|
||||
// To do: this file is obviously not needed anymore. It needs to be removed.
|
||||
|
||||
void I_InitTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void I_ShutdownTimer()
|
||||
{
|
||||
}
|
|
@ -119,9 +119,6 @@ void SetLanguageIDs ()
|
|||
LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang;
|
||||
}
|
||||
|
||||
void I_InitTimer ();
|
||||
void I_ShutdownTimer ();
|
||||
|
||||
//
|
||||
// I_Init
|
||||
//
|
||||
|
@ -132,7 +129,6 @@ void I_Init (void)
|
|||
|
||||
atterm (I_ShutdownSound);
|
||||
I_InitSound ();
|
||||
I_InitTimer ();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -148,8 +144,6 @@ void I_Quit (void)
|
|||
G_CheckDemoStatus();
|
||||
|
||||
C_DeinitConsole();
|
||||
|
||||
I_ShutdownTimer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
** i_timer.cpp
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2005-2016 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// Moved from sdl/i_system.cpp
|
||||
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "hardware.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
|
||||
void I_InitTimer ()
|
||||
{
|
||||
if(SDL_InitSubSystem(SDL_INIT_TIMER) < 0)
|
||||
I_FatalError("Could not initialize SDL timers:\n%s\n", SDL_GetError());
|
||||
|
||||
// Maybe this file isn't needed at all anymore.
|
||||
// Someone with Linux should test if the timer subsystem is used elsewhere..
|
||||
}
|
||||
|
||||
void I_ShutdownTimer ()
|
||||
{
|
||||
SDL_QuitSubSystem(SDL_INIT_TIMER);
|
||||
}
|
|
@ -11,13 +11,16 @@ This is a simplified version of VSMatrix that has been adjusted for GZDoom's nee
|
|||
----------------------------------------------------*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "gl/system/gl_system.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "doomtype.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244) // truncate from double to float
|
||||
#endif
|
||||
|
||||
static inline FLOATTYPE
|
||||
DegToRad(FLOATTYPE degrees)
|
||||
|
@ -310,22 +313,6 @@ VSMatrix::get(MatrixTypes aType)
|
|||
SEND MATRICES TO OPENGL
|
||||
------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
// universal
|
||||
void
|
||||
VSMatrix::matrixToGL(int loc)
|
||||
{
|
||||
#ifdef USE_DOUBLE
|
||||
float copyto[16];
|
||||
copy(copyto);
|
||||
glUniformMatrix4fv(loc, 1, false, copyto);
|
||||
#else
|
||||
glUniformMatrix4fv(loc, 1, false, mMatrix);
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// AUX functions
|
||||
// -----------------------------------------------------
|
|
@ -21,6 +21,8 @@
|
|||
#define __VSMatrix__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "vectors.h"
|
||||
#include "doomtype.h"
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
typedef double FLOATTYPE;
|
||||
|
@ -82,7 +84,6 @@ class VSMatrix {
|
|||
return mMatrix;
|
||||
}
|
||||
|
||||
void matrixToGL(int location);
|
||||
void multMatrixPoint(const FLOATTYPE *point, FLOATTYPE *res);
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
|
@ -112,4 +113,103 @@ class VSMatrix {
|
|||
|
||||
};
|
||||
|
||||
|
||||
class Matrix3x4 // used like a 4x4 matrix with the last row always being (0,0,0,1)
|
||||
{
|
||||
float m[3][4];
|
||||
|
||||
public:
|
||||
|
||||
void MakeIdentity()
|
||||
{
|
||||
memset(m, 0, sizeof(m));
|
||||
m[0][0] = m[1][1] = m[2][2] = 1.f;
|
||||
}
|
||||
|
||||
void Translate(float x, float y, float z)
|
||||
{
|
||||
m[0][3] = m[0][0]*x + m[0][1]*y + m[0][2]*z + m[0][3];
|
||||
m[1][3] = m[1][0]*x + m[1][1]*y + m[1][2]*z + m[1][3];
|
||||
m[2][3] = m[2][0]*x + m[2][1]*y + m[2][2]*z + m[2][3];
|
||||
}
|
||||
|
||||
void Scale(float x, float y, float z)
|
||||
{
|
||||
m[0][0] *=x;
|
||||
m[1][0] *=x;
|
||||
m[2][0] *=x;
|
||||
|
||||
m[0][1] *=y;
|
||||
m[1][1] *=y;
|
||||
m[2][1] *=y;
|
||||
|
||||
m[0][2] *=z;
|
||||
m[1][2] *=z;
|
||||
m[2][2] *=z;
|
||||
}
|
||||
|
||||
void Rotate(float ax, float ay, float az, float angle)
|
||||
{
|
||||
Matrix3x4 m1;
|
||||
|
||||
FVector3 axis(ax, ay, az);
|
||||
axis.MakeUnit();
|
||||
double c = cos(angle * M_PI/180.), s = sin(angle * M_PI/180.), t = 1 - c;
|
||||
double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z;
|
||||
double tx, ty, txx, tyy, u, v;
|
||||
|
||||
tx = t*axis.X;
|
||||
m1.m[0][0] = float( (txx=tx*axis.X) + c );
|
||||
m1.m[0][1] = float( (u=tx*axis.Y) - sz);
|
||||
m1.m[0][2] = float( (v=tx*axis.Z) + sy);
|
||||
|
||||
ty = t*axis.Y;
|
||||
m1.m[1][0] = float( u + sz);
|
||||
m1.m[1][1] = float( (tyy=ty*axis.Y) + c );
|
||||
m1.m[1][2] = float( (u=ty*axis.Z) - sx);
|
||||
|
||||
m1.m[2][0] = float( v - sy);
|
||||
m1.m[2][1] = float( u + sx);
|
||||
m1.m[2][2] = float( (t-txx-tyy) + c );
|
||||
|
||||
m1.m[0][3] = 0.f;
|
||||
m1.m[1][3] = 0.f;
|
||||
m1.m[2][3] = 0.f;
|
||||
|
||||
*this = (*this) * m1;
|
||||
}
|
||||
|
||||
Matrix3x4 operator *(const Matrix3x4 &other)
|
||||
{
|
||||
Matrix3x4 result;
|
||||
|
||||
result.m[0][0] = m[0][0]*other.m[0][0] + m[0][1]*other.m[1][0] + m[0][2]*other.m[2][0];
|
||||
result.m[0][1] = m[0][0]*other.m[0][1] + m[0][1]*other.m[1][1] + m[0][2]*other.m[2][1];
|
||||
result.m[0][2] = m[0][0]*other.m[0][2] + m[0][1]*other.m[1][2] + m[0][2]*other.m[2][2];
|
||||
result.m[0][3] = m[0][0]*other.m[0][3] + m[0][1]*other.m[1][3] + m[0][2]*other.m[2][3] + m[0][3];
|
||||
|
||||
result.m[1][0] = m[1][0]*other.m[0][0] + m[1][1]*other.m[1][0] + m[1][2]*other.m[2][0];
|
||||
result.m[1][1] = m[1][0]*other.m[0][1] + m[1][1]*other.m[1][1] + m[1][2]*other.m[2][1];
|
||||
result.m[1][2] = m[1][0]*other.m[0][2] + m[1][1]*other.m[1][2] + m[1][2]*other.m[2][2];
|
||||
result.m[1][3] = m[1][0]*other.m[0][3] + m[1][1]*other.m[1][3] + m[1][2]*other.m[2][3] + m[1][3];
|
||||
|
||||
result.m[2][0] = m[2][0]*other.m[0][0] + m[2][1]*other.m[1][0] + m[2][2]*other.m[2][0];
|
||||
result.m[2][1] = m[2][0]*other.m[0][1] + m[2][1]*other.m[1][1] + m[2][2]*other.m[2][1];
|
||||
result.m[2][2] = m[2][0]*other.m[0][2] + m[2][1]*other.m[1][2] + m[2][2]*other.m[2][2];
|
||||
result.m[2][3] = m[2][0]*other.m[0][3] + m[2][1]*other.m[1][3] + m[2][2]*other.m[2][3] + m[2][3];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FVector3 operator *(const FVector3 &vec)
|
||||
{
|
||||
FVector3 result;
|
||||
|
||||
result.X = vec.X*m[0][0] + vec.Y*m[0][1] + vec.Z*m[0][2] + m[0][3];
|
||||
result.Y = vec.X*m[1][0] + vec.Y*m[1][1] + vec.Z*m[1][2] + m[1][3];
|
||||
result.Z = vec.X*m[2][0] + vec.Y*m[2][1] + vec.Z*m[2][2] + m[2][3];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
880
src/r_data/models/models.cpp
Normal file
880
src/r_data/models/models.cpp
Normal file
|
@ -0,0 +1,880 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005-2016 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_models.cpp
|
||||
**
|
||||
** General model handling code
|
||||
**
|
||||
**/
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
#include "m_crc32.h"
|
||||
#include "c_console.h"
|
||||
#include "g_game.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "r_state.h"
|
||||
#include "d_player.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "r_utility.h"
|
||||
#include "i_time.h"
|
||||
#include "r_data/models/models.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data
|
||||
#endif
|
||||
|
||||
CVAR(Bool, gl_interpolate_model_frames, true, CVAR_ARCHIVE)
|
||||
EXTERN_CVAR(Bool, r_drawvoxels)
|
||||
|
||||
extern TDeletingArray<FVoxel *> Voxels;
|
||||
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
||||
|
||||
DeletingModelArray Models;
|
||||
|
||||
void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
|
||||
{
|
||||
// Setup transformation.
|
||||
|
||||
int translation = 0;
|
||||
if (!(smf->flags & MDL_IGNORETRANSLATION))
|
||||
translation = actor->Translation;
|
||||
|
||||
// y scale for a sprite means height, i.e. z in the world!
|
||||
float scaleFactorX = actor->Scale.X * smf->xscale;
|
||||
float scaleFactorY = actor->Scale.X * smf->yscale;
|
||||
float scaleFactorZ = actor->Scale.Y * smf->zscale;
|
||||
float pitch = 0;
|
||||
float roll = 0;
|
||||
double rotateOffset = 0;
|
||||
float angle = actor->Angles.Yaw.Degrees;
|
||||
|
||||
// [BB] Workaround for the missing pitch information.
|
||||
if ((smf->flags & MDL_PITCHFROMMOMENTUM))
|
||||
{
|
||||
const double x = actor->Vel.X;
|
||||
const double y = actor->Vel.Y;
|
||||
const double z = actor->Vel.Z;
|
||||
|
||||
if (actor->Vel.LengthSquared() > EQUAL_EPSILON)
|
||||
{
|
||||
// [BB] Calculate the pitch using spherical coordinates.
|
||||
if (z || x || y) pitch = float(atan(z / sqrt(x*x + y*y)) / M_PI * 180);
|
||||
|
||||
// Correcting pitch if model is moving backwards
|
||||
if (fabs(x) > EQUAL_EPSILON || fabs(y) > EQUAL_EPSILON)
|
||||
{
|
||||
if ((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1;
|
||||
}
|
||||
else pitch = fabs(pitch);
|
||||
}
|
||||
}
|
||||
|
||||
if (smf->flags & MDL_ROTATING)
|
||||
{
|
||||
const double time = smf->rotationSpeed*GetTimeFloat() / 200.;
|
||||
rotateOffset = double((time - xs_FloorToInt(time)) *360.);
|
||||
}
|
||||
|
||||
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
|
||||
// If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch.
|
||||
if (smf->flags & MDL_USEACTORPITCH)
|
||||
{
|
||||
double d = actor->Angles.Pitch.Degrees;
|
||||
if (smf->flags & MDL_BADROTATION) pitch += d;
|
||||
else pitch -= d;
|
||||
}
|
||||
if (smf->flags & MDL_USEACTORROLL) roll += actor->Angles.Roll.Degrees;
|
||||
|
||||
VSMatrix objectToWorldMatrix;
|
||||
objectToWorldMatrix.loadIdentity();
|
||||
|
||||
// Model space => World space
|
||||
objectToWorldMatrix.translate(x, z, y);
|
||||
|
||||
// [Nash] take SpriteRotation into account
|
||||
angle += actor->SpriteRotation.Degrees;
|
||||
|
||||
if (actor->renderflags & RF_INTERPOLATEANGLES)
|
||||
{
|
||||
// [Nash] use interpolated angles
|
||||
DRotator Angles = actor->InterpolatedAngles(r_viewpoint.TicFrac);
|
||||
angle = Angles.Yaw.Degrees;
|
||||
}
|
||||
|
||||
// Applying model transformations:
|
||||
// 1) Applying actor angle, pitch and roll to the model
|
||||
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
|
||||
|
||||
// 2) Applying Doomsday like rotation of the weapon pickup models
|
||||
// The rotation angle is based on the elapsed time.
|
||||
|
||||
if (smf->flags & MDL_ROTATING)
|
||||
{
|
||||
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY, smf->rotationCenterZ);
|
||||
objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
|
||||
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY, -smf->rotationCenterZ);
|
||||
}
|
||||
|
||||
// 3) Scaling model.
|
||||
objectToWorldMatrix.scale(scaleFactorX, scaleFactorZ, scaleFactorY);
|
||||
|
||||
// 4) Aplying model offsets (model offsets do not depend on model scalings).
|
||||
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale);
|
||||
|
||||
// 5) Applying model rotations.
|
||||
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
|
||||
|
||||
// consider the pixel stretching. For non-voxels this must be factored out here
|
||||
float stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor() : 1.f) / level.info->pixelstretch;
|
||||
objectToWorldMatrix.scale(1, stretch, 1);
|
||||
|
||||
BeginDrawModel(actor, smf, objectToWorldMatrix);
|
||||
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), nullptr, translation);
|
||||
EndDrawModel(actor, smf);
|
||||
}
|
||||
|
||||
void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
|
||||
{
|
||||
AActor * playermo = players[consoleplayer].camera;
|
||||
FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false);
|
||||
|
||||
// [BB] No model found for this sprite, so we can't render anything.
|
||||
if (smf == nullptr)
|
||||
return;
|
||||
|
||||
// The model position and orientation has to be drawn independently from the position of the player,
|
||||
// but we need to position it correctly in the world for light to work properly.
|
||||
VSMatrix objectToWorldMatrix = GetViewToWorldMatrix();
|
||||
|
||||
// Scaling model (y scale for a sprite means height, i.e. z in the world!).
|
||||
objectToWorldMatrix.scale(smf->xscale, smf->zscale, smf->yscale);
|
||||
|
||||
// Aplying model offsets (model offsets do not depend on model scalings).
|
||||
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale);
|
||||
|
||||
// [BB] Weapon bob, very similar to the normal Doom weapon bob.
|
||||
objectToWorldMatrix.rotate(ofsX / 4, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate((ofsY - WEAPONTOP) / -4., 1, 0, 0);
|
||||
|
||||
// [BB] For some reason the jDoom models need to be rotated.
|
||||
objectToWorldMatrix.rotate(90.f, 0, 1, 0);
|
||||
|
||||
// Applying angleoffset, pitchoffset, rolloffset.
|
||||
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
|
||||
|
||||
BeginDrawHUDModel(playermo, objectToWorldMatrix);
|
||||
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0);
|
||||
EndDrawHUDModel(playermo);
|
||||
}
|
||||
|
||||
void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
|
||||
const FState *curState,
|
||||
const int curTics,
|
||||
const PClass *ti,
|
||||
Matrix3x4 *normaltransform,
|
||||
int translation)
|
||||
{
|
||||
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
||||
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
||||
FSpriteModelFrame * smfNext = nullptr;
|
||||
double inter = 0.;
|
||||
if (gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION))
|
||||
{
|
||||
FState *nextState = curState->GetNextState();
|
||||
if (curState != nextState && nextState)
|
||||
{
|
||||
// [BB] To interpolate at more than 35 fps we take tic fractions into account.
|
||||
float ticFraction = 0.;
|
||||
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
|
||||
if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN))
|
||||
{
|
||||
double time = GetTimeFloat();
|
||||
ticFraction = (time - static_cast<int>(time));
|
||||
}
|
||||
inter = static_cast<double>(curState->Tics - curTics - ticFraction) / static_cast<double>(curState->Tics);
|
||||
|
||||
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
|
||||
// In this case inter is negative and we need to set it to zero.
|
||||
if (inter < 0.)
|
||||
inter = 0.;
|
||||
else
|
||||
{
|
||||
// [BB] Workaround for actors that use the same frame twice in a row.
|
||||
// Most of the standard Doom monsters do this in their see state.
|
||||
if ((smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES))
|
||||
{
|
||||
const FState *prevState = curState - 1;
|
||||
if ((curState->sprite == prevState->sprite) && (curState->Frame == prevState->Frame))
|
||||
{
|
||||
inter /= 2.;
|
||||
inter += 0.5;
|
||||
}
|
||||
if ((curState->sprite == nextState->sprite) && (curState->Frame == nextState->Frame))
|
||||
{
|
||||
inter /= 2.;
|
||||
nextState = nextState->GetNextState();
|
||||
}
|
||||
}
|
||||
if (inter != 0.0)
|
||||
smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<MAX_MODELS_PER_FRAME; i++)
|
||||
{
|
||||
if (smf->modelIDs[i] != -1)
|
||||
{
|
||||
FModel * mdl = Models[smf->modelIDs[i]];
|
||||
FTexture *tex = smf->skinIDs[i].isValid() ? TexMan(smf->skinIDs[i]) : nullptr;
|
||||
mdl->BuildVertexBuffer(this);
|
||||
SetVertexBuffer(mdl->mVBuf);
|
||||
|
||||
mdl->PushSpriteMDLFrame(smf, i);
|
||||
|
||||
if (smfNext && smf->modelframes[i] != smfNext->modelframes[i])
|
||||
mdl->RenderFrame(this, tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation);
|
||||
else
|
||||
mdl->RenderFrame(this, tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation);
|
||||
|
||||
ResetVertexBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void gl_LoadModels()
|
||||
{
|
||||
/*
|
||||
for (int i = Models.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
Models[i]->BuildVertexBuffer();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void gl_FlushModels()
|
||||
{
|
||||
for (int i = Models.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
Models[i]->DestroyVertexBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FModel::~FModel()
|
||||
{
|
||||
if (mVBuf != nullptr) delete mVBuf;
|
||||
}
|
||||
|
||||
static TArray<FSpriteModelFrame> SpriteModelFrames;
|
||||
static int * SpriteModelHash;
|
||||
//TArray<FStateModelFrame> StateModelFrames;
|
||||
|
||||
static void DeleteModelHash()
|
||||
{
|
||||
if (SpriteModelHash != nullptr) delete [] SpriteModelHash;
|
||||
SpriteModelHash = nullptr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FindGFXFile
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static int FindGFXFile(FString & fn)
|
||||
{
|
||||
int lump = Wads.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below.
|
||||
if (lump != -1) return lump;
|
||||
|
||||
int best = -1;
|
||||
int dot = fn.LastIndexOf('.');
|
||||
int slash = fn.LastIndexOf('/');
|
||||
if (dot > slash) fn.Truncate(dot);
|
||||
|
||||
static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", nullptr };
|
||||
|
||||
for (const char ** extp=extensions; *extp; extp++)
|
||||
{
|
||||
int lump = Wads.CheckNumForFullName(fn + *extp);
|
||||
if (lump >= best) best = lump;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// LoadSkin
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FTextureID LoadSkin(const char * path, const char * fn)
|
||||
{
|
||||
FString buffer;
|
||||
|
||||
buffer.Format("%s%s", path, fn);
|
||||
|
||||
int texlump = FindGFXFile(buffer);
|
||||
const char * const texname = texlump < 0 ? fn : Wads.GetLumpFullName(texlump);
|
||||
return TexMan.CheckForTexture(texname, FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ModelFrameHash
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static int ModelFrameHash(FSpriteModelFrame * smf)
|
||||
{
|
||||
const uint32_t *table = GetCRCTable ();
|
||||
uint32_t hash = 0xffffffff;
|
||||
|
||||
const char * s = (const char *)(&smf->type); // this uses type, sprite and frame for hashing
|
||||
const char * se= (const char *)(&smf->hashnext);
|
||||
|
||||
for (; s<se; s++)
|
||||
{
|
||||
hash = CRC1 (hash, *s, table);
|
||||
}
|
||||
return hash ^ 0xffffffff;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FindModel
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static unsigned FindModel(const char * path, const char * modelfile)
|
||||
{
|
||||
FModel * model = nullptr;
|
||||
FString fullname;
|
||||
|
||||
fullname.Format("%s%s", path, modelfile);
|
||||
int lump = Wads.CheckNumForFullName(fullname);
|
||||
|
||||
if (lump<0)
|
||||
{
|
||||
Printf("FindModel: '%s' not found\n", fullname.GetChars());
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i< Models.Size(); i++)
|
||||
{
|
||||
if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
|
||||
}
|
||||
|
||||
int len = Wads.LumpLength(lump);
|
||||
FMemLump lumpd = Wads.ReadLump(lump);
|
||||
char * buffer = (char*)lumpd.GetMem();
|
||||
|
||||
if (!memcmp(buffer, "DMDM", 4))
|
||||
{
|
||||
model = new FDMDModel;
|
||||
}
|
||||
else if (!memcmp(buffer, "IDP2", 4))
|
||||
{
|
||||
model = new FMD2Model;
|
||||
}
|
||||
else if (!memcmp(buffer, "IDP3", 4))
|
||||
{
|
||||
model = new FMD3Model;
|
||||
}
|
||||
|
||||
if (model != nullptr)
|
||||
{
|
||||
if (!model->Load(path, lump, buffer, len))
|
||||
{
|
||||
delete model;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// try loading as a voxel
|
||||
FVoxel *voxel = R_LoadKVX(lump);
|
||||
if (voxel != nullptr)
|
||||
{
|
||||
model = new FVoxelModel(voxel, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
|
||||
model->mFileName = fullname;
|
||||
return Models.Push(model);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_InitModels
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void gl_InitModels()
|
||||
{
|
||||
int Lump, lastLump;
|
||||
FString path;
|
||||
int index, surface;
|
||||
int i;
|
||||
|
||||
FSpriteModelFrame smf;
|
||||
|
||||
lastLump = 0;
|
||||
|
||||
for(unsigned i=0;i<Models.Size();i++)
|
||||
{
|
||||
delete Models[i];
|
||||
}
|
||||
Models.Clear();
|
||||
SpriteModelFrames.Clear();
|
||||
DeleteModelHash();
|
||||
|
||||
// First, create models for each voxel
|
||||
for (unsigned i = 0; i < Voxels.Size(); i++)
|
||||
{
|
||||
FVoxelModel *md = new FVoxelModel(Voxels[i], false);
|
||||
Voxels[i]->VoxelIndex = Models.Push(md);
|
||||
}
|
||||
// now create GL model frames for the voxeldefs
|
||||
for (unsigned i = 0; i < VoxelDefs.Size(); i++)
|
||||
{
|
||||
FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex];
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
|
||||
smf.skinIDs[0] = md->GetPaletteTexture();
|
||||
smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale;
|
||||
smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees;
|
||||
if (VoxelDefs[i]->PlacedSpin != 0)
|
||||
{
|
||||
smf.yrotate = 1.f;
|
||||
smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f;
|
||||
smf.flags |= MDL_ROTATING;
|
||||
}
|
||||
VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf);
|
||||
if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin)
|
||||
{
|
||||
if (VoxelDefs[i]->DroppedSpin != 0)
|
||||
{
|
||||
smf.yrotate = 1.f;
|
||||
smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f;
|
||||
smf.flags |= MDL_ROTATING;
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.yrotate = 0;
|
||||
smf.rotationSpeed = 0;
|
||||
smf.flags &= ~MDL_ROTATING;
|
||||
}
|
||||
SpriteModelFrames.Push(smf);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
|
||||
{
|
||||
FScanner sc(Lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("model"))
|
||||
{
|
||||
path = "";
|
||||
sc.MustGetString();
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
|
||||
smf.xscale=smf.yscale=smf.zscale=1.f;
|
||||
|
||||
smf.type = PClass::FindClass(sc.String);
|
||||
if (!smf.type || smf.type->Defaults == nullptr)
|
||||
{
|
||||
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
|
||||
}
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("path"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
path = sc.String;
|
||||
if (path[(int)path.Len()-1]!='/') path+='/';
|
||||
}
|
||||
else if (sc.Compare("model"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index = sc.Number;
|
||||
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
|
||||
if (smf.modelIDs[index] == -1)
|
||||
{
|
||||
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("scale"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xscale = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yscale = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zscale = sc.Float;
|
||||
}
|
||||
// [BB] Added zoffset reading.
|
||||
// Now it must be considered deprecated.
|
||||
else if (sc.Compare("zoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.zoffset=sc.Float;
|
||||
}
|
||||
// Offset reading.
|
||||
else if (sc.Compare("offset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xoffset = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yoffset = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zoffset = sc.Float;
|
||||
}
|
||||
// angleoffset, pitchoffset and rolloffset reading.
|
||||
else if (sc.Compare("angleoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.angleoffset = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("pitchoffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.pitchoffset = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rolloffset"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rolloffset = sc.Float;
|
||||
}
|
||||
// [BB] Added model flags reading.
|
||||
else if (sc.Compare("ignoretranslation"))
|
||||
{
|
||||
smf.flags |= MDL_IGNORETRANSLATION;
|
||||
}
|
||||
else if (sc.Compare("pitchfrommomentum"))
|
||||
{
|
||||
smf.flags |= MDL_PITCHFROMMOMENTUM;
|
||||
}
|
||||
else if (sc.Compare("inheritactorpitch"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
|
||||
}
|
||||
else if (sc.Compare("inheritactorroll"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORROLL;
|
||||
}
|
||||
else if (sc.Compare("useactorpitch"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORPITCH;
|
||||
}
|
||||
else if (sc.Compare("useactorroll"))
|
||||
{
|
||||
smf.flags |= MDL_USEACTORROLL;
|
||||
}
|
||||
else if (sc.Compare("rotating"))
|
||||
{
|
||||
smf.flags |= MDL_ROTATING;
|
||||
smf.xrotate = 0.;
|
||||
smf.yrotate = 1.;
|
||||
smf.zrotate = 0.;
|
||||
smf.rotationCenterX = 0.;
|
||||
smf.rotationCenterY = 0.;
|
||||
smf.rotationCenterZ = 0.;
|
||||
smf.rotationSpeed = 1.;
|
||||
}
|
||||
else if (sc.Compare("rotation-speed"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rotationSpeed = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rotation-vector"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.xrotate = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.yrotate = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.zrotate = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("rotation-center"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterX = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterY = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
smf.rotationCenterZ = sc.Float;
|
||||
}
|
||||
else if (sc.Compare("interpolatedoubledframes"))
|
||||
{
|
||||
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
|
||||
}
|
||||
else if (sc.Compare("nointerpolation"))
|
||||
{
|
||||
smf.flags |= MDL_NOINTERPOLATION;
|
||||
}
|
||||
else if (sc.Compare("skin"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index=sc.Number;
|
||||
if (index<0 || index>=MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
if (sc.Compare(""))
|
||||
{
|
||||
smf.skinIDs[index]=FNullTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
|
||||
if (!smf.skinIDs[index].isValid())
|
||||
{
|
||||
Printf("Skin '%s' not found in '%s'\n",
|
||||
sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("surfaceskin"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
index = sc.Number;
|
||||
sc.MustGetNumber();
|
||||
surface = sc.Number;
|
||||
|
||||
if (index<0 || index >= MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
if (surface<0 || surface >= MD3_MAX_SURFACES)
|
||||
{
|
||||
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
sc.MustGetString();
|
||||
FixPathSeperator(sc.String);
|
||||
if (sc.Compare(""))
|
||||
{
|
||||
smf.surfaceskinIDs[index][surface] = FNullTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
|
||||
if (!smf.surfaceskinIDs[index][surface].isValid())
|
||||
{
|
||||
Printf("Surface Skin '%s' not found in '%s'\n",
|
||||
sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("frameindex") || sc.Compare("frame"))
|
||||
{
|
||||
bool isframe=!!sc.Compare("frame");
|
||||
|
||||
sc.MustGetString();
|
||||
smf.sprite = -1;
|
||||
for (i = 0; i < (int)sprites.Size (); ++i)
|
||||
{
|
||||
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
|
||||
{
|
||||
if (sprites[i].numframes==0)
|
||||
{
|
||||
//sc.ScriptError("Sprite %s has no frames", sc.String);
|
||||
}
|
||||
smf.sprite = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (smf.sprite==-1)
|
||||
{
|
||||
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
|
||||
sc.MustGetString();
|
||||
FString framechars = sc.String;
|
||||
|
||||
sc.MustGetNumber();
|
||||
index=sc.Number;
|
||||
if (index<0 || index>=MAX_MODELS_PER_FRAME)
|
||||
{
|
||||
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
|
||||
}
|
||||
if (isframe)
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (smf.modelIDs[index] != -1)
|
||||
{
|
||||
FModel *model = Models[smf.modelIDs[index]];
|
||||
smf.modelframes[index] = model->FindFrame(sc.String);
|
||||
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
|
||||
}
|
||||
else smf.modelframes[index] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
smf.modelframes[index] = sc.Number;
|
||||
}
|
||||
|
||||
for(i=0; framechars[i]>0; i++)
|
||||
{
|
||||
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int c = toupper(framechars[i])-'A';
|
||||
|
||||
if (c<0 || c>=29)
|
||||
{
|
||||
sc.ScriptError("Invalid frame character %c found", c+'A');
|
||||
}
|
||||
if (map[c]) continue;
|
||||
smf.frame=c;
|
||||
SpriteModelFrames.Push(smf);
|
||||
GetDefaultByType(smf.type)->hasmodel = true;
|
||||
map[c]=1;
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("dontcullbackfaces"))
|
||||
{
|
||||
smf.flags |= MDL_DONTCULLBACKFACES;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a hash table for quick access
|
||||
SpriteModelHash = new int[SpriteModelFrames.Size ()];
|
||||
atterm(DeleteModelHash);
|
||||
memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int));
|
||||
|
||||
for (i = 0; i < (int)SpriteModelFrames.Size (); i++)
|
||||
{
|
||||
int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size ();
|
||||
|
||||
SpriteModelFrames[i].hashnext = SpriteModelHash[j];
|
||||
SpriteModelHash[j]=i;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_FindModelFrame
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
|
||||
{
|
||||
if (GetDefaultByType(ti)->hasmodel)
|
||||
{
|
||||
FSpriteModelFrame smf;
|
||||
|
||||
memset(&smf, 0, sizeof(smf));
|
||||
smf.type=ti;
|
||||
smf.sprite=sprite;
|
||||
smf.frame=frame;
|
||||
|
||||
int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()];
|
||||
|
||||
while (hash>=0)
|
||||
{
|
||||
FSpriteModelFrame * smff = &SpriteModelFrames[hash];
|
||||
if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff;
|
||||
hash=smff->hashnext;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for voxel replacements
|
||||
if (r_drawvoxels)
|
||||
{
|
||||
spritedef_t *sprdef = &sprites[sprite];
|
||||
if (frame < sprdef->numframes)
|
||||
{
|
||||
spriteframe_t *sprframe = &SpriteFrames[sprdef->spriteframes + frame];
|
||||
if (sprframe->Voxel != nullptr)
|
||||
{
|
||||
int index = sprframe->Voxel->VoxeldefIndex;
|
||||
if (dropped && sprframe->Voxel->DroppedSpin !=sprframe->Voxel->PlacedSpin) index++;
|
||||
return &SpriteModelFrames[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_IsHUDModelForPlayerAvailable
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool gl_IsHUDModelForPlayerAvailable (player_t * player)
|
||||
{
|
||||
if (player == nullptr || player->ReadyWeapon == nullptr)
|
||||
return false;
|
||||
|
||||
DPSprite *psp = player->FindPSprite(PSP_WEAPON);
|
||||
|
||||
if (psp == nullptr || psp->GetState() == nullptr)
|
||||
return false;
|
||||
|
||||
FState* state = psp->GetState();
|
||||
FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false);
|
||||
return ( smf != nullptr );
|
||||
}
|
||||
|
496
src/r_data/models/models.h
Normal file
496
src/r_data/models/models.h
Normal file
|
@ -0,0 +1,496 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005-2016 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#ifndef __GL_MODELS_H_
|
||||
#define __GL_MODELS_H_
|
||||
|
||||
#include "tarray.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "actor.h"
|
||||
#include "dobject.h"
|
||||
#include "p_pspr.h"
|
||||
#include "r_data/voxels.h"
|
||||
#include "info.h"
|
||||
|
||||
#define MAX_LODS 4
|
||||
|
||||
enum { VX, VZ, VY };
|
||||
|
||||
#define MD2_MAGIC 0x32504449
|
||||
#define DMD_MAGIC 0x4D444D44
|
||||
#define MD3_MAGIC 0x33504449
|
||||
#define NUMVERTEXNORMALS 162
|
||||
#define MD3_MAX_SURFACES 32
|
||||
|
||||
FTextureID LoadSkin(const char * path, const char * fn);
|
||||
|
||||
struct FSpriteModelFrame;
|
||||
class IModelVertexBuffer;
|
||||
|
||||
class FModelRenderer
|
||||
{
|
||||
public:
|
||||
virtual ~FModelRenderer() { }
|
||||
|
||||
void RenderModel(float x, float y, float z, FSpriteModelFrame *modelframe, AActor *actor);
|
||||
void RenderHUDModel(DPSprite *psp, float ofsx, float ofsy);
|
||||
|
||||
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0;
|
||||
virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0;
|
||||
|
||||
virtual IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) = 0;
|
||||
|
||||
virtual void SetVertexBuffer(IModelVertexBuffer *buffer) = 0;
|
||||
virtual void ResetVertexBuffer() = 0;
|
||||
|
||||
virtual VSMatrix GetViewToWorldMatrix() = 0;
|
||||
|
||||
virtual void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) = 0;
|
||||
virtual void EndDrawHUDModel(AActor *actor) = 0;
|
||||
|
||||
virtual void SetInterpolation(double interpolation) = 0;
|
||||
virtual void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) = 0;
|
||||
virtual void DrawArrays(int start, int count) = 0;
|
||||
virtual void DrawElements(int numIndices, size_t offset) = 0;
|
||||
|
||||
virtual double GetTimeFloat() = 0;
|
||||
|
||||
private:
|
||||
void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation);
|
||||
};
|
||||
|
||||
struct FModelVertex
|
||||
{
|
||||
float x, y, z; // world position
|
||||
float u, v; // texture coordinates
|
||||
unsigned packedNormal; // normal vector as GL_INT_2_10_10_10_REV.
|
||||
|
||||
void Set(float xx, float yy, float zz, float uu, float vv)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
z = zz;
|
||||
u = uu;
|
||||
v = vv;
|
||||
}
|
||||
|
||||
void SetNormal(float nx, float ny, float nz)
|
||||
{
|
||||
int inx = clamp(int(nx * 512), -512, 511);
|
||||
int iny = clamp(int(ny * 512), -512, 511);
|
||||
int inz = clamp(int(nz * 512), -512, 511);
|
||||
int inw = 0;
|
||||
packedNormal = (inw << 30) | ((inz & 1023) << 20) | ((iny & 1023) << 10) | (inx & 1023);
|
||||
}
|
||||
};
|
||||
|
||||
#define VMO ((FModelVertex*)NULL)
|
||||
|
||||
class FModelRenderer;
|
||||
|
||||
class IModelVertexBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~IModelVertexBuffer() { }
|
||||
|
||||
virtual FModelVertex *LockVertexBuffer(unsigned int size) = 0;
|
||||
virtual void UnlockVertexBuffer() = 0;
|
||||
|
||||
virtual unsigned int *LockIndexBuffer(unsigned int size) = 0;
|
||||
virtual void UnlockIndexBuffer() = 0;
|
||||
|
||||
virtual void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) = 0;
|
||||
};
|
||||
|
||||
class FModel
|
||||
{
|
||||
public:
|
||||
|
||||
FModel()
|
||||
{
|
||||
mVBuf = NULL;
|
||||
}
|
||||
virtual ~FModel();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
|
||||
virtual int FindFrame(const char * name) = 0;
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0;
|
||||
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
|
||||
virtual void AddSkins(uint8_t *hitlist) = 0;
|
||||
void DestroyVertexBuffer()
|
||||
{
|
||||
delete mVBuf;
|
||||
mVBuf = NULL;
|
||||
}
|
||||
virtual float getAspectFactor() { return 1.f; }
|
||||
|
||||
const FSpriteModelFrame *curSpriteMDLFrame;
|
||||
int curMDLIndex;
|
||||
void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; };
|
||||
|
||||
IModelVertexBuffer *mVBuf;
|
||||
FString mFileName;
|
||||
};
|
||||
|
||||
class FDMDModel : public FModel
|
||||
{
|
||||
protected:
|
||||
|
||||
struct FTriangle
|
||||
{
|
||||
unsigned short vertexIndices[3];
|
||||
unsigned short textureIndices[3];
|
||||
};
|
||||
|
||||
|
||||
struct DMDHeader
|
||||
{
|
||||
int magic;
|
||||
int version;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct DMDModelVertex
|
||||
{
|
||||
float xyz[3];
|
||||
};
|
||||
|
||||
struct FTexCoord
|
||||
{
|
||||
short s, t;
|
||||
};
|
||||
|
||||
struct FGLCommandVertex
|
||||
{
|
||||
float s, t;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct DMDInfo
|
||||
{
|
||||
int skinWidth;
|
||||
int skinHeight;
|
||||
int frameSize;
|
||||
int numSkins;
|
||||
int numVertices;
|
||||
int numTexCoords;
|
||||
int numFrames;
|
||||
int numLODs;
|
||||
int offsetSkins;
|
||||
int offsetTexCoords;
|
||||
int offsetFrames;
|
||||
int offsetLODs;
|
||||
int offsetEnd;
|
||||
};
|
||||
|
||||
struct ModelFrame
|
||||
{
|
||||
char name[16];
|
||||
unsigned int vindex;
|
||||
};
|
||||
|
||||
struct ModelFrameVertexData
|
||||
{
|
||||
DMDModelVertex *vertices;
|
||||
DMDModelVertex *normals;
|
||||
};
|
||||
|
||||
struct DMDLoDInfo
|
||||
{
|
||||
int numTriangles;
|
||||
int numGlCommands;
|
||||
int offsetTriangles;
|
||||
int offsetGlCommands;
|
||||
};
|
||||
|
||||
struct DMDLoD
|
||||
{
|
||||
FTriangle * triangles;
|
||||
};
|
||||
|
||||
|
||||
int mLumpNum;
|
||||
DMDHeader header;
|
||||
DMDInfo info;
|
||||
FTextureID * skins;
|
||||
ModelFrame * frames;
|
||||
bool allowTexComp; // Allow texture compression with this.
|
||||
|
||||
// Temp data only needed for buffer construction
|
||||
FTexCoord * texCoords;
|
||||
ModelFrameVertexData *framevtx;
|
||||
DMDLoDInfo lodInfo[MAX_LODS];
|
||||
DMDLoD lods[MAX_LODS];
|
||||
|
||||
public:
|
||||
FDMDModel()
|
||||
{
|
||||
mLumpNum = -1;
|
||||
frames = NULL;
|
||||
skins = NULL;
|
||||
for (int i = 0; i < MAX_LODS; i++)
|
||||
{
|
||||
lods[i].triangles = NULL;
|
||||
}
|
||||
info.numLODs = 0;
|
||||
texCoords = NULL;
|
||||
framevtx = NULL;
|
||||
}
|
||||
virtual ~FDMDModel();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
virtual void LoadGeometry();
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
|
||||
void UnloadGeometry();
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
|
||||
};
|
||||
|
||||
// This uses the same internal representation as DMD
|
||||
class FMD2Model : public FDMDModel
|
||||
{
|
||||
public:
|
||||
FMD2Model() {}
|
||||
virtual ~FMD2Model();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual void LoadGeometry();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FMD3Model : public FModel
|
||||
{
|
||||
struct MD3Tag
|
||||
{
|
||||
// Currently I have no use for this
|
||||
};
|
||||
|
||||
struct MD3TexCoord
|
||||
{
|
||||
float s,t;
|
||||
};
|
||||
|
||||
struct MD3Vertex
|
||||
{
|
||||
float x,y,z;
|
||||
float nx,ny,nz;
|
||||
};
|
||||
|
||||
struct MD3Triangle
|
||||
{
|
||||
int VertIndex[3];
|
||||
};
|
||||
|
||||
struct MD3Surface
|
||||
{
|
||||
int numVertices;
|
||||
int numTriangles;
|
||||
int numSkins;
|
||||
|
||||
FTextureID * skins;
|
||||
MD3Triangle * tris;
|
||||
MD3TexCoord * texcoords;
|
||||
MD3Vertex * vertices;
|
||||
|
||||
unsigned int vindex; // contains numframes arrays of vertices
|
||||
unsigned int iindex;
|
||||
|
||||
MD3Surface()
|
||||
{
|
||||
tris=NULL;
|
||||
vertices=NULL;
|
||||
texcoords=NULL;
|
||||
vindex = iindex = UINT_MAX;
|
||||
}
|
||||
|
||||
~MD3Surface()
|
||||
{
|
||||
if (skins) delete [] skins;
|
||||
UnloadGeometry();
|
||||
}
|
||||
|
||||
void UnloadGeometry()
|
||||
{
|
||||
if (tris) delete [] tris;
|
||||
if (vertices) delete [] vertices;
|
||||
if (texcoords) delete [] texcoords;
|
||||
tris = NULL;
|
||||
vertices = NULL;
|
||||
texcoords = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
struct MD3Frame
|
||||
{
|
||||
// The bounding box information is of no use in the Doom engine
|
||||
// That will still be done with the actor's size information.
|
||||
char Name[16];
|
||||
float origin[3];
|
||||
};
|
||||
|
||||
int numFrames;
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
int mLumpNum;
|
||||
|
||||
MD3Frame * frames;
|
||||
MD3Surface * surfaces;
|
||||
|
||||
public:
|
||||
FMD3Model() { }
|
||||
virtual ~FMD3Model();
|
||||
|
||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
void LoadGeometry();
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
};
|
||||
|
||||
struct FVoxelVertexHash
|
||||
{
|
||||
// Returns the hash value for a key.
|
||||
hash_t Hash(const FModelVertex &key)
|
||||
{
|
||||
int ix = xs_RoundToInt(key.x);
|
||||
int iy = xs_RoundToInt(key.y);
|
||||
int iz = xs_RoundToInt(key.z);
|
||||
return (hash_t)(ix + (iy<<9) + (iz<<18));
|
||||
}
|
||||
|
||||
// Compares two keys, returning zero if they are the same.
|
||||
int Compare(const FModelVertex &left, const FModelVertex &right)
|
||||
{
|
||||
return left.x != right.x || left.y != right.y || left.z != right.z || left.u != right.u || left.v != right.v;
|
||||
}
|
||||
};
|
||||
|
||||
struct FIndexInit
|
||||
{
|
||||
void Init(unsigned int &value)
|
||||
{
|
||||
value = 0xffffffff;
|
||||
}
|
||||
};
|
||||
|
||||
typedef TMap<FModelVertex, unsigned int, FVoxelVertexHash, FIndexInit> FVoxelMap;
|
||||
|
||||
|
||||
class FVoxelModel : public FModel
|
||||
{
|
||||
protected:
|
||||
FVoxel *mVoxel;
|
||||
bool mOwningVoxel; // if created through MODELDEF deleting this object must also delete the voxel object
|
||||
FTextureID mPalette;
|
||||
unsigned int mNumIndices;
|
||||
TArray<FModelVertex> mVertices;
|
||||
TArray<unsigned int> mIndices;
|
||||
|
||||
void MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &check);
|
||||
void AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, uint8_t color, FVoxelMap &check);
|
||||
unsigned int AddVertex(FModelVertex &vert, FVoxelMap &check);
|
||||
|
||||
public:
|
||||
FVoxelModel(FVoxel *voxel, bool owned);
|
||||
~FVoxelModel();
|
||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
void Initialize();
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
FTextureID GetPaletteTexture() const { return mPalette; }
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
float getAspectFactor();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_MODELS_PER_FRAME 4
|
||||
|
||||
//
|
||||
// [BB] Model rendering flags.
|
||||
//
|
||||
enum
|
||||
{
|
||||
// [BB] Color translations for the model skin are ignored. This is
|
||||
// useful if the skin texture is not using the game palette.
|
||||
MDL_IGNORETRANSLATION = 1,
|
||||
MDL_PITCHFROMMOMENTUM = 2,
|
||||
MDL_ROTATING = 4,
|
||||
MDL_INTERPOLATEDOUBLEDFRAMES = 8,
|
||||
MDL_NOINTERPOLATION = 16,
|
||||
MDL_USEACTORPITCH = 32,
|
||||
MDL_USEACTORROLL = 64,
|
||||
MDL_BADROTATION = 128,
|
||||
MDL_DONTCULLBACKFACES = 256,
|
||||
};
|
||||
|
||||
struct FSpriteModelFrame
|
||||
{
|
||||
int modelIDs[MAX_MODELS_PER_FRAME];
|
||||
FTextureID skinIDs[MAX_MODELS_PER_FRAME];
|
||||
FTextureID surfaceskinIDs[MAX_MODELS_PER_FRAME][MD3_MAX_SURFACES];
|
||||
int modelframes[MAX_MODELS_PER_FRAME];
|
||||
float xscale, yscale, zscale;
|
||||
// [BB] Added zoffset, rotation parameters and flags.
|
||||
// Added xoffset, yoffset
|
||||
float xoffset, yoffset, zoffset;
|
||||
float xrotate, yrotate, zrotate;
|
||||
float rotationCenterX, rotationCenterY, rotationCenterZ;
|
||||
float rotationSpeed;
|
||||
unsigned int flags;
|
||||
const PClass * type;
|
||||
short sprite;
|
||||
short frame;
|
||||
FState * state; // for later!
|
||||
int hashnext;
|
||||
float angleoffset;
|
||||
// added pithoffset, rolloffset.
|
||||
float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float.
|
||||
};
|
||||
|
||||
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
|
||||
|
||||
bool gl_IsHUDModelForPlayerAvailable (player_t * player);
|
||||
|
||||
class DeletingModelArray : public TArray<FModel *>
|
||||
{
|
||||
public:
|
||||
|
||||
~DeletingModelArray()
|
||||
{
|
||||
for (unsigned i = 0; i<Size(); i++)
|
||||
{
|
||||
delete (*this)[i];
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
extern DeletingModelArray Models;
|
||||
|
||||
#endif
|
|
@ -20,25 +20,21 @@
|
|||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_models.cpp
|
||||
** models.cpp
|
||||
**
|
||||
** MD2/DMD model format code
|
||||
**
|
||||
**/
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
#include "m_crc32.h"
|
||||
#include "r_data/models/models.h"
|
||||
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data
|
||||
#endif
|
||||
|
||||
static float avertexnormals[NUMVERTEXNORMALS][3] = {
|
||||
#include "tab_anorms.h"
|
||||
|
@ -374,9 +370,9 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
|
|||
}
|
||||
|
||||
renderer->SetInterpolation(inter);
|
||||
renderer->SetMaterial(skin, CLAMP_NONE, translation);
|
||||
renderer->SetMaterial(skin, false, translation);
|
||||
mVBuf->SetupFrame(renderer, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3);
|
||||
renderer->DrawArrays(GL_TRIANGLES, 0, lodInfo[0].numTriangles * 3);
|
||||
renderer->DrawArrays(0, lodInfo[0].numTriangles * 3);
|
||||
renderer->SetInterpolation(0.f);
|
||||
}
|
||||
|
|
@ -20,21 +20,18 @@
|
|||
//--------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
#include "m_crc32.h"
|
||||
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "r_data/models/models.h"
|
||||
|
||||
#define MAX_QPATH 64
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// decode the lat/lng normal to a 3 float normal
|
||||
|
@ -367,9 +364,9 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
|
|||
if (!surfaceSkin) return;
|
||||
}
|
||||
|
||||
renderer->SetMaterial(surfaceSkin, CLAMP_NONE, translation);
|
||||
renderer->SetMaterial(surfaceSkin, false, translation);
|
||||
mVBuf->SetupFrame(renderer, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices);
|
||||
renderer->DrawElements(GL_TRIANGLES, surf->numTriangles * 3, GL_UNSIGNED_INT, surf->iindex * sizeof(unsigned int));
|
||||
renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int));
|
||||
}
|
||||
renderer->SetInterpolation(0.f);
|
||||
}
|
|
@ -26,7 +26,6 @@
|
|||
**
|
||||
**/
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
|
@ -38,17 +37,12 @@
|
|||
#include "colormatcher.h"
|
||||
#include "textures/bitmap.h"
|
||||
#include "g_levellocals.h"
|
||||
//#include "gl/gl_intern.h"
|
||||
#include "models.h"
|
||||
#include "v_palette.h"
|
||||
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/utility/gl_geometric.h"
|
||||
#include "gl/utility/gl_convert.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -440,8 +434,8 @@ float FVoxelModel::getAspectFactor()
|
|||
|
||||
void FVoxelModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation)
|
||||
{
|
||||
renderer->SetMaterial(skin, CLAMP_NOFILTER, translation);
|
||||
renderer->SetMaterial(skin, true, translation);
|
||||
mVBuf->SetupFrame(renderer, 0, 0, 0);
|
||||
renderer->DrawElements(GL_TRIANGLES, mNumIndices, GL_UNSIGNED_INT, 0);
|
||||
renderer->DrawElements(mNumIndices, 0);
|
||||
}
|
||||
|
|
@ -30,10 +30,6 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "mpg123_decoder.h"
|
||||
#include "files.h"
|
||||
|
|
|
@ -32,13 +32,6 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
|
|
@ -30,11 +30,6 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile_decoder.h"
|
||||
#include "templates.h"
|
||||
#include "files.h"
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "c_cvars.h"
|
||||
#include "doomstat.h"
|
||||
#include "v_video.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
|
@ -1384,6 +1385,8 @@ void ShowEAXEditor ()
|
|||
EAXEditWindow = CreateDialog (g_hInst, MAKEINTRESOURCE(IDD_EAXEDIT), Window, EAXProc);
|
||||
}
|
||||
|
||||
extern int NewWidth, NewHeight, NewBits, DisplayBits;
|
||||
|
||||
CCMD (reverbedit)
|
||||
{
|
||||
if (EAXEditWindow != 0)
|
||||
|
@ -1395,6 +1398,9 @@ CCMD (reverbedit)
|
|||
ForceWindowed = true;
|
||||
if (fullscreen)
|
||||
{
|
||||
NewWidth = screen->VideoWidth;
|
||||
NewHeight = screen->VideoHeight;
|
||||
NewBits = DisplayBits;
|
||||
setmodeneeded = true;
|
||||
SpawnEAXWindow = true;
|
||||
}
|
||||
|
|
|
@ -820,7 +820,7 @@ void I_SetFPSLimit(int limit)
|
|||
{
|
||||
CloseHandle(FPSLimitEvent);
|
||||
FPSLimitEvent = NULL;
|
||||
Printf("Failed to create FPS limitter timer\n");
|
||||
Printf("Failed to create FPS limiter timer\n");
|
||||
return;
|
||||
}
|
||||
DPrintf(DMSG_NOTIFY, "FPS timer set to %u ms\n", period);
|
||||
|
|
|
@ -796,7 +796,7 @@ class Ceiling : MovingCeiling native
|
|||
crushSlowdown = 2
|
||||
}
|
||||
|
||||
native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom);
|
||||
native static bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue