md3-vanilla

This commit is contained in:
Jaime Passos 2019-03-18 18:34:20 -03:00
parent 9879734d52
commit f210053735
25 changed files with 2921 additions and 962 deletions

View file

@ -399,7 +399,11 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
)
set (SRB2_HWRENDER_HEADERS
@ -413,6 +417,10 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h
)
set(SRB2_R_OPENGL_SOURCES

View file

@ -279,7 +279,8 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
endif
ifdef NOHS
@ -732,16 +733,18 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
endif
@ -893,24 +896,27 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif

View file

@ -366,16 +366,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Miscellaneous types that don't fit anywhere else (Can this be changed?) */
typedef struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} byteColor_t;
union FColorRGBA
{
UINT32 rgba;
struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} s;
byteColor_t s;
} ATTRPACK;
typedef union FColorRGBA RGBA_t;

View file

@ -89,14 +89,29 @@ typedef struct
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
//#define USE_FTRANSFORM_ANGLEZ
//#define USE_FTRANSFORM_MIRROR
// Vanilla features
#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
INT32 splitscreen;
UINT8 splitscreen;
boolean flip; // screenflip
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
#endif
} FTransform;
// Transformed vector, as passed to HWR API
@ -108,14 +123,6 @@ typedef struct
FUINT argb; // flat-shaded color
} FOutVector;
// jimita
typedef struct
{
float vx, vy, vz;
float nx, ny, nz;
float s, t;
} FOutVectorMD2;
// ==========================================================================
// RENDER MODES
// ==========================================================================

View file

@ -52,7 +52,8 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
@ -95,7 +96,8 @@ struct hwdriver_s
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;
DrawMD2 pfnDrawMD2;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed;
GetRenderVersion pfnGetRenderVersion;

View file

@ -35,6 +35,9 @@
#include "../w_wad.h"
#include "../z_zone.h"
#include "../r_things.h"
#include "../r_draw.h"
#include "../p_tick.h"
#include "hw_model.h"
#include "hw_main.h"
#include "../v_video.h"
@ -67,171 +70,6 @@
#include "errno.h"
#endif
#define NUMVERTEXNORMALS 162
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
md2_t md2_models[NUMSPRITES];
md2_t md2_playermodels[MAXSKINS];
@ -240,194 +78,24 @@ md2_t md2_playermodels[MAXSKINS];
/*
* free model
*/
static void md2_freeModel (md2_model_t *model)
#if 0
static void md2_freeModel (model_t *model)
{
if (model)
{
if (model->skins)
free(model->skins);
if (model->texCoords)
free(model->texCoords);
if (model->triangles)
free(model->triangles);
if (model->frames)
{
size_t i;
for (i = 0; i < model->header.numFrames; i++)
{
if (model->frames[i].vertices)
free(model->frames[i].vertices);
}
free(model->frames);
}
if (model->glCommandBuffer)
free(model->glCommandBuffer);
free(model);
}
UnloadModel(model);
}
#endif
//
// load model
//
// Hurdler: the current path is the Legacy.exe path
static md2_model_t *md2_readModel(const char *filename)
static model_t *md2_readModel(const char *filename)
{
FILE *file;
md2_model_t *model;
UINT8 buffer[MD2_MAX_FRAMESIZE];
size_t i;
model = calloc(1, sizeof (*model));
if (model == NULL)
return 0;
//Filename checking fixed ~Monster Iestyn and Golden
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
if (!file)
{
free(model);
return 0;
}
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
|| model->header.magic != MD2_IDENT
|| model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
return 0;
}
model->header.numSkins = 1;
#define MD2LIMITCHECK(field, max, msgname) \
if (field > max) \
{ \
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \
fclose(file); \
return 0; \
}
// Uncomment if these are actually needed
// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins")
// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates")
MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles")
MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames")
MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices")
#undef MD2LIMITCHECK
// read skins
fseek(file, model->header.offsetSkins, SEEK_SET);
if (model->header.numSkins > 0)
{
model->skins = calloc(sizeof (md2_skin_t), model->header.numSkins);
if (!model->skins || model->header.numSkins !=
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read texture coordinates
fseek(file, model->header.offsetTexCoords, SEEK_SET);
if (model->header.numTexCoords > 0)
{
model->texCoords = calloc(sizeof (md2_textureCoordinate_t), model->header.numTexCoords);
if (!model->texCoords || model->header.numTexCoords !=
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read triangles
fseek(file, model->header.offsetTriangles, SEEK_SET);
if (model->header.numTriangles > 0)
{
model->triangles = calloc(sizeof (md2_triangle_t), model->header.numTriangles);
if (!model->triangles || model->header.numTriangles !=
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read alias frames
fseek(file, model->header.offsetFrames, SEEK_SET);
if (model->header.numFrames > 0)
{
model->frames = calloc(sizeof (md2_frame_t), model->header.numFrames);
if (!model->frames)
{
md2_freeModel (model);
fclose(file);
return 0;
}
for (i = 0; i < model->header.numFrames; i++)
{
md2_alias_frame_t *frame = (md2_alias_frame_t *)(void *)buffer;
size_t j;
model->frames[i].vertices = calloc(sizeof (md2_triangleVertex_t), model->header.numVertices);
if (!model->frames[i].vertices || model->header.frameSize !=
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
strcpy(model->frames[i].name, frame->name);
for (j = 0; j < model->header.numVertices; j++)
{
model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0];
model->frames[i].vertices[j].vertex[2] = -1* ((float) ((INT32) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]);
model->frames[i].vertices[j].vertex[1] = (float) ((INT32) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2];
model->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0];
model->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1];
model->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2];
}
}
}
// read gl commands
fseek(file, model->header.offsetGlCommands, SEEK_SET);
if (model->header.numGlCommands)
{
model->glCommandBuffer = calloc(sizeof (INT32), model->header.numGlCommands);
if (!model->glCommandBuffer || model->header.numGlCommands !=
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
fclose(file);
return model;
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
}
static inline void md2_printModelInfo (md2_model_t *model)
static inline void md2_printModelInfo (model_t *model)
{
#if 0
INT32 i;
@ -882,7 +550,7 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
return;
}
// Check for any MD2s that match the names of player skins!
// Check for any MD2s that match the names of sprite names!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, skins[skin].name) == 0)
@ -1195,30 +863,21 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con
// : (monsters, bonuses, weapons, lights, ...)
// Returns :
// -----------------+
/*
wait/stand
death
pain
walk
shoot/fire
die?
atka?
atkb?
attacka/b/c/d?
res?
run?
*/
// hw_main.c
#define NORMALFOG 0x00000000
#define FADEFOG 0x19000000
void HWR_DrawMD2(gr_vissprite_t *spr)
{
FSurfaceInfo Surf;
md2_t *md2;
char filename[64];
INT32 frame;
INT32 frame = 0;
INT32 nextFrame = -1;
FTransform p;
md2_t *md2;
FSurfaceInfo Surf;
if (!cv_grmd2.value)
return;
@ -1263,10 +922,9 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
GLPatch_t *gpatch;
INT32 *buff;
INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics;
md2_frame_t *curr, *next = NULL;
//mdlframe_t *next = NULL;
const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP);
spritedef_t *sprdef;
spriteframe_t *sprframe;
@ -1307,6 +965,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (md2->model)
{
md2_printModelInfo(md2->model);
HWD.pfnCreateModelVBOs(md2->model);
}
else
{
@ -1355,30 +1014,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
}
//FIXME: this is not yet correct
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
buff = md2->model->glCommandBuffer;
curr = &md2->model->frames[frame];
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
#ifdef USE_MODEL_NEXTFRAME
if (cv_grmd2.value == 1 && tics <= durs)
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
if (spr->mobj->frame & FF_ANIMATE)
{
UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextframe >= (UINT32)spr->mobj->state->var1)
nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
nextframe %= md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= spr->mobj->state->var1)
nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK);
nextFrame %= md2->model->meshes[0].numFrames;
//next = &md2->model->meshes[0].frames[nextFrame];
}
else
{
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
{
const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
//next = &md2->model->meshes[0].frames[nextFrame];
}
}
}
#endif
//Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(spr->mobj->x);
@ -1398,7 +1057,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (sprframe->rotate)
{
const fixed_t anglef = AngleFixed(spr->mobj->angle);
fixed_t anglef = AngleFixed(spr->mobj->angle);
// \todo adapt for 2.2 directionchar? The below code is from Kart
#if 0
if (spr->mobj->player)
anglef = AngleFixed(spr->mobj->player->frameangle);
else
anglef = AngleFixed(spr->mobj->angle);
#endif
p.angley = FIXED_TO_FLOAT(anglef);
}
else
@ -1407,13 +1073,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef);
}
p.anglex = 0.0f;
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
{
fixed_t tempz = spr->mobj->standingslope->normal.z;
fixed_t tempy = spr->mobj->standingslope->normal.y;
fixed_t tempx = spr->mobj->standingslope->normal.x;
fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
p.anglez = FIXED_TO_FLOAT(tempangle);
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
p.anglex = FIXED_TO_FLOAT(tempangle);
}
#endif
// SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
p.flip = atransform.flip;
#ifdef USE_FTRANSFORM_MIRROR
p.mirror = atransform.mirror; // from Kart
#endif
HWD.pfnDrawMD2(buff, curr, durs, tics, next, &p, finalscale, flip, &Surf);
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf);
}
}

View file

@ -16,97 +16,7 @@
#define _HW_MD2_H_
#include "hw_glob.h"
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
#define MD2_MAX_FRAMES 512
#define MD2_MAX_SKINS 32
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
UINT32 magic;
UINT32 version;
UINT32 skinWidth;
UINT32 skinHeight;
UINT32 frameSize;
UINT32 numSkins;
UINT32 numVertices;
UINT32 numTexCoords;
UINT32 numTriangles;
UINT32 numGlCommands;
UINT32 numFrames;
UINT32 offsetSkins;
UINT32 offsetTexCoords;
UINT32 offsetTriangles;
UINT32 offsetFrames;
UINT32 offsetGlCommands;
UINT32 offsetEnd;
} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes
typedef struct
{
UINT8 vertex[3];
UINT8 lightNormalIndex;
} ATTRPACK md2_alias_triangleVertex_t;
typedef struct
{
float vertex[3];
float normal[3];
} ATTRPACK md2_triangleVertex_t;
typedef struct
{
INT16 vertexIndices[3];
INT16 textureIndices[3];
} ATTRPACK md2_triangle_t;
typedef struct
{
INT16 s, t;
} ATTRPACK md2_textureCoordinate_t;
typedef struct
{
float scale[3];
float translate[3];
char name[16];
md2_alias_triangleVertex_t alias_vertices[1];
} ATTRPACK md2_alias_frame_t;
typedef struct
{
char name[16];
md2_triangleVertex_t *vertices;
} ATTRPACK md2_frame_t;
typedef char md2_skin_t[64];
typedef struct
{
float s, t;
INT32 vertexIndex;
} ATTRPACK md2_glCommandVertex_t;
typedef struct
{
md2_header_t header;
md2_skin_t *skins;
md2_textureCoordinate_t *texCoords;
md2_triangle_t *triangles;
md2_frame_t *frames;
INT32 *glCommandBuffer;
} ATTRPACK md2_model_t;
#include "hw_model.h"
#if defined(_MSC_VER)
#pragma pack()
@ -117,7 +27,7 @@ typedef struct
char filename[32];
float scale;
float offset;
md2_model_t *model;
model_t *model;
void *grpatch;
void *blendgrpatch;
boolean notfound;

564
src/hardware/hw_md2load.c Normal file
View file

@ -0,0 +1,564 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md2load.h"
#include "hw_model.h"
#include "../z_zone.h"
#define NUMVERTEXNORMALS 162
// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and
// you'll have your normals.
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
typedef struct
{
int ident; // A "magic number" that's used to identify the .md2 file
int version; // The version of the file, always 8
int skinwidth; // Width of the skin(s) in pixels
int skinheight; // Height of the skin(s) in pixels
int framesize; // Size of each frame in bytes
int numSkins; // Number of skins with the model
int numXYZ; // Number of vertices in each frame
int numST; // Number of texture coordinates in each frame.
int numTris; // Number of triangles in each frame
int numGLcmds; // Number of dwords (4 bytes) in the gl command list.
int numFrames; // Number of frames
int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates
int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles
int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames
int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md2header_t;
typedef struct
{
unsigned short meshIndex[3]; // indices into the array of vertices in each frames
unsigned short stIndex[3]; // indices into the array of texture coordinates
} md2triangle_t;
typedef struct
{
short s;
short t;
} md2texcoord_t;
typedef struct
{
unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal.
unsigned char lightNormalIndex; // Index to the array of normals
} md2vertex_t;
typedef struct
{
float scale[3]; // Used by the v member in the md2framePoint structure
float translate[3]; // Used by the v member in the md2framePoint structure
char name[16]; // Name of the frame
} md2frame_t;
// Load the model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
FILE *f;
model_t *retModel = NULL;
md2header_t *header;
size_t fileLen;
int i, j;
size_t namelen;
char *texturefilename;
const char *texPos;
char *buffer;
const float WUNITS = 1.0f;
float dataScale = WUNITS;
md2triangle_t *tris;
md2texcoord_t *texcoords;
md2frame_t *frames;
int t;
// MD2 currently does not work with tinyframes, so force useFloat = true
//
// <SSNTails>
// the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float.
//
// MD2 is intended to be draw in triangle strips and fans
// not very compatible with a modern GL implementation, either
// so the idea would be to full float expand it, and put it in a vertex buffer object
// I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else.
// You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates
// I already have the decompression work done
useFloat = true;
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
//size_t fileLen;
//int i, j;
//size_t namelen;
//char *texturefilename;
texPos = strchr(fileName, '/');
if (texPos)
{
texPos++;
namelen = strlen(texPos) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, texPos);
}
else
{
namelen = strlen(fileName) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, fileName);
}
texturefilename[namelen - 2] = 'z';
texturefilename[namelen - 3] = 'u';
texturefilename[namelen - 4] = 'b';
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
fclose(f);
// get pointer to file header
header = (md2header_t*)buffer;
retModel->numMeshes = 1; // MD2 only has one mesh
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0);
retModel->meshes[0].numFrames = header->numFrames;
// const float WUNITS = 1.0f;
// float dataScale = WUNITS;
// Tris and ST are simple structures that can be straight-copied
tris = (md2triangle_t*)&buffer[header->offsetTris];
texcoords = (md2texcoord_t*)&buffer[header->offsetST];
frames = (md2frame_t*)&buffer[header->offsetFrames];
// Read in textures
retModel->numMaterials = header->numSkins;
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
// int t;
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.8f;
retModel->materials[t].ambient[1] = 0.8f;
retModel->materials[t].ambient[2] = 0.8f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8f;
retModel->materials[t].diffuse[1] = 0.8f;
retModel->materials[t].diffuse[2] = 0.8f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.0f;
retModel->materials[t].specular[1] = 0.0f;
retModel->materials[t].specular[2] = 0.0f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 0.0f;
retModel->materials[t].spheremap = false;
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, texturefilename);
size_t len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[0].numTriangles = header->numTris;
if (!useFloat) // Decompress to MD3 'tinyframe' space
{
char *ptr;
md2triangle_t *trisPtr;
unsigned short *indexptr;
float *uvptr;
dataScale = 0.015624f; // 1 / 64.0f
retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].numVertices = header->numXYZ;
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
short *vertptr;
char *normptr;
// char *tanptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0);
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0);
vertptr = retModel->meshes[0].tinyframes[i].vertices;
normptr = retModel->meshes[0].tinyframes[i].normals;
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numXYZ; j++, vertex++)
{
*vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale);
vertptr++;
*vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale);
vertptr++;
*vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale);
vertptr++;
// Normal
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127);
}
}
// This doesn't need to be done every frame!
trisPtr = tris;
indexptr = retModel->meshes[0].indices;
uvptr = (float*)retModel->meshes[0].uvs;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*indexptr = trisPtr->meshIndex[0];
indexptr++;
*indexptr = trisPtr->meshIndex[1];
indexptr++;
*indexptr = trisPtr->meshIndex[2];
indexptr++;
uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
}
else // Full float loading method
{
md2triangle_t *trisPtr;
float *uvptr;
char *ptr;
retModel->meshes[0].numVertices = header->numTris * 3;
retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
trisPtr = tris;
uvptr = retModel->meshes[0].uvs;
for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++)
{
*uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
float *vertptr, *normptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
//float *vertptr, *normptr;
normptr = (float*)retModel->meshes[0].frames[i].normals;
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
trisPtr = tris;
retModel->meshes[0].frames[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1];
}
}
}
free(buffer);
return retModel;
}

20
src/hardware/hw_md2load.h Normal file
View file

@ -0,0 +1,20 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD2LOAD_H_
#define _HW_MD2LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

510
src/hardware/hw_md3load.c Normal file
View file

@ -0,0 +1,510 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md3load.h"
#include "hw_model.h"
#include "../z_zone.h"
typedef struct
{
int ident; // A "magic number" that's used to identify the .md3 file
int version; // The version of the file, always 15
char name[64];
int flags;
int numFrames; // Number of frames
int numTags;
int numSurfaces;
int numSkins; // Number of skins with the model
int offsetFrames;
int offsetTags;
int offsetSurfaces;
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md3modelHeader;
typedef struct
{
float minBounds[3]; // First corner of the bounding box
float maxBounds[3]; // Second corner of the bounding box
float localOrigin[3]; // Local origin, usually (0, 0, 0)
float radius; // Radius of bounding sphere
char name[16]; // Name of frame
} md3Frame;
typedef struct
{
char name[64]; // Name of tag
float origin[3]; // Coordinates of tag
float axis[9]; // Orientation of tag object
} md3Tag;
typedef struct
{
int ident;
char name[64]; // Name of this surface
int flags;
int numFrames; // # of keyframes
int numShaders; // # of shaders
int numVerts; // # of vertices
int numTriangles; // # of triangles
int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start
int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start
int offsetST; // Relative offset from start of this struct to where the list of tex coords start
int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start
int offsetEnd; // Relative offset from start of this struct to where this surface ends
} md3Surface;
typedef struct
{
char name[64]; // Name of this shader
int shaderIndex; // Shader index number
} md3Shader;
typedef struct
{
int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object.
} md3Triangle;
typedef struct
{
float st[2];
} md3TexCoord;
typedef struct
{
short x, y, z, n;
} md3Vertex;
static float latlnglookup[256][256][3];
static void GetNormalFromLatLong(short latlng, float *out)
{
float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)];
out[0] = *lookup++;
out[1] = *lookup++;
out[2] = *lookup++;
}
#if 0
static void NormalToLatLng(float *n, short *out)
{
// Special cases
if (0.0f == n[0] && 0.0f == n[1])
{
if (n[2] > 0.0f)
*out = 0;
else
*out = 128;
}
else
{
char x, y;
x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f));
y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f));
*out = (x << 8) + y;
}
}
#endif
static inline void LatLngToNormal(short n, float *out)
{
const float PI = (3.1415926535897932384626433832795f);
float lat = (float)(n >> 8);
float lng = (float)(n & 255);
lat *= PI / 128.0f;
lng *= PI / 128.0f;
out[0] = cosf(lat) * sinf(lng);
out[1] = sinf(lat) * sinf(lng);
out[2] = cosf(lng);
}
static void LatLngInit(void)
{
int i, j;
for (i = 0; i < 256; i++)
{
for (j = 0; j < 256; j++)
LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]);
}
}
static boolean latlnginit = false;
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
const float WUNITS = 1.0f;
model_t *retModel = NULL;
md3modelHeader *mdh;
long fileLen;
long fileReadLen;
char *buffer;
int surfEnd;
int i, t;
int matCount;
FILE *f;
if (!latlnginit)
{
LatLngInit();
latlnginit = true;
}
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
fileReadLen = fread(buffer, fileLen, 1, f);
fclose(f);
(void)fileReadLen; // intentionally ignore return value, per buildbot
// get pointer to file header
mdh = (md3modelHeader*)buffer;
retModel->numMeshes = mdh->numSurfaces;
retModel->numMaterials = 0;
surfEnd = 0;
for (i = 0; i < mdh->numSurfaces; i++)
{
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces];
surfEnd += mdS->offsetEnd;
retModel->numMaterials += mdS->numShaders;
}
// Initialize materials
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.3686f;
retModel->materials[t].ambient[1] = 0.3684f;
retModel->materials[t].ambient[2] = 0.3684f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8863f;
retModel->materials[t].diffuse[1] = 0.8850f;
retModel->materials[t].diffuse[2] = 0.8850f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.4902f;
retModel->materials[t].specular[1] = 0.4887f;
retModel->materials[t].specular[2] = 0.4887f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 25.0f;
retModel->materials[t].spheremap = false;
}
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
matCount = 0;
for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
{
int j;
md3Shader *mdShader;
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd];
surfEnd += mdS->offsetEnd;
mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders);
for (j = 0; j < mdS->numShaders; j++, matCount++)
{
size_t len = strlen(mdShader[j].name);
mdShader[j].name[len-1] = 'z';
mdShader[j].name[len-2] = 'u';
mdShader[j].name[len-3] = 'b';
// Load material
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, mdShader[j].name);
len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[i].numFrames = mdS->numFrames;
retModel->meshes[i].numTriangles = mdS->numTriangles;
if (!useFloat) // 'tinyframe' mode with indices
{
float tempNormal[3];
float *uvptr;
md3TexCoord *mdST;
unsigned short *indexptr;
md3Triangle *mdT;
retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].numVertices = mdS->numVerts;
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
short *vertptr;
char *normptr;
// char *tanptr;
int k;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0);
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0);
vertptr = retModel->meshes[i].tinyframes[j].vertices;
normptr = retModel->meshes[i].tinyframes[j].normals;
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
for (k = 0; k < mdS->numVerts; k++)
{
// Vertex
*vertptr = mdV[k].x;
vertptr++;
*vertptr = mdV[k].z;
vertptr++;
*vertptr = 1.0f - mdV[k].y;
vertptr++;
// Normal
GetNormalFromLatLong(mdV[k].n, tempNormal);
*normptr = (char)(tempNormal[0] * 127);
normptr++;
*normptr = (char)(tempNormal[2] * 127);
normptr++;
*normptr = (char)(tempNormal[1] * 127);
normptr++;
}
}
uvptr = (float*)retModel->meshes[i].uvs;
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
for (j = 0; j < mdS->numVerts; j++)
{
*uvptr = mdST[j].st[0];
uvptr++;
*uvptr = mdST[j].st[1];
uvptr++;
}
indexptr = retModel->meshes[i].indices;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (j = 0; j < mdS->numTriangles; j++, mdT++)
{
// Indices
*indexptr = (unsigned short)mdT->index[0];
indexptr++;
*indexptr = (unsigned short)mdT->index[1];
indexptr++;
*indexptr = (unsigned short)mdT->index[2];
indexptr++;
}
}
else // Traditional full-float loading method
{
float dataScale = 0.015624f * WUNITS;
float tempNormal[3];
md3TexCoord *mdST;
md3Triangle *mdT;
float *uvptr;
int k;
retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts;
retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
float *vertptr;
float *normptr;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
// if (retModel->materials[i].lightmap)
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
vertptr = retModel->meshes[i].frames[j].vertices;
normptr = retModel->meshes[i].frames[j].normals;
retModel->meshes[i].frames[j].material = &retModel->materials[i];
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
// Vertex 1
*vertptr = mdV[mdT->index[0]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[0]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 2
*vertptr = mdV[mdT->index[1]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[1]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 3
*vertptr = mdV[mdT->index[2]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[2]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
mdT++; // Advance to next triangle
}
}
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
uvptr = (float*)retModel->meshes[i].uvs;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
*uvptr = mdST[mdT->index[0]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[0]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[1];
uvptr++;
mdT++; // Advance to next triangle
}
}
}
/*
// Tags?
retModel->numTags = mdh->numTags;
retModel->maxNumFrames = mdh->numFrames;
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
tag_t *curTag = retModel->tags;
for (i = 0; i < mdh->numFrames; i++)
{
int j;
for (j = 0; j < retModel->numTags; j++, mdTag++)
{
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
curTag->transform.m[0][0] = mdTag->axis[0];
curTag->transform.m[0][1] = mdTag->axis[1];
curTag->transform.m[0][2] = mdTag->axis[2];
curTag->transform.m[1][0] = mdTag->axis[3];
curTag->transform.m[1][1] = mdTag->axis[4];
curTag->transform.m[1][2] = mdTag->axis[5];
curTag->transform.m[2][0] = mdTag->axis[6];
curTag->transform.m[2][1] = mdTag->axis[7];
curTag->transform.m[2][2] = mdTag->axis[8];
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
curTag->transform.m[3][3] = 1.0f;
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
curTag++;
}
}*/
free(buffer);
return retModel;
}

19
src/hardware/hw_md3load.h Normal file
View file

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD3LOAD_H_
#define _HW_MD3LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

593
src/hardware/hw_model.c Normal file
View file

@ -0,0 +1,593 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "../z_zone.h"
#include "../doomdef.h"
#include "hw_model.h"
#include "hw_md2load.h"
#include "hw_md3load.h"
#include "u_list.h"
#include <string.h>
static float PI = (3.1415926535897932384626433832795f);
static float U_Deg2Rad(float deg)
{
return deg * ((float)PI / 180.0f);
}
vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f };
vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f };
vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f };
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle)
{
float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca;
angle = U_Deg2Rad(angle);
// Rotate the point (x,y,z) around the vector (u,v,w)
ux = axisVec->x * rotVec->x;
uy = axisVec->x * rotVec->y;
uz = axisVec->x * rotVec->z;
vx = axisVec->y * rotVec->x;
vy = axisVec->y * rotVec->y;
vz = axisVec->y * rotVec->z;
wx = axisVec->z * rotVec->x;
wy = axisVec->z * rotVec->y;
wz = axisVec->z * rotVec->z;
sa = sinf(angle);
ca = cosf(angle);
rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa;
rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa;
rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa;
}
void UnloadModel(model_t *model)
{
// Wouldn't it be great if C just had destructors?
int i;
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->frames[j].normals)
Z_Free(mesh->frames[j].normals);
if (mesh->frames[j].tangents)
Z_Free(mesh->frames[j].tangents);
if (mesh->frames[j].vertices)
Z_Free(mesh->frames[j].vertices);
if (mesh->frames[j].colors)
Z_Free(mesh->frames[j].colors);
}
Z_Free(mesh->frames);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->tinyframes[j].normals)
Z_Free(mesh->tinyframes[j].normals);
if (mesh->tinyframes[j].tangents)
Z_Free(mesh->tinyframes[j].tangents);
if (mesh->tinyframes[j].vertices)
Z_Free(mesh->tinyframes[j].vertices);
}
if (mesh->indices)
Z_Free(mesh->indices);
Z_Free(mesh->tinyframes);
}
if (mesh->uvs)
Z_Free(mesh->uvs);
if (mesh->lightuvs)
Z_Free(mesh->lightuvs);
}
if (model->meshes)
Z_Free(model->meshes);
if (model->tags)
Z_Free(model->tags);
if (model->materials)
Z_Free(model->materials);
DeleteVBOs(model);
Z_Free(model);
}
tag_t *GetTagByName(model_t *model, char *name, int frame)
{
if (frame < model->maxNumFrames)
{
tag_t *iterator = &model->tags[frame * model->numTags];
int i;
for (i = 0; i < model->numTags; i++)
{
if (!stricmp(iterator[i].name, name))
return &iterator[i];
}
}
return NULL;
}
//
// LoadModel
//
// Load a model and
// convert it to the
// internal format.
//
model_t *LoadModel(const char *filename, int ztag)
{
model_t *model;
// What type of file?
const char *extension = NULL;
int i;
for (i = (int)strlen(filename)-1; i >= 0; i--)
{
if (filename[i] != '.')
continue;
extension = &filename[i];
break;
}
if (!extension)
{
CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename);
return NULL;
}
if (!strcmp(extension, ".md3"))
{
if (!(model = MD3_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats
{
if (!(model = MD3_LoadModel(filename, ztag, true)))
return NULL;
}
else if (!strcmp(extension, ".md2"))
{
if (!(model = MD2_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md2s"))
{
if (!(model = MD2_LoadModel(filename, ztag, true)))
return NULL;
}
else
{
CONS_Printf("Unknown model format: %s\n", extension);
return NULL;
}
model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0);
strcpy(model->mdlFilename, filename);
Optimize(model);
GeneratePolygonNormals(model, ztag);
// Default material properties
for (i = 0 ; i < model->numMaterials; i++)
{
material_t *material = &model->materials[i];
material->ambient[0] = 0.7686f;
material->ambient[1] = 0.7686f;
material->ambient[2] = 0.7686f;
material->ambient[3] = 1.0f;
material->diffuse[0] = 0.5863f;
material->diffuse[1] = 0.5863f;
material->diffuse[2] = 0.5863f;
material->diffuse[3] = 1.0f;
material->specular[0] = 0.4902f;
material->specular[1] = 0.4902f;
material->specular[2] = 0.4902f;
material->specular[3] = 1.0f;
material->shininess = 25.0f;
}
return model;
}
//
// GenerateVertexNormals
//
// Creates a new normal for a vertex using the average of all of the polygons it belongs to.
//
void GenerateVertexNormals(model_t *model)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
int memTag = PU_STATIC;
float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0);
int k;
float *vertPtr = frame->vertices;
float *oldNormals;
M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3);
/* if (!systemSucks)
{
memTag = Z_GetTag(frame->tangents);
float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag);
M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3);
}*/
for (k = 0; k < mesh->numVertices; k++)
{
float x, y, z;
int vCount = 0;
vector_t normal;
int l;
float *testPtr = frame->vertices;
x = *vertPtr++;
y = *vertPtr++;
z = *vertPtr++;
normal.x = normal.y = normal.z = 0;
for (l = 0; l < mesh->numVertices; l++)
{
float testX, testY, testZ;
testX = *testPtr++;
testY = *testPtr++;
testZ = *testPtr++;
if (fabsf(x - testX) > FLT_EPSILON
|| fabsf(y - testY) > FLT_EPSILON
|| fabsf(z - testZ) > FLT_EPSILON)
continue;
// Found a vertex match! Add it...
normal.x += frame->normals[3 * l + 0];
normal.y += frame->normals[3 * l + 1];
normal.z += frame->normals[3 * l + 2];
vCount++;
}
if (vCount > 1)
{
// Vector::Normalize(&normal);
newNormals[3 * k + 0] = (float)normal.x;
newNormals[3 * k + 1] = (float)normal.y;
newNormals[3 * k + 2] = (float)normal.z;
/* if (!systemSucks)
{
Vector::vector_t tangent;
Vector::Tangent(&normal, &tangent);
newTangents[3 * k + 0] = tangent.x;
newTangents[3 * k + 1] = tangent.y;
newTangents[3 * k + 2] = tangent.z;
}*/
}
}
oldNormals = frame->normals;
frame->normals = newNormals;
Z_Free(oldNormals);
/* if (!systemSucks)
{
float *oldTangents = frame->tangents;
frame->tangents = newTangents;
Z_Free(oldTangents);
}*/
}
}
}
typedef struct materiallist_s
{
struct materiallist_s *next;
struct materiallist_s *prev;
material_t *material;
} materiallist_t;
static boolean AddMaterialToList(materiallist_t **head, material_t *material)
{
materiallist_t *node, *newMatNode;
for (node = *head; node; node = node->next)
{
if (node->material == material)
return false;
}
// Didn't find it, so add to the list
newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0);
newMatNode->material = material;
ListAdd(newMatNode, (listitem_t**)head);
return true;
}
//
// Optimize
//
// Groups triangles from meshes in the model
// Only works for models with 1 frame
//
void Optimize(model_t *model)
{
int numMeshes = 0;
int i;
materiallist_t *matListHead = NULL;
int memTag;
mesh_t *newMeshes;
materiallist_t *node;
if (model->numMeshes <= 1)
return; // No need
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *curMesh = &model->meshes[i];
if (curMesh->numFrames > 1)
return; // Can't optimize models with > 1 frame
if (!curMesh->frames)
return; // Don't optimize tinyframe models (no need)
// We are condensing to 1 mesh per material, so
// the # of materials we use will be the new
// # of meshes
if (AddMaterialToList(&matListHead, curMesh->frames[0].material))
numMeshes++;
}
memTag = PU_STATIC;
newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0);
i = 0;
for (node = matListHead; node; node = node->next)
{
material_t *curMat = node->material;
mesh_t *newMesh = &newMeshes[i];
mdlframe_t *curFrame;
int uvCount;
int vertCount;
int colorCount;
// Find all triangles with this material and count them
int numTriangles = 0;
int j;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
numTriangles += curMesh->numTriangles;
}
newMesh->numFrames = 1;
newMesh->numTriangles = numTriangles;
newMesh->numVertices = numTriangles * 3;
newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
// if (node->material->lightmap)
// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0);
curFrame = &newMesh->frames[0];
curFrame->material = curMat;
curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
// if (!systemSucks)
// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0);
// Now traverse the meshes of the model, adding in
// vertices/normals/uvs that match the current material
uvCount = 0;
vertCount = 0;
colorCount = 0;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
{
float *dest;
float *src;
char *destByte;
char *srcByte;
M_Memcpy(&newMesh->uvs[uvCount],
curMesh->uvs,
sizeof(float)*2*curMesh->numTriangles*3);
/* if (node->material->lightmap)
{
M_Memcpy(&newMesh->lightuvs[uvCount],
curMesh->lightuvs,
sizeof(float)*2*curMesh->numTriangles*3);
}*/
uvCount += 2*curMesh->numTriangles*3;
dest = (float*)newMesh->frames[0].vertices;
src = (float*)curMesh->frames[0].vertices;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
dest = (float*)newMesh->frames[0].normals;
src = (float*)curMesh->frames[0].normals;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
/* if (!systemSucks)
{
dest = (float*)newMesh->frames[0].tangents;
src = (float*)curMesh->frames[0].tangents;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
}*/
vertCount += 3 * curMesh->numTriangles * 3;
destByte = (char*)newMesh->frames[0].colors;
srcByte = (char*)curMesh->frames[0].colors;
if (srcByte)
{
M_Memcpy(&destByte[colorCount],
srcByte,
sizeof(char)*4*curMesh->numTriangles*3);
}
else
{
memset(&destByte[colorCount],
255,
sizeof(char)*4*curMesh->numTriangles*3);
}
colorCount += 4 * curMesh->numTriangles * 3;
}
}
i++;
}
CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes);
model->meshes = newMeshes;
model->numMeshes = numMeshes;
}
void GeneratePolygonNormals(model_t *model, int ztag)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
int k;
mdlframe_t *frame = &mesh->frames[j];
const float *vertices = frame->vertices;
vector_t *polyNormals;
frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0);
polyNormals = frame->polyNormals;
for (k = 0; k < mesh->numTriangles; k++)
{
// Vector::Normal(vertices, polyNormals);
vertices += 3 * 3;
polyNormals++;
}
}
}
}
//
// Reload
//
// Reload VBOs
//
#if 0
static void Reload(void)
{
/* model_t *node;
for (node = modelHead; node; node = node->next)
{
int i;
for (i = 0; i < node->numMeshes; i++)
{
mesh_t *mesh = &node->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->frames[j]);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->tinyframes[j]);
}
}
}*/
}
#endif
void DeleteVBOs(model_t *model)
{
(void)model;
/* for (int i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
for (int j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
else if (mesh->tinyframes)
{
for (int j = 0; j < mesh->numFrames; j++)
{
tinyframe_t *frame = &mesh->tinyframes[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
}*/
}

104
src/hardware/hw_model.h Normal file
View file

@ -0,0 +1,104 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MODEL_H_
#define _HW_MODEL_H_
#include "../doomtype.h"
typedef struct
{
float x, y, z;
} vector_t;
extern vector_t vectorXaxis;
extern vector_t vectorYaxis;
extern vector_t vectorZaxis;
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle);
typedef struct
{
float ambient[4], diffuse[4], specular[4], emissive[4];
float shininess;
boolean spheremap;
// Texture::texture_t *texture;
// Texture::texture_t *lightmap;
} material_t;
typedef struct
{
material_t *material; // Pointer to the allocated 'materials' list in model_t
float *vertices;
float *normals;
float *tangents;
char *colors;
unsigned int vboID;
vector_t *polyNormals;
} mdlframe_t;
typedef struct
{
material_t *material;
short *vertices;
char *normals;
char *tangents;
unsigned int vboID;
} tinyframe_t;
// Equivalent to MD3's many 'surfaces'
typedef struct mesh_s
{
int numVertices;
int numTriangles;
float *uvs;
float *lightuvs;
int numFrames;
mdlframe_t *frames;
tinyframe_t *tinyframes;
unsigned short *indices;
} mesh_t;
typedef struct tag_s
{
char name[64];
// matrix_t transform;
} tag_t;
typedef struct model_s
{
int maxNumFrames;
int numMaterials;
material_t *materials;
int numMeshes;
mesh_t *meshes;
int numTags;
tag_t *tags;
char *mdlFilename;
boolean unloaded;
} model_t;
extern int numModels;
extern model_t *modelHead;
tag_t *GetTagByName(model_t *model, char *name, int frame);
model_t *LoadModel(const char *filename, int ztag);
void UnloadModel(model_t *model);
void Optimize(model_t *model);
void GenerateVertexNormals(model_t *model);
void GeneratePolygonNormals(model_t *model, int ztag);
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
void DeleteVBOs(model_t *model);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _R_VBO_H_
#define _R_VBO_H_
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
} vbo32_t;
typedef struct
{
float x, y, z; // Vertex
float s0, t0; // Texcoord0
unsigned char r, g, b, a; // Color
float pad[2]; // Pad
} vbo2d32_t;
typedef struct
{
float x, y; // Vertex
float s0, t0; // Texcoord0
} vbofont_t;
typedef struct
{
short x, y, z; // Vertex
char nx, ny, nz; // Normal
char tanx, tany, tanz; // Tangent
float s0, t0; // Texcoord0
} vbotiny_t;
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
float s1, t1; // Texcoord1
float s2, t2; // Texcoord2
float tan0, tan1, tan2; // Tangent
unsigned char r, g, b, a; // Color
} vbo64_t;
#endif

231
src/hardware/u_list.c Normal file
View file

@ -0,0 +1,231 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "u_list.h"
#include "../z_zone.h"
// Utility for managing
// structures in a linked
// list.
//
// Struct must have "next" and "prev" pointers
// as its first two variables.
//
//
// ListAdd
//
// Adds an item to the list
//
void ListAdd(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
listitem_t *tail;
tail = *itemHead;
while (tail->next != NULL)
tail = tail->next;
tail->next = item;
tail->next->prev = tail;
item->next = NULL;
}
}
//
// ListAddFront
//
// Adds an item to the front of the list
// (This is much faster)
//
void ListAddFront(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
(*itemHead)->prev = item;
item->next = (*itemHead);
item->prev = NULL;
*itemHead = item;
}
}
//
// ListAddBefore
//
// Adds an item before the item specified in the list
//
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *prev = spot->prev;
if (!prev)
ListAddFront(pItem, itemHead);
else
{
item->next = spot;
spot->prev = item;
item->prev = prev;
prev->next = item;
}
}
//
// ListAddAfter
//
// Adds an item after the item specified in the list
//
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *next = spot->next;
if (!next)
ListAdd(pItem, itemHead);
else
{
item->prev = spot;
spot->next = item;
item->next = next;
next->prev = item;
}
}
//
// ListRemove
//
// Take an item out of the list and free its memory.
//
void ListRemove(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
Z_Free (item);
}
//
// ListRemoveAll
//
// Removes all items from the list, freeing their memory.
//
void ListRemoveAll(listitem_t **itemHead)
{
listitem_t *item;
listitem_t *next;
for (item = *itemHead; item; item = next)
{
next = item->next;
ListRemove(item, itemHead);
}
}
//
// ListRemoveNoFree
//
// Take an item out of the list, but don't free its memory.
//
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
}
//
// ListGetCount
//
// Counts the # of items in a list
// Should not be used in performance-minded code
//
unsigned int ListGetCount(void *itemHead)
{
listitem_t *item = (listitem_t*)itemHead;
unsigned int count = 0;
for (; item; item = item->next)
count++;
return count;
}
//
// ListGetByIndex
//
// Gets an item in the list by its index
// Should not be used in performance-minded code
//
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
{
listitem_t *head = (listitem_t*)itemHead;
unsigned int count = 0;
listitem_t *node;
for (node = head; node; node = node->next)
{
if (count == index)
return node;
count++;
}
return NULL;
}

29
src/hardware/u_list.h Normal file
View file

@ -0,0 +1,29 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _U_LIST_H_
#define _U_LIST_H_
typedef struct listitem_s
{
struct listitem_s *next;
struct listitem_s *prev;
} listitem_t;
void ListAdd(void *pItem, listitem_t **itemHead);
void ListAddFront(void *pItem, listitem_t **itemHead);
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead);
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead);
void ListRemove(void *pItem, listitem_t **itemHead);
void ListRemoveAll(listitem_t **itemHead);
void ListRemoveNoFree(void *pItem, listitem_t **itemHead);
unsigned int ListGetCount(void *itemHead);
listitem_t *ListGetByIndex(void *itemHead, unsigned int index);
#endif

View file

@ -411,6 +411,19 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
return false;
}
// ClosestPointOnVector
//
// Similar to ClosestPointOnLine, but uses a vector instead of two points.
//
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out)
{
fixed_t t = FV3_Dot(dir, p);
// Return the point on the line closest
FV3_MulEx(dir, t, out);
return;
}
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2)
{
return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z));
@ -519,7 +532,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect
//
// Calculates the normal of a polygon.
//
void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
fixed_t FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
{
vector3_t a_1;
vector3_t a_2;
@ -529,7 +542,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
FV3_Cross(&a_1, &a_2, a_normal);
FV3_NormalizeEx(a_normal, a_normal);
return FV3_NormalizeEx(a_normal, a_normal);
}
//
// Strength
//
// Measures the 'strength' of a vector in a particular direction.
//
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir)
{
vector3_t normal;
fixed_t dist = FV3_NormalizeEx(a_1, &normal);
fixed_t dot = FV3_Dot(&normal, dir);
FV3_ClosestPointOnVector(dir, a_1, &normal);
dist = FV3_Magnitude(&normal);
if (dot < 0) // Not facing same direction, so negate result.
dist = -dist;
return dist;
}
//

View file

@ -394,9 +394,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2);
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2);
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result);
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o);
void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir);
fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point);
boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance);
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector);

View file

@ -227,6 +227,10 @@
<ClInclude Include="..\hardware\hw_light.h" />
<ClInclude Include="..\hardware\hw_main.h" />
<ClInclude Include="..\hardware\hw_md2.h" />
<ClInclude Include="..\hardware\hw_md2load.h" />
<ClInclude Include="..\hardware\hw_md3load.h" />
<ClInclude Include="..\hardware\hw_model.h" />
<ClInclude Include="..\hardware\u_list.h" />
<ClInclude Include="..\hu_stuff.h" />
<ClInclude Include="..\info.h" />
<ClInclude Include="..\i_addrinfo.h" />
@ -365,8 +369,12 @@
<ClCompile Include="..\hardware\hw_light.c" />
<ClCompile Include="..\hardware\hw_main.c" />
<ClCompile Include="..\hardware\hw_md2.c" />
<ClCompile Include="..\hardware\hw_md2load.c" />
<ClCompile Include="..\hardware\hw_md3load.c" />
<ClCompile Include="..\hardware\hw_model.c" />
<ClCompile Include="..\hardware\hw_trick.c" />
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
<ClCompile Include="..\hardware\u_list.c" />
<ClCompile Include="..\hu_stuff.c" />
<ClCompile Include="..\info.c" />
<ClCompile Include="..\i_addrinfo.c">
@ -478,4 +486,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -246,6 +246,18 @@
<ClInclude Include="..\hardware\hw_md2.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md2load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md3load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_model.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\u_list.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\byteptr.h">
<Filter>I_Interface</Filter>
</ClInclude>
@ -623,10 +635,22 @@
</ClCompile>
<ClCompile Include="..\hardware\hw_md2.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md2load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md3load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_model.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_trick.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\u_list.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\filesrch.c">
<Filter>I_Interface</Filter>
</ClCompile>
@ -894,4 +918,4 @@
<Filter>SDLApp</Filter>
</Image>
</ItemGroup>
</Project>
</Project>

View file

@ -88,7 +88,8 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(ClearMipMapCache);
GETFUNC(SetSpecialState);
GETFUNC(GetTextureUsed);
GETFUNC(DrawMD2);
GETFUNC(DrawModel);
GETFUNC(CreateModelVBOs);
GETFUNC(SetTransform);
GETFUNC(GetRenderVersion);
GETFUNC(PostImgRedraw);

View file

@ -1485,7 +1485,8 @@ void I_StartupGraphics(void)
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL);
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL);
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);

View file

@ -222,15 +222,6 @@
<ClCompile Include="..\f_wipe.c" />
<ClCompile Include="..\g_game.c" />
<ClCompile Include="..\g_input.c" />
<ClCompile Include="..\hardware\hw3sound.c" />
<ClCompile Include="..\hardware\hw_bsp.c" />
<ClCompile Include="..\hardware\hw_cache.c" />
<ClCompile Include="..\hardware\hw_clip.c" />
<ClCompile Include="..\hardware\hw_draw.c" />
<ClCompile Include="..\hardware\hw_light.c" />
<ClCompile Include="..\hardware\hw_main.c" />
<ClCompile Include="..\hardware\hw_md2.c" />
<ClCompile Include="..\hardware\hw_trick.c" />
<ClCompile Include="..\hu_stuff.c" />
<ClCompile Include="..\info.c" />
<ClCompile Include="..\i_addrinfo.c">
@ -384,16 +375,6 @@
<ClInclude Include="..\hardware\hw3dsdrv.h" />
<ClInclude Include="..\hardware\hw3sound.h" />
<ClInclude Include="..\hardware\hws_data.h" />
<ClInclude Include="..\hardware\hw_clip.h" />
<ClInclude Include="..\hardware\hw_data.h" />
<ClInclude Include="..\hardware\hw_defs.h" />
<ClInclude Include="..\hardware\hw_dll.h" />
<ClInclude Include="..\hardware\hw_drv.h" />
<ClInclude Include="..\hardware\hw_glide.h" />
<ClInclude Include="..\hardware\hw_glob.h" />
<ClInclude Include="..\hardware\hw_light.h" />
<ClInclude Include="..\hardware\hw_main.h" />
<ClInclude Include="..\hardware\hw_md2.h" />
<ClInclude Include="..\hu_stuff.h" />
<ClInclude Include="..\info.h" />
<ClInclude Include="..\i_addrinfo.h" />
@ -494,4 +475,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -87,30 +87,6 @@
<ClCompile Include="win_vid.c">
<Filter>Win32app</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_bsp.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_cache.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_clip.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_draw.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_light.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_main.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md2.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_trick.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw3sound.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
@ -476,36 +452,6 @@
<ClInclude Include="win_main.h">
<Filter>Win32app</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_clip.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_data.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_defs.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_dll.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_drv.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_glide.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_glob.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_light.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_main.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md2.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw3dsdrv.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
@ -881,4 +827,4 @@
<Filter>A_Asm</Filter>
</CustomBuild>
</ItemGroup>
</Project>
</Project>