mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-01-02 15:51:12 +00:00
389 lines
9.3 KiB
C
389 lines
9.3 KiB
C
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// 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 General Public License for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file
|
|
/// \brief NDS 3D API for SRB2.
|
|
//
|
|
// In an ideal world, we would share as much code as possible with r_opengl.c,
|
|
// but this will do for now.
|
|
|
|
#include "../doomtype.h"
|
|
#include "../hardware/hw_defs.h"
|
|
#include "../hardware/hw_dll.h"
|
|
#include "../hardware/hw_md2.h"
|
|
#include "r_nds3d.h"
|
|
|
|
static I_Error_t I_Error_GL = NULL;
|
|
|
|
#define NOTEXTURE_NUM 0 // small white texture
|
|
#define FIRST_TEX_AVAIL (NOTEXTURE_NUM + 1)
|
|
#define MAX_SRB2_TEXTURES 256
|
|
|
|
FCOORD NEAR_CLIPPING_PLANE = 0.9f;
|
|
float fov = 90.0f;
|
|
|
|
static FBITFIELD CurrentPolyFlags = 0xFFFFFFFF;
|
|
static UINT32 CurrentGLPolyFmt = POLY_CULL_NONE;
|
|
static UINT8 CurrentPolyAlpha = 31;
|
|
static UINT16 myPaletteData[256];
|
|
static FTextureInfo* gr_cachetail = NULL;
|
|
static FTextureInfo* gr_cachehead = NULL;
|
|
static INT32 NextTexAvail = FIRST_TEX_AVAIL;
|
|
static UINT32 tex_downloaded = 0;
|
|
static INT32 texids[MAX_SRB2_TEXTURES];
|
|
static boolean scalehack = false;
|
|
|
|
|
|
static void GenerateTextureNames(void)
|
|
{
|
|
glGenTextures(MAX_SRB2_TEXTURES - 1, texids + 1);
|
|
texids[NOTEXTURE_NUM] = 0;
|
|
}
|
|
|
|
static void Flush(void)
|
|
{
|
|
// Delete all textures at once, since libnds's glDeleteTextures seems to be buggy.
|
|
glResetTextures();
|
|
GenerateTextureNames();
|
|
while (gr_cachehead)
|
|
{
|
|
gr_cachehead->downloaded = 0;
|
|
gr_cachehead = gr_cachehead->nextmipmap;
|
|
}
|
|
gr_cachetail = gr_cachehead = NULL;
|
|
NextTexAvail = FIRST_TEX_AVAIL;
|
|
tex_downloaded = 0;
|
|
}
|
|
|
|
static void SetNoTexture(void)
|
|
{
|
|
// Set small white texture.
|
|
if (tex_downloaded != NOTEXTURE_NUM)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, texids[NOTEXTURE_NUM]);
|
|
tex_downloaded = NOTEXTURE_NUM;
|
|
}
|
|
}
|
|
|
|
|
|
static void SetAlpha(UINT8 alpha)
|
|
{
|
|
CurrentPolyAlpha = alpha >> 3;
|
|
glPolyFmt(CurrentGLPolyFmt | POLY_ALPHA(CurrentPolyAlpha));
|
|
}
|
|
|
|
|
|
|
|
boolean NDS3D_Init(I_Error_t ErrorFunction)
|
|
{
|
|
I_Error_GL = ErrorFunction;
|
|
glPolyFmt(CurrentGLPolyFmt | POLY_ALPHA(CurrentPolyAlpha));
|
|
GenerateTextureNames();
|
|
return true;
|
|
}
|
|
|
|
void NDS3D_Shutdown(void) {}
|
|
|
|
void NDS3D_SetPalette(RGBA_t *ppal, RGBA_t *pgamma)
|
|
{
|
|
INT32 i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
UINT8 red = (UINT8)min((ppal[i].s.red*pgamma->s.red)/127, 255) >> 3;
|
|
UINT8 green = (UINT8)min((ppal[i].s.green*pgamma->s.green)/127, 255) >> 3;
|
|
UINT8 blue = (UINT8)min((ppal[i].s.blue*pgamma->s.blue)/127, 255) >> 3;
|
|
|
|
myPaletteData[i] = ARGB16(ppal[i].s.alpha ? 1 : 0, red, green, blue);
|
|
}
|
|
|
|
Flush();
|
|
}
|
|
|
|
void NDS3D_FinishUpdate(INT32 waitvbl)
|
|
{
|
|
(void)waitvbl;
|
|
|
|
glFlush(0);
|
|
}
|
|
|
|
void NDS3D_Draw2DLine(F2DCoord *v1, F2DCoord *v2, RGBA_t Color)
|
|
{
|
|
(void)v1;
|
|
(void)v2;
|
|
(void)Color;
|
|
}
|
|
|
|
void NDS3D_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags)
|
|
{
|
|
FUINT i;
|
|
|
|
NDS3D_SetBlend(PolyFlags);
|
|
|
|
// If Modulated, mix the surface colour to the texture
|
|
if ((CurrentPolyFlags & PF_Modulated) && pSurf)
|
|
{
|
|
glColor3b(pSurf->FlatColor.s.red, pSurf->FlatColor.s.green, pSurf->FlatColor.s.blue);
|
|
SetAlpha(pSurf->FlatColor.s.alpha);
|
|
}
|
|
|
|
// libnds doesn't have GL_TRIANGLE_FAN, so use GL_TRIANGLE_STRIP instead
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
for (i = 0; i < iNumPts; i++)
|
|
{
|
|
FUINT index = (i & 1) ? (i >> 1) : (iNumPts - 1 - (i >> 1));
|
|
FLOAT x, y, z;
|
|
|
|
if (scalehack)
|
|
{
|
|
x = pOutVerts[index].x/4096.0f;
|
|
y = pOutVerts[index].y/4096.0f;
|
|
z = pOutVerts[index].z/4096.0f;
|
|
}
|
|
else
|
|
{
|
|
x = pOutVerts[index].x;
|
|
y = pOutVerts[index].y;
|
|
z = pOutVerts[index].z;
|
|
}
|
|
|
|
glTexCoord2f(pOutVerts[index].sow, pOutVerts[index].tow);
|
|
glVertex3f(x,y,z);
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
void NDS3D_SetBlend(FBITFIELD PolyFlags)
|
|
{
|
|
FBITFIELD Xor = PolyFlags ^ CurrentPolyFlags;
|
|
|
|
if (Xor & (PF_NoTexture|PF_Modulated))
|
|
{
|
|
if (Xor&PF_Modulated)
|
|
{
|
|
if(!(PolyFlags & PF_Modulated))
|
|
{
|
|
glColor3b(255, 255, 255);
|
|
CurrentPolyAlpha = 31;
|
|
}
|
|
}
|
|
|
|
if (PolyFlags & PF_NoTexture)
|
|
{
|
|
SetNoTexture();
|
|
}
|
|
}
|
|
|
|
CurrentPolyFlags = PolyFlags;
|
|
glPolyFmt(CurrentGLPolyFmt | POLY_ALPHA(CurrentPolyAlpha));
|
|
}
|
|
|
|
void NDS3D_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor)
|
|
{
|
|
(void)ClearColor;
|
|
|
|
if (ColorMask && ClearColor)
|
|
{
|
|
// TODO: Fixed-ify
|
|
glClearColor((uint8)(ClearColor->red*31),
|
|
(uint8)(ClearColor->green*31),
|
|
(uint8)(ClearColor->blue*31),
|
|
(uint8)(ClearColor->alpha*31));
|
|
}
|
|
|
|
if (DepthMask)
|
|
glClearDepth(GL_MAX_DEPTH);
|
|
|
|
NDS3D_SetBlend(DepthMask ? PF_Occlude | CurrentPolyFlags : CurrentPolyFlags&~PF_Occlude);
|
|
}
|
|
|
|
void NDS3D_SetTexture(FTextureInfo *TexInfo)
|
|
{
|
|
if (!TexInfo)
|
|
{
|
|
SetNoTexture();
|
|
return;
|
|
}
|
|
else if (TexInfo->downloaded)
|
|
{
|
|
if (TexInfo->downloaded != tex_downloaded)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, texids[TexInfo->downloaded]);
|
|
tex_downloaded = TexInfo->downloaded;
|
|
}
|
|
}
|
|
else if (TexInfo->grInfo.data)
|
|
{
|
|
UINT8 wtype, htype;
|
|
INT32 texparam = GL_TEXTURE_COLOR0_TRANSPARENT;
|
|
|
|
// We rely on the numerical values of GL_TEXTURE_SIZE_ENUM here.
|
|
wtype = TEXTURE_SIZE_8;
|
|
while(TexInfo->width > 1 << (wtype + 3)) wtype++;
|
|
|
|
htype = TEXTURE_SIZE_8;
|
|
while(TexInfo->height > 1 << (htype + 3)) htype++;
|
|
|
|
TexInfo->downloaded = NextTexAvail++;
|
|
tex_downloaded = TexInfo->downloaded;
|
|
glBindTexture(GL_TEXTURE_2D, texids[TexInfo->downloaded]);
|
|
|
|
if(!glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB256, wtype, htype, 0, TEXGEN_TEXCOORD, TexInfo->grInfo.data))
|
|
{
|
|
// HACK: If we're out of memory, flush and try again.
|
|
// This will result in artefacts for one frame.
|
|
Flush();
|
|
TexInfo->downloaded = 0;
|
|
NDS3D_SetTexture(TexInfo);
|
|
return;
|
|
}
|
|
|
|
if (TexInfo->downloaded > FIRST_TEX_AVAIL)
|
|
{
|
|
// We already have a texture using the palette, so it's already in VRAM
|
|
glAssignColorTable(GL_TEXTURE_2D, texids[FIRST_TEX_AVAIL]);
|
|
}
|
|
else
|
|
{
|
|
// Generate the palette in hardware
|
|
glColorTableEXT(0, 0, 256, 0, 0, myPaletteData);
|
|
}
|
|
|
|
if (TexInfo->flags & TF_WRAPX)
|
|
texparam |= GL_TEXTURE_WRAP_S;
|
|
|
|
if (TexInfo->flags & TF_WRAPY)
|
|
texparam |= GL_TEXTURE_WRAP_T;
|
|
|
|
glTexParameter(0, texparam);
|
|
|
|
TexInfo->nextmipmap = NULL;
|
|
if (gr_cachetail)
|
|
{
|
|
gr_cachetail->nextmipmap = TexInfo;
|
|
gr_cachetail = TexInfo;
|
|
}
|
|
else
|
|
gr_cachetail = gr_cachehead = TexInfo;
|
|
}
|
|
}
|
|
|
|
void NDS3D_ReadRect(INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data)
|
|
{
|
|
(void)x;
|
|
(void)y;
|
|
(void)width;
|
|
(void)height;
|
|
(void)dst_stride;
|
|
(void)dst_data;
|
|
}
|
|
|
|
void NDS3D_GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip)
|
|
{
|
|
(void)minx;
|
|
(void)miny;
|
|
(void)maxx;
|
|
(void)maxy;
|
|
//glViewport(minx, vid.height-maxy, maxx-minx, maxy-miny);
|
|
NEAR_CLIPPING_PLANE = nearclip;
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(fov, ASPECT_RATIO, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
void NDS3D_ClearMipMapCache(void) {}
|
|
|
|
void NDS3D_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
|
|
{
|
|
(void)IdState;
|
|
(void)Value;
|
|
}
|
|
|
|
void NDS3D_DrawMD2(INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale)
|
|
{
|
|
(void)gl_cmd_buffer;
|
|
(void)frame;
|
|
(void)pos;
|
|
(void)scale;
|
|
}
|
|
|
|
void NDS3D_DrawMD2i(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
|
|
{
|
|
(void)gl_cmd_buffer;
|
|
(void)frame;
|
|
(void)duration;
|
|
(void)tics;
|
|
(void)nextframe;
|
|
(void)pos;
|
|
(void)scale;
|
|
(void)flipped;
|
|
(void)color;
|
|
}
|
|
|
|
void NDS3D_SetTransform(FTransform *ptransform)
|
|
{
|
|
static INT32 special_splitscreen;
|
|
glLoadIdentity();
|
|
if (ptransform)
|
|
{
|
|
scalehack = true;
|
|
|
|
glScalef(ptransform->scalex*4096.0f, ptransform->scaley*4096.0f, -ptransform->scalez*4096.0f);
|
|
glRotatef(ptransform->anglex , 1.0f, 0.0f, 0.0f);
|
|
glRotatef(ptransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
|
|
glTranslatef(-ptransform->x/4096.0f, -ptransform->z/4096.0f, -ptransform->y/4096.0f);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
special_splitscreen = (ptransform->splitscreen && ptransform->fovxangle == 90.0f);
|
|
if (special_splitscreen)
|
|
gluPerspective(53.13l, 2*ASPECT_RATIO, // 53.13 = 2*atan(0.5)
|
|
NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);
|
|
else
|
|
gluPerspective(ptransform->fovxangle, ASPECT_RATIO, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
else
|
|
{
|
|
scalehack = false;
|
|
|
|
glScalef(1.0f, 1.0f, -1.0f);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
if (special_splitscreen)
|
|
gluPerspective(53.13l, 2*ASPECT_RATIO, // 53.13 = 2*atan(0.5)
|
|
NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);
|
|
else
|
|
//Hurdler: is "fov" correct?
|
|
gluPerspective(fov, ASPECT_RATIO, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
INT32 NDS3D_GetTextureUsed(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
INT32 NDS3D_GetRenderVersion(void)
|
|
{
|
|
return 0;
|
|
}
|