Add minimal renderergl2 implementation
Some checks failed
CodeQL / Analyze (push) Waiting to run
Build branch / build-all (push) Failing after 17s

This implementation should just let the game run without crashing, the renderer doesn't show anything yet
This commit is contained in:
smallmodel 2024-12-19 23:18:21 +01:00
parent fe16f999d8
commit 3d950764a2
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512
45 changed files with 12269 additions and 3355 deletions

View file

@ -10,6 +10,8 @@ set(SOURCES_RENDERER_COMMON ${SOURCES_RENDERER_COMMON}
add_library(omohrenderer_common STATIC ${SOURCES_RENDERER_COMMON})
target_include_directories(omohrenderer_common PUBLIC "../sdl" "./")
target_compile_features(omohrenderer_common PUBLIC cxx_nullptr)
target_compile_features(omohrenderer_common PUBLIC c_variadic_macros)
target_link_libraries(omohrenderer_common PUBLIC qcommon_shared)
target_link_libraries(omohrenderer_common PUBLIC omohsdl_gl)
target_compile_definitions(omohrenderer_common PRIVATE USE_INTERNAL_JPEG=1)

View file

@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
#define MAX_REAL_LIGHTS 32
#define REFENTITYNUM_BITS 10 // can't be increased without changing drawsurf bit packing
#define REFENTITYNUM_BITS 12 // can't be increased without changing drawsurf bit packing
#define REFENTITYNUM_MASK ((1<<REFENTITYNUM_BITS) - 1)
// the last N-bit number (2^REFENTITYNUM_BITS - 1) is reserved for the special world refentity,
// and this is reflected by the value of MAX_REFENTITIES (which therefore is not a power-of-2)

View file

@ -2,7 +2,10 @@ cmake_minimum_required(VERSION 3.12)
project(omohrenderergl2)
file(GLOB SOURCES_RENDERER "./*.c" "./*.cpp" "../renderercommon/tr_*.c")
file(GLOB SOURCES_RENDERER "*.c" "*.cpp" "../renderercommon/tr_*.c")
# Remove Quake III old model source
list(REMOVE_ITEM SOURCES_RENDERER "${CMAKE_CURRENT_SOURCE_DIR}/tr_model.c")
include("glsl/shaders.cmake")
if (${USE_RENDERER_DLOPEN})

View file

@ -1,34 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
int RE_MapVersion(void)
{
// FIXME: unimplemented
return 0;
}
void RE_PrintBSPFileSizes(void)
{
// FIXME: unimplemented
}

View file

@ -1,38 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
static backEndCounters_t pc_save;
/*
=====================
R_PerformanceCounters
=====================
*/
void R_SavePerformanceCounters(void) {
memcpy(&pc_save, &backEnd.pc, sizeof(pc_save));
}
void R_SyncRenderThread() {
R_IssuePendingRenderCommands();
}

View file

@ -1,23 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"

View file

@ -1,175 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
cvar_t* r_reset_tc_array;
cvar_t* r_numdebuglines;
cvar_t* r_staticlod;
cvar_t* r_lodscale;
cvar_t* r_lodcap;
cvar_t* r_lodviewmodelcap;
cvar_t* r_uselod;
cvar_t* lod_LOD;
cvar_t* lod_minLOD;
cvar_t* lod_maxLOD;
cvar_t* lod_LOD_slider;
cvar_t* lod_curve_0_val;
cvar_t* lod_curve_1_val;
cvar_t* lod_curve_2_val;
cvar_t* lod_curve_3_val;
cvar_t* lod_curve_4_val;
cvar_t* lod_edit_0;
cvar_t* lod_edit_1;
cvar_t* lod_edit_2;
cvar_t* lod_edit_3;
cvar_t* lod_edit_4;
cvar_t* lod_curve_0_slider;
cvar_t* lod_curve_1_slider;
cvar_t* lod_curve_2_slider;
cvar_t* lod_curve_3_slider;
cvar_t* lod_curve_4_slider;
cvar_t* lod_pitch_val;
cvar_t* lod_zee_val;
cvar_t* lod_mesh;
cvar_t* lod_meshname;
cvar_t* lod_tikiname;
cvar_t* lod_metric;
cvar_t* lod_tris;
cvar_t* lod_position;
cvar_t* lod_save;
cvar_t* lod_tool;
cvar_t* r_showSkeleton;
int r_sequencenumber;
//=============================================================================
/*
** RE_BeginRegistration
*/
void RE_BeginRegistration(glconfig_t* glconfigOut) {
int i;
R_Init();
*glconfigOut = glConfig;
R_IssuePendingRenderCommands();
tr.visIndex = 0;
// force markleafs to regenerate
for (i = 0; i < MAX_VISCOUNTS; i++) {
tr.visClusters[i] = -2;
}
R_ClearFlares();
RE_ClearScene();
tr.registered = qtrue;
}
const char* RE_GetGraphicsInfo() {
// FIXME: unimplemented
return NULL;
}
qboolean R_SetMode(int mode, const glconfig_t* glConfig) {
// FIXME: unimplemented
return qfalse;
}
void R_SetFullscreen(qboolean fullscreen) {
// FIXME: unimplemented
}
void RE_SetRenderTime(int t) {
// FIXME: unimplemented
}
void GetRefAPI_new(refimport_t* ri, refexport_t* re)
{
re->FreeModels = RE_FreeModels;
re->SpawnEffectModel = RE_SpawnEffectModel;
re->RegisterServerModel = RE_RegisterServerModel;
re->UnregisterServerModel = RE_UnregisterServerModel;
re->RefreshShaderNoMip = RE_RefreshShaderNoMip;
re->PrintBSPFileSizes = RE_PrintBSPFileSizes;
re->MapVersion = RE_MapVersion;
re->LoadFont = R_LoadFont;
re->BeginFrame = RE_BeginFrame;
re->MarkFragments = R_MarkFragments_New;
re->MarkFragmentsForInlineModel = R_MarkFragmentsForInlineModel;
re->GetInlineModelBounds = R_GetInlineModelBounds;
re->GetLightingForDecal = R_GetLightingForDecal;
re->GetLightingForSmoke = R_GetLightingForSmoke;
re->R_GatherLightSources = R_GatherLightSources;
re->ModelBounds = R_ModelBounds;
re->ModelRadius = R_ModelRadius;
re->AddRefEntityToScene = RE_AddRefEntityToScene;
re->AddRefSpriteToScene = RE_AddRefSpriteToScene;
re->AddPolyToScene = RE_AddPolyToScene;
re->AddTerrainMarkToScene = RE_AddTerrainMarkToScene;
re->AddLightToScene = RE_AddLightToScene;
re->RenderScene = RE_RenderScene;
re->GetRenderEntity = RE_GetRenderEntity;
re->SavePerformanceCounters = R_SavePerformanceCounters;
re->R_Model_GetHandle = R_Model_GetHandle;
re->DrawStretchRaw = RE_StretchRaw;
re->DebugLine = R_DebugLine;
re->DrawStretchPic = Draw_StretchPic;
re->DrawTilePic = Draw_TilePic;
re->DrawTilePicOffset = Draw_TilePicOffset;
re->DrawTrianglePic = Draw_TrianglePic;
re->DrawBox = DrawBox;
re->AddBox = AddBox;
re->Set2DWindow = Set2DWindow;
re->Scissor = RE_Scissor;
re->DrawLineLoop = DrawLineLoop;
re->DrawString = R_DrawString;
re->GetFontHeight = R_GetFontHeight;
re->GetFontStringWidth = R_GetFontStringWidth;
re->SwipeBegin = RE_SwipeBegin;
re->SwipeEnd = RE_SwipeEnd;
re->SetRenderTime = RE_SetRenderTime;
re->Noise = R_NoiseGet4f;
re->SetMode = R_SetMode;
re->SetFullscreen = R_SetFullscreen;
re->GetShaderHeight = RE_GetShaderHeight;
re->GetShaderWidth = RE_GetShaderWidth;
re->GetGraphicsInfo = RE_GetGraphicsInfo;
re->ForceUpdatePose = RE_ForceUpdatePose;
re->TIKI_Orientation = RE_TIKI_Orientation;
re->TIKI_IsOnGround = RE_TIKI_IsOnGround;
re->SetFrameNumber = RE_SetFrameNumber;
}

View file

@ -1,33 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
void R_GetLightingForDecal(vec3_t vLight, vec3_t vFacing, vec3_t vOrigin)
{
// FIXME: unimplemented
}
void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin)
{
// FIXME: unimplemented
}

View file

@ -1,465 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#pragma once
extern int r_sequencenumber;
void GetRefAPI_new(refimport_t* ri, refexport_t* re);
extern cvar_t* r_reset_tc_array;
extern cvar_t* r_numdebuglines;
extern cvar_t* r_staticlod;
extern cvar_t* r_lodscale;
extern cvar_t* r_lodcap;
extern cvar_t* r_lodviewmodelcap;
extern cvar_t* r_uselod;
extern cvar_t* lod_LOD;
extern cvar_t* lod_minLOD;
extern cvar_t* lod_maxLOD;
extern cvar_t* lod_LOD_slider;
extern cvar_t* lod_curve_0_val;
extern cvar_t* lod_curve_1_val;
extern cvar_t* lod_curve_2_val;
extern cvar_t* lod_curve_3_val;
extern cvar_t* lod_curve_4_val;
extern cvar_t* lod_edit_0;
extern cvar_t* lod_edit_1;
extern cvar_t* lod_edit_2;
extern cvar_t* lod_edit_3;
extern cvar_t* lod_edit_4;
extern cvar_t* lod_curve_0_slider;
extern cvar_t* lod_curve_1_slider;
extern cvar_t* lod_curve_2_slider;
extern cvar_t* lod_curve_3_slider;
extern cvar_t* lod_curve_4_slider;
extern cvar_t* lod_pitch_val;
extern cvar_t* lod_zee_val;
extern cvar_t* lod_mesh;
extern cvar_t* lod_meshname;
extern cvar_t* lod_tikiname;
extern cvar_t* lod_metric;
extern cvar_t* lod_tris;
extern cvar_t* lod_position;
extern cvar_t* lod_save;
extern cvar_t* lod_tool;
extern cvar_t* r_showSkeleton;
typedef union varnodeUnpacked_u {
float fVariance;
struct {
byte flags;
unsigned char unused[3];
} s;
} varnodeUnpacked_t;
typedef unsigned short terraInt;
typedef struct terrainVert_s {
vec3_t xyz;
vec2_t texCoords[2];
float fVariance;
float fHgtAvg;
float fHgtAdd;
unsigned int uiDistRecalc;
terraInt nRef;
terraInt iVertArray;
byte* pHgt;
terraInt iNext;
terraInt iPrev;
} terrainVert_t;
typedef struct terraTri_s {
unsigned short iPt[3];
terraInt nSplit;
unsigned int uiDistRecalc;
struct cTerraPatchUnpacked_s* patch;
varnodeUnpacked_t* varnode;
terraInt index;
byte lod;
byte byConstChecks;
terraInt iLeft;
terraInt iRight;
terraInt iBase;
terraInt iLeftChild;
terraInt iRightChild;
terraInt iParent;
terraInt iPrev;
terraInt iNext;
} terraTri_t;
typedef struct srfTerrain_s {
surfaceType_t surfaceType;
terraInt iVertHead;
terraInt iTriHead;
terraInt iTriTail;
terraInt iMergeHead;
int nVerts;
int nTris;
int lmapSize;
int dlightBits[2];
float lmapStep;
int dlightMap[2];
byte* lmData;
float lmapX;
float lmapY;
} srfTerrain_t;
typedef struct cTerraPatchUnpacked_s {
srfTerrain_t drawinfo;
int viewCount;
int visCountCheck;
int visCountDraw;
int frameCount;
unsigned int uiDistRecalc;
float s;
float t;
vec2_t texCoord[2][2];
float x0;
float y0;
float z0;
float zmax;
shader_t* shader;
short int iNorth;
short int iEast;
short int iSouth;
short int iWest;
struct cTerraPatchUnpacked_s* pNextActive;
varnodeUnpacked_t varTree[2][63];
unsigned char heightmap[81];
byte flags;
byte byDirty;
} cTerraPatchUnpacked_t;
typedef struct srfStaticModel_s {
surfaceType_t surfaceType;
struct cStaticModelUnpacked_s* parent;
} srfStaticModel_t;
typedef struct cStaticModelUnpacked_s {
qboolean useSpecialLighting;
qboolean bLightGridCalculated;
qboolean bRendered;
char model[128];
vec3_t origin;
vec3_t angles;
vec3_t axis[3];
float scale;
int firstVertexData;
int numVertexData;
int visCount;
dtiki_t* tiki;
sphere_dlight_t dlights[32];
int numdlights;
float radius;
float cull_radius;
int iGridLighting;
float lodpercentage[2];
} cStaticModelUnpacked_t;
typedef struct refSprite_s {
surfaceType_t surftype;
int hModel;
int shaderNum;
float origin[3];
float scale;
float axis[3][3];
unsigned char shaderRGBA[4];
int renderfx;
float shaderTime;
} refSprite_t;
//
// tr_shader.c
//
qhandle_t RE_RefreshShaderNoMip(const char* name);
//
// tr_bsp.c
//
void RE_PrintBSPFileSizes(void);
int RE_MapVersion(void);
typedef struct skelSurfaceGame_s skelSurfaceGame_t;
typedef struct staticSurface_s staticSurface_t;
/*
============================================================
DRAWING
============================================================
*/
void Draw_StretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader);
void Draw_TilePic(float x, float y, float w, float h, qhandle_t hShader);
void Draw_TilePicOffset(float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY);
void Draw_TrianglePic(const vec2_t vPoints[3], const vec2_t vTexCoords[3], qhandle_t hShader);
void DrawBox(float x, float y, float w, float h);
void AddBox(float x, float y, float w, float h);
void Set2DWindow(int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f);
void RE_Scissor(int x, int y, int width, int height);
void DrawLineLoop(const vec2_t* points, int count, int stipple_factor, int stipple_mask);
/*
============================================================
FLARES
============================================================
*/
void R_ClearFlares(void);
void RB_AddFlare(void* surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal);
void RB_AddDlightFlares(void);
void RB_RenderFlares(void);
/*
=============================================================
FONT
=============================================================
*/
fontheader_t* R_LoadFont(const char* name);
void R_LoadFontShader(fontheader_t* font);
void R_DrawString(fontheader_t* font, const char* text, float x, float y, int maxlen, qboolean bVirtualScreen);
float R_GetFontHeight(const fontheader_t* font);
float R_GetFontStringWidth(const fontheader_t* font, const char* s);
/*
============================================================
LIGHTS
============================================================
*/
void R_DlightBmodel(bmodel_t* bmodel);
void R_GetLightingGridValue(const vec3_t vPos, vec3_t vLight);
void R_GetLightingForDecal(vec3_t vLight, vec3_t vFacing, vec3_t vOrigin);
void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin);
void R_SetupEntityLighting(const trRefdef_t* refdef, trRefEntity_t* ent);
void RB_SetupEntityGridLighting();
void RB_SetupStaticModelGridLighting(trRefdef_t* refdef, cStaticModelUnpacked_t* ent, const vec3_t lightOrigin);
void R_TransformDlights(int count, dlight_t* dl, orientationr_t* ori);
void RB_Light_Real(unsigned char* colors);
void RB_Sphere_BuildDLights();
void RB_Sphere_SetupEntity();
void RB_Grid_SetupEntity();
void RB_Grid_SetupStaticModel();
void RB_Light_Fullbright(unsigned char* colors);
void R_Sphere_InitLights();
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights);
void R_UploadDlights();
/*
=============================================================
MARKS
=============================================================
*/
void R_LevelMarksLoad(const char* szBSPName);
void R_LevelMarksInit();
void R_LevelMarksFree();
void R_UpdateLevelMarksSystem();
void R_AddPermanentMarkFragmentSurfaces(void** pFirstMarkFragment, int iNumMarkFragment);
int R_MarkFragments_New(int numPoints, const vec3_t* points, const vec3_t projection,
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer, float fRadiusSquared);
int R_MarkFragmentsForInlineModel(clipHandle_t bmodel, const vec3_t angles, const vec3_t origin, int numPoints,
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t* fragmentBuffer, float radiusSquared);
/*
=============================================================
SHADE
=============================================================
*/
void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor);
void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha);
void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax);
void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st);
void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st);
/*
=============================================================
SKY PORTALS
=============================================================
*/
void R_Sky_Init();
void R_Sky_Reset();
void R_Sky_AddSurf(msurface_t* surf);
/*
=============================================================
SPRITE
=============================================================
*/
sprite_t* SPR_RegisterSprite(const char* name);
void RB_DrawSprite(const refSprite_t* spr);
/*
=============================================================
SUN FLARE
=============================================================
*/
void R_InitLensFlare();
void R_DrawLensFlares();
/*
=============================================================
SWIPE
=============================================================
*/
void RB_DrawSwipeSurface(surfaceType_t* pswipe);
void RE_SwipeBegin(float thistime, float life, qhandle_t shader);
void RE_SwipeEnd();
/*
=============================================================
TERRAIN
=============================================================
*/
void R_MarkTerrainPatch(cTerraPatchUnpacked_t* pPatch);
void R_AddTerrainSurfaces();
void R_InitTerrain();
void R_TerrainPrepareFrame();
/*
=============================================================
SCENE GENERATION
=============================================================
*/
void RE_AddRefSpriteToScene(const refEntity_t* ent);
void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx);
refEntity_t* RE_GetRenderEntity(int entityNumber);
/*
=============================================================
TIKI
=============================================================
*/
void R_InitStaticModels(void);
void RE_FreeModels(void);
qhandle_t RE_SpawnEffectModel(const char* szModel, vec3_t vPos, vec3_t* axis);
qhandle_t RE_RegisterServerModel(const char* name);
void RE_UnregisterServerModel(qhandle_t hModel);
orientation_t RE_TIKI_Orientation(refEntity_t* model, int tagnum);
qboolean RE_TIKI_IsOnGround(refEntity_t* model, int tagnum, float threshold);
float R_ModelRadius(qhandle_t handle);
void R_ModelBounds(qhandle_t handle, vec3_t mins, vec3_t maxs);
dtiki_t* R_Model_GetHandle(qhandle_t handle);
float R_GetRadius(refEntity_t* model);
void R_GetFrame(refEntity_t* model, struct skelAnimFrame_s* newFrame);
void RE_ForceUpdatePose(refEntity_t* model);
void RE_SetFrameNumber(int frameNumber);
void R_UpdatePoseInternal(refEntity_t* model);
void RB_SkelMesh(skelSurfaceGame_t* sf);
void RB_StaticMesh(staticSurface_t* staticSurf);
void RB_Static_BuildDLights();
void R_PrintInfoStaticModels();
void R_AddSkelSurfaces(trRefEntity_t* ent);
void R_AddStaticModelSurfaces(void);
float R_CalcLod(const vec3_t origin, float radius);
int R_LerpTag(orientation_t* tag, qhandle_t handle, int startFrame, int endFrame,
float frac, const char* tagName);
void R_PrintInfoWorldtris(void);
/*
=============================================================
UTIL
=============================================================
*/
int RE_GetShaderHeight(qhandle_t hShader);
int RE_GetShaderWidth(qhandle_t hShader);
void RB_StreamBegin(shader_t* shader);
void RB_StreamEnd(void);
void RB_StreamBeginDrawSurf(void);
void RB_StreamEndDrawSurf(void);
static void addTriangle(void);
void RB_Vertex3fv(vec3_t v);
void RB_Vertex3f(vec_t x, vec_t y, vec_t z);
void RB_Vertex2f(vec_t x, vec_t y);
void RB_Color4f(vec_t r, vec_t g, vec_t b, vec_t a);
void RB_Color3f(vec_t r, vec_t g, vec_t b);
void RB_Color3fv(vec3_t col);
void RB_Color4bv(unsigned char* colors);
void RB_Texcoord2f(float s, float t);
void RB_Texcoord2fv(vec2_t st);
void R_DrawDebugNumber(const vec3_t org, float number, float scale, float r, float g, float b, int precision);
void R_DebugRotatedBBox(const vec3_t org, vec3_t ang, vec3_t mins, vec3_t maxs, float r, float g, float b, float alpha);
const char* RE_GetGraphicsInfo();
/*
=============================================================
WORLD MAP
=============================================================
*/
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs);
extern int g_nStaticSurfaces;
extern qboolean g_bInfostaticmodels;
extern qboolean g_bInfoworldtris;
//
//
//
void R_DebugCircle(const vec3_t org, float radius, float r, float g, float b, float alpha, qboolean horizontal);
void R_DebugLine(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha);
void RE_SetRenderTime(int t);
qboolean R_SetMode(int mode, const glconfig_t* glConfig);
void R_SetFullscreen(qboolean fullscreen);
void R_SavePerformanceCounters(void);
void R_SyncRenderThread(void);

View file

@ -1,107 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#pragma once
typedef struct suninfo_s {
vec3_t color;
vec3_t direction;
vec3_t flaredirection;
char szFlareName[64];
qboolean exists;
} suninfo_t;
typedef struct {
vec3_t transformed;
int index;
} sphere_dlight_t;
typedef enum {
LIGHT_POINT,
LIGHT_DIRECTIONAL,
LIGHT_SPOT,
LIGHT_SPOT_FAST
} lighttype_t;
typedef struct reallightinfo_s {
vec3_t color;
lighttype_t eType;
float fIntensity;
float fDist;
float fSpotSlope;
float fSpotConst;
float fSpotScale;
vec3_t vOrigin;
vec3_t vDirection;
} reallightinfo_t;
typedef float cube_entry_t[3][4];
typedef struct {
vec3_t origin;
vec3_t worldOrigin;
vec3_t traceOrigin;
float radius;
struct mnode_s* leaves[8];
void(*TessFunction) (unsigned char* dstColors);
union {
unsigned char level[4];
int value;
} ambient;
int numRealLights;
reallightinfo_t light[32];
int bUsesCubeMap;
float cubemap[24][3][4];
} sphereor_t;
typedef struct spherel_s {
vec3_t origin;
vec3_t color;
float intensity;
struct mnode_s* leaf;
int needs_trace;
int spot_light;
float spot_radiusbydistance;
vec3_t spot_dir;
int reference_count;
} spherel_t;
typedef enum {
SPRITE_PARALLEL,
SPRITE_PARALLEL_ORIENTED,
SPRITE_ORIENTED,
SPRITE_PARALLEL_UPRIGHT
} spriteType_t;
typedef struct {
spriteType_t type;
float scale;
} spriteParms_t;
typedef struct {
float width;
float height;
float origin_x;
float origin_y;
float scale;
struct shader_s* shader;
} sprite_t;

View file

@ -1,122 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
#define CIRCLE_LENGTH 25
/*
================
R_DebugCircle
================
*/
void R_DebugCircle(const vec3_t org, float radius, float r, float g, float b, float alpha, qboolean horizontal) {
int i;
float ang;
debugline_t* line;
vec3_t forward, right;
vec3_t pos, lastpos;
if (!ri.DebugLines || !ri.numDebugLines) {
return;
}
if (horizontal)
{
VectorSet(forward, 1, 0, 0);
VectorSet(right, 0, 1, 0);
}
else
{
VectorCopy(tr.refdef.viewaxis[1], right);
VectorCopy(tr.refdef.viewaxis[2], forward);
}
VectorClear(pos);
VectorClear(lastpos);
for (i = 0; i < CIRCLE_LENGTH; i++) {
VectorCopy(pos, lastpos);
ang = (float)i * 0.0174532925199433f;
pos[0] = (org[0] + sin(ang) * radius * forward[0]) +
cos(ang) * radius * right[0];
pos[1] = (org[1] + sin(ang) * radius * forward[1]) +
cos(ang) * radius * right[1];
pos[2] = (org[2] + sin(ang) * radius * forward[2]) +
cos(ang) * radius * right[2];
if (i > 0)
{
if (*ri.numDebugLines >= r_numdebuglines->integer) {
ri.Printf(PRINT_ALL, "R_DebugCircle: Exceeded MAX_DEBUG_LINES\n");
return;
}
line = &(*ri.DebugLines)[*ri.numDebugLines];
(*ri.numDebugLines)++;
VectorCopy(lastpos, line->start);
VectorCopy(pos, line->end);
VectorSet(line->color, r, g, b);
line->alpha = alpha;
line->width = 1.0;
line->factor = 1;
line->pattern = -1;
}
}
}
/*
================
R_DebugLine
================
*/
void R_DebugLine(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha) {
debugline_t* line;
if (!ri.DebugLines || !ri.numDebugLines) {
return;
}
if (*ri.numDebugLines >= r_numdebuglines->integer) {
ri.Printf(PRINT_ALL, "R_DebugLine: Exceeded MAX_DEBUG_LINES\n");
}
line = &(*ri.DebugLines)[*ri.numDebugLines];
(*ri.numDebugLines)++;
VectorCopy(start, line->start);
VectorCopy(end, line->end);
VectorSet(line->color, r, g, b);
line->alpha = alpha;
line->width = 1.0;
line->factor = 1;
line->pattern = -1;
}
/*
================
R_DrawDebugLines
================
*/
void R_DrawDebugLines(void) {
// FIXME: stub
}

View file

@ -1,35 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
int R_MarkFragments_New(int numPoints, const vec3_t* points, const vec3_t projection,
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer, float fRadiusSquared) {
return R_MarkFragments(numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer);
}
int R_MarkFragmentsForInlineModel(clipHandle_t bmodel, const vec3_t angles, const vec3_t origin, int numPoints,
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t* fragmentBuffer, float radiusSquared)
{
// FIXME: unimplemented
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,77 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
extern int r_firstSceneDrawSurf;
extern int r_numdlights;
extern int r_firstSceneDlight;
extern int r_numentities;
extern int r_firstSceneEntity;
extern int r_numpolys;
extern int r_firstScenePoly;
extern int r_numpolyverts;
void RE_AddRefSpriteToScene(const refEntity_t* ent) {
// FIXME: unimplemented
}
/*
=====================
R_AddTerrainMarkSurfaces
=====================
*/
void R_AddTerrainMarkSurfaces(void) {
// FIXME: unimplemented
}
/*
=====================
RE_AddTerrainMarkToScene
=====================
*/
void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx) {
// FIXME: unimplemented
}
//=================================================================================
/*
=====================
RE_GetRenderEntity
=====================
*/
refEntity_t* RE_GetRenderEntity(int entityNumber) {
int i;
for (i = 0; i < r_numentities; i++) {
if (backEndData->entities[i].e.entityNumber == entityNumber) {
return &backEndData->entities[i].e;
}
}
return NULL;
}

View file

@ -1,77 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
/*
** RB_CalcColorFromConstant
*/
void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor)
{
int i;
for (i = 0; i < tess.numVertexes; i++) {
dstColors[i * 4] = constantColor[0];
dstColors[i * 4 + 1] = constantColor[1];
dstColors[i * 4 + 2] = constantColor[2];
dstColors[i * 4 + 3] = constantColor[3];
}
}
void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha)
{
int i;
for (i = 0; i < tess.numVertexes; i++) {
dstColors[i * 4 + 3] = constantAlpha;
}
}
void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax)
{
// FIXME: unimplemented
}
void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st)
{
// FIXME: unimplemented
}
void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st)
{
// FIXME: unimplemented
}

View file

@ -1,29 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
qhandle_t RE_RefreshShaderNoMip(const char* name) {
// FIXME: unimplemented
// Workaround
return RE_RegisterShaderNoMip(name);
}

View file

@ -1,129 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sphere_shade.cpp -- sphere shade
#include "../tr_local.h"
vec3_t spheredef[6];
suninfo_t s_sun;
static vec3_t ambientlight;
static qboolean bEntityOverbright;
static int iEntityLightingMax;
static int light_reference_count = 0;
int compare_light_intensities(const void* p1, const void* p2)
{
return ((const reallightinfo_t*)p2)->fIntensity - ((const reallightinfo_t*)p1)->fIntensity;
}
static void RB_OptimizeLights()
{
// FIXME: unimplemented
}
static void RB_Light_CubeMap(const color4ub_t colors)
{
// FIXME: unimplemented
}
void RB_Light_Real(unsigned char* colors)
{
int i, j;
float* normal;
float* xyz;
unsigned char* color;
vec3_t v;
vec3_t colorout;
float fDot;
reallightinfo_t* pLight;
// FIXME: unimplemented
}
static void RB_Sphere_Light_Sun()
{
// FIXME: unimplemented
}
static qboolean RB_Sphere_CalculateSphereOrigin()
{
// FIXME: unimplemented
return qfalse;
}
static void RB_Sphere_DrawDebugLine(const spherel_t* thislight, float falloff, const vec3_t origin)
{
// FIXME: unimplemented
}
static void RB_Sphere_AddSpotLight(const spherel_t* thislight)
{
// FIXME: unimplemented
}
static void RB_Sphere_AddLight(const spherel_t* thislight)
{
// FIXME: unimplemented
}
static void RB_Sphere_BuildStaticLights()
{
// FIXME: unimplemented
}
void RB_Sphere_BuildDLights()
{
// FIXME: unimplemented
}
void RB_Sphere_SetupEntity()
{
// FIXME: unimplemented
}
void RB_Grid_SetupEntity()
{
// FIXME: unimplemented
}
void RB_Grid_SetupStaticModel()
{
// FIXME: unimplemented
}
void RB_Light_Fullbright(unsigned char* colors)
{
memset((void*)colors, 0xFF, tess.numVertexes);
}
void R_Sphere_InitLights()
{
// FIXME: unimplemented
}
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights)
{
// FIXME: unimplemented
return 0;
}

View file

@ -1,66 +0,0 @@
/*
===========================================================================
Copyright (C) 2010 su44
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sprite.c - MoHAA sprite system
#include "../tr_local.h"
/*
=====================
SPR_RegisterSprite
=====================
*/
sprite_t *SPR_RegisterSprite(const char *name)
{
image_t *spriteImage;
shader_t *shader;
sprite_t *spr;
char shadername[256];
COM_StripExtension(name,shadername,sizeof(shadername));
shader = R_FindShader(shadername,-1,qfalse,qfalse,qfalse,qfalse);
if(shader) {
spriteImage = 0;
if(shader->stages[0])
spriteImage = shader->stages[0]->bundle[0].image[0];
if ( !spriteImage ) {
ri.Printf(1, "Could not find image for sprite in shader %s\n", name);
return 0;
}
spr = ri.Hunk_Alloc(sizeof(sprite_t), h_dontcare);
spr->height = spriteImage->height;
spr->width = spriteImage->width;
spr->origin_x = spr->width * 0.5;
spr->origin_y = spr->height * 0.5;
spr->shader = shader;
spr->scale = spr->shader->sprite.scale;
return spr;
}
return 0;
}
/*
=====================
RB_DrawSprite
=====================
*/
void RB_DrawSprite( const refSprite_t *spr ) {
// FIXME: stub
}

View file

@ -1,44 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_swipe.cpp -- swipe rendering
#include "../tr_local.h"
void RB_DrawSwipeSurface(surfaceType_t* pswipe) {
// FIXME: unimplemented
}
void RE_SwipeBegin(float thistime, float life, qhandle_t shader)
{
// FIXME: unimplemented
}
void RE_SwipePoint(vec3_t point1, vec3_t point2, float time)
{
// FIXME: unimplemented
}
void RE_SwipeEnd()
{
// FIXME: unimplemented
}

View file

@ -1,260 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_util.c -- renderer utility
#include "../tr_local.h"
static const size_t colorSize = (1 << (sizeof(uint16_t) * 8)) - 1;
static uint16_t cntColor[4];
static float cntSt[ 2 ];
/*
===============
RB_StreamBegin
===============
*/
void RB_StreamBegin( shader_t *shader ) {
RB_BeginSurface( shader, 0, 0 );
}
/*
===============
RB_StreamEnd
===============
*/
void RB_StreamEnd( void ) {
int i;
if( tess.numVertexes <= 2 ) {
RB_EndSurface();
return;
}
tess.indexes[ 0 ] = 0;
tess.indexes[ 1 ] = 1;
tess.indexes[ 2 ] = 2;
for( i = 0; i < tess.numVertexes - 2; i++ ) {
tess.indexes[ i * 3 + 0 ] = ( i & 1 ) + i;
tess.indexes[ i * 3 + 1 ] = i - ( ( i & 1 ) - 1 );
tess.indexes[ i * 3 + 2 ] = i + 2;
tess.numIndexes += 3;
}
RB_EndSurface();
}
/*
===============
RB_StreamBeginDrawSurf
===============
*/
void RB_StreamBeginDrawSurf( void ) {
backEnd.dsStreamVert = tess.numVertexes;
}
/*
===============
RB_StreamEndDrawSurf
===============
*/
void RB_StreamEndDrawSurf( void ) {
int numverts;
int i;
if( tess.numVertexes - backEnd.dsStreamVert <= 2 ) {
tess.numVertexes = backEnd.dsStreamVert;
return;
}
numverts = tess.numVertexes - backEnd.dsStreamVert - 2;
for( i = 0; i < numverts; i++ ) {
tess.indexes[ i + tess.numIndexes ] = ( i & 1 ) + i + backEnd.dsStreamVert;
tess.indexes[ i + tess.numIndexes + 1 ] = i + backEnd.dsStreamVert - ( ( i & 1 ) - 1 );
tess.indexes[ i + tess.numIndexes + 2 ] = i + backEnd.dsStreamVert + 2;
tess.numIndexes += 3;
}
}
/*
===============
addTriangle
===============
*/
static void addTriangle(void) {
tess.texCoords[tess.numVertexes][0] = cntSt[0];
tess.texCoords[tess.numVertexes][1] = cntSt[1];
tess.color[tess.numVertexes][0] = cntColor[0];
tess.color[tess.numVertexes][1] = cntColor[1];
tess.color[tess.numVertexes][2] = cntColor[2];
tess.color[tess.numVertexes][3] = cntColor[3];
tess.numVertexes++;
}
/*
===============
RB_Vertex3fv
===============
*/
void RB_Vertex3fv( vec3_t v ) {
VectorCopy( v, tess.xyz[ tess.numVertexes ] );
addTriangle();
}
/*
===============
RB_Vertex3f
===============
*/
void RB_Vertex3f( vec_t x, vec_t y, vec_t z ) {
tess.xyz[ tess.numVertexes ][ 0 ] = x;
tess.xyz[ tess.numVertexes ][ 1 ] = y;
tess.xyz[ tess.numVertexes ][ 2 ] = z;
addTriangle();
}
/*
===============
RB_Vertex2f
===============
*/
void RB_Vertex2f( vec_t x, vec_t y ) {
RB_Vertex3f( x, y, 0 );
}
/*
===============
RB_Color4f
===============
*/
void RB_Color4f( vec_t r, vec_t g, vec_t b, vec_t a ) {
cntColor[ 0 ] = r * tr.identityLightByte;
cntColor[ 1 ] = g * tr.identityLightByte;
cntColor[ 2 ] = b * tr.identityLightByte;
cntColor[ 3 ] = a * 255.0;
}
/*
===============
RB_Color3f
===============
*/
void RB_Color3f( vec_t r, vec_t g, vec_t b ) {
RB_Color4f( r, g, b, 1.0 );
}
/*
===============
RB_Color3fv
===============
*/
void RB_Color3fv( vec3_t col ) {
RB_Color3f( col[ 0 ], col[ 1 ], col[ 2 ] );
}
/*
===============
RB_Color4bv
===============
*/
void RB_Color4bv( unsigned char *colors ) {
cntColor[ 0 ] = colors[ 0 ];
cntColor[ 1 ] = colors[ 1 ];
cntColor[ 2 ] = colors[ 2 ];
cntColor[ 3 ] = colors[ 3 ];
}
/*
===============
RB_Texcoord2f
===============
*/
void RB_Texcoord2f( float s, float t ) {
cntSt[ 0 ] = s;
cntSt[ 1 ] = t;
}
/*
===============
RB_Texcoord2fv
===============
*/
void RB_Texcoord2fv( vec2_t st ) {
cntSt[ 0 ] = st[ 0 ];
cntSt[ 1 ] = st[ 1 ];
}
static int Numbers[ 12 ][ 8 ];
static float Lines[ 13 ][ 4 ];
/*
===============
R_DrawDebugNumber
===============
*/
void R_DrawDebugNumber( const vec3_t org, float number, float scale, float r, float g, float b, int precision ) {
// FIXME: unimplemented
}
/*
===============
R_DebugRotatedBBox
===============
*/
void R_DebugRotatedBBox( const vec3_t org, vec3_t ang, vec3_t mins, vec3_t maxs, float r, float g, float b, float alpha ) {
}
/*
===============
RE_GetShaderWidth
===============
*/
int RE_GetShaderWidth( qhandle_t hShader ) {
shader_t *shader;
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
} else {
shader = tr.defaultShader;
}
return shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
}
/*
===============
RE_GetShaderHeight
===============
*/
int RE_GetShaderHeight( qhandle_t hShader ) {
shader_t *shader;
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
}
else {
shader = tr.defaultShader;
}
return shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
}

View file

@ -1,28 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../tr_local.h"
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs)
{
// FIXME: unimplemented
}

View file

@ -43,6 +43,42 @@ static byte *fileBase;
int c_subdivisions;
int c_gridVerts;
//
// OPENMOHAA-specific stuff
//=========================
static int map_length;
static int nummodels;
static int numShaders;
static int numbrushes;
static int numbrushsides;
static int numFogs;
static int numplanes;
static int num_entities;
static int numnodes;
static int numleafs;
static int numleafsurfaces;
static int numDrawVerts;
static int numDrawIndexes;
static int numDrawSurfaces;
static int numLightDefs;
static int numLightBytes;
static int numVisBytes;
static int numSLights;
static int entLightVisSize;
static int g_iGridArraySize;
static int g_iGridDataSize;
static int g_iGridPaletteBytes;
static int g_iGridOffsets;
static int g_nStaticModelData;
static int map_version;
static int g_nStaticModelIndices;
static int g_nStaticModels;
static int g_nTerPatchIndices;
static int g_nTerraPatches;
//=========================
//===============================================================================
static void HSVtoRGB( float h, float s, float v, float rgb[3] )
@ -3016,3 +3052,66 @@ void RE_LoadWorldMap( const char *name ) {
ri.FS_FreeFile( buffer.v );
}
//
// OPENMOHAA-specific stuff
//
/*
=================
RE_MapVersion
=================
*/
int RE_MapVersion(void)
{
return map_version;
}
/*
=================
RE_PrintBSPFileSizes
=================
*/
void RE_PrintBSPFileSizes(void)
{
ri.Printf(PRINT_ALL, "%s: %i\n", s_worldData.name, map_length);
ri.Printf(PRINT_ALL, "%6i models %7i\n", nummodels, 40 * nummodels);
ri.Printf(PRINT_ALL, "%6i shaders %7i\n", numShaders, 140 * numShaders);
ri.Printf(PRINT_ALL, "%6i brushes %7i\n", numbrushes, 12 * numbrushes);
ri.Printf(PRINT_ALL, "%6i brushsides %7i\n", numbrushsides, 12 * numbrushsides);
ri.Printf(PRINT_ALL, "%6i fogs %7i\n", numFogs, 72 * numFogs);
ri.Printf(PRINT_ALL, "%6i planes %7i\n", numplanes, 16 * numplanes);
ri.Printf(PRINT_ALL, "%6i nodes %7i\n", numnodes, 36 * numnodes);
ri.Printf(PRINT_ALL, "%6i leafs %7i\n", numleafs, numleafs << 6);
ri.Printf(PRINT_ALL, "%6i leafsurfaces %7i\n", numleafsurfaces, 4 * numleafsurfaces);
ri.Printf(PRINT_ALL, "%6i drawverts %7i\n", numDrawVerts, 44 * numDrawVerts);
ri.Printf(PRINT_ALL, "%6i drawindexes %7i\n", numDrawIndexes, 4 * numDrawIndexes);
ri.Printf(PRINT_ALL, "%6i drawsurfaces %7i\n", numDrawSurfaces, 108 * numDrawSurfaces);
ri.Printf(PRINT_ALL, "%6i lightdefs %7i\n", numLightDefs, 52 * numLightDefs);
ri.Printf(PRINT_ALL, "%6i lightmaps %7i\n", numLightBytes / 49152, numLightBytes);
ri.Printf(PRINT_ALL, " visibility %7i\n", numVisBytes);
ri.Printf(PRINT_ALL, "%6i entitylights %7i\n", numSLights, 56 * numSLights);
ri.Printf(PRINT_ALL, " entitylightvis %7i\n", entLightVisSize);
ri.Printf(PRINT_ALL, " light grid palette %7i\n", g_iGridPaletteBytes);
ri.Printf(PRINT_ALL, "%6i light grid offsets %7i\n", g_iGridOffsets, 2 * g_iGridOffsets);
ri.Printf(PRINT_ALL, " light grid data %7i\n", g_iGridDataSize);
ri.Printf(PRINT_ALL, "%6i terrain %7i\n", g_nTerraPatches, 388 * g_nTerraPatches);
ri.Printf(PRINT_ALL, "%6i terrain indexes %7i\n", g_nTerPatchIndices, 2 * g_nTerPatchIndices);
ri.Printf(PRINT_ALL, " static model data %7i\n", g_nStaticModelData);
ri.Printf(PRINT_ALL, "%6i static models defs %7i\n", g_nStaticModels, 164 * g_nStaticModels);
ri.Printf(PRINT_ALL, " static model indexes %7i\n", g_nStaticModelIndices);
}
/*
=================
R_ClearWorld
Set the world to NULL to prevent anyone from accessing
freed world data
=================
*/
void R_ClearWorld(void) {
tr.world = NULL;
}

View file

@ -21,12 +21,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tr_local.h"
static backEndCounters_t pc_save;
/*
=====================
R_SavePerformanceCounters
=====================
*/
void R_SavePerformanceCounters(void) {
memcpy(&pc_save, &backEnd.pc, sizeof(pc_save));
}
/*
=====================
R_PerformanceCounters
=====================
*/
void R_PerformanceCounters( void ) {
if (r_fps->integer) {
ri.SetPerformanceCounters(
backEnd.pc.c_totalIndexes / 3,
backEnd.pc.c_vertexes,
R_SumOfUsedImages(),
pc_save.c_totalIndexes / 3,
pc_save.c_vertexes,
backEnd.pc.c_characterlights
);
}
if ( !r_speeds->integer ) {
// clear the counters even if we aren't printing
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );

View file

@ -21,7 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// tr_draw.c -- drawing
#include "../tr_local.h"
#include "tr_local.h"
vec4_t r_colorWhite = { 1.0, 1.0, 1.0, 1.0 };
@ -40,6 +40,7 @@ void Draw_SetColor(const vec4_t rgba) {
backEnd.color2D[1] = (byte)(rgba[1] * tr.identityLightByte);
backEnd.color2D[2] = (byte)(rgba[2] * tr.identityLightByte);
backEnd.color2D[3] = (byte)(rgba[3] * 255.0);
//qglColor4ubv(backEnd.color2D);
#else
RE_SetColor(rgba);
#endif
@ -54,7 +55,7 @@ void Draw_StretchPic(float x, float y, float w, float h, float s1, float t1, flo
#if 1
shader_t* shader;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (hShader) {
shader = R_GetShaderByHandle(hShader);
@ -90,6 +91,58 @@ void Draw_StretchPic(float x, float y, float w, float h, float s1, float t1, flo
#endif
}
/*
================
Draw_StretchPic2
================
*/
void Draw_StretchPic2(float x, float y, float w, float h, float s1, float t1, float s2, float t2, float sx, float sy, qhandle_t hShader) {
shader_t* shader;
float halfWidth, halfHeight;
float scaledWidth1, scaledHeight1;
float scaledWidth2, scaledHeight2;
R_IssuePendingRenderCommands();
if (hShader) {
shader = R_GetShaderByHandle(hShader);
}
else {
shader = tr.defaultShader;
}
if (w <= 0) {
w = shader->stages[0]->bundle[0].image[0]->width;
h = shader->stages[0]->bundle[0].image[0]->height;
}
halfWidth = w * 0.5f;
halfHeight = h * 0.5f;
scaledWidth1 = halfWidth * sy;
scaledHeight1 = halfHeight * sx;
scaledWidth2 = halfWidth * sx;
scaledHeight2 = halfHeight * sy;
// draw the pic
RB_Color4f(backEnd.color2D[0], backEnd.color2D[1], backEnd.color2D[2], backEnd.color2D[3]);
RB_BeginSurface(shader, 0, 0);
RB_Texcoord2f(s1, t1);
RB_Vertex3f(x + halfWidth - (scaledWidth2 + -scaledHeight2), y + halfWidth - scaledHeight1 - scaledWidth1, 0);
RB_Texcoord2f(t2, t1);
RB_Vertex3f(scaledWidth2 - -scaledHeight2 + x + halfWidth, scaledWidth1 - scaledHeight1 + y + halfWidth, 0);
RB_Texcoord2f(s1, s2);
RB_Vertex3f(x+ halfWidth - (scaledWidth2 + scaledHeight2), scaledHeight1 - scaledWidth1 + y + halfWidth, 0);
RB_Texcoord2f(t2, s2);
RB_Vertex3f(scaledWidth2 - scaledHeight2 + x + halfWidth, scaledWidth1 + scaledHeight1 + y + halfWidth, 0);
RB_StreamEnd();
}
/*
================
Draw_TilePic
@ -99,7 +152,7 @@ void Draw_TilePic(float x, float y, float w, float h, qhandle_t hShader) {
shader_t* shader;
float picw, pich;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (hShader) {
shader = R_GetShaderByHandle(hShader);
@ -145,7 +198,7 @@ void Draw_TilePicOffset(float x, float y, float w, float h, qhandle_t hShader, i
shader_t* shader;
float picw, pich;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (hShader) {
shader = R_GetShaderByHandle(hShader);
@ -191,7 +244,7 @@ void Draw_TrianglePic(const vec2_t vPoints[3], const vec2_t vTexCoords[3], qhand
int i;
shader_t* shader;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (hShader) {
shader = R_GetShaderByHandle(hShader);
@ -219,15 +272,15 @@ RE_DrawBackground_TexSubImage
================
*/
void RE_DrawBackground_TexSubImage(int cols, int rows, int bgr, byte* data) {
// FIXME: unimplemented (GL2)
#if 0
GLenum format;
int w, h;
vec4_t quadVerts[4];
vec2_t texCoords[4];
int w, h;
w = glConfig.vidWidth;
h = glConfig.vidHeight;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
qglFinish();
if (bgr) {
@ -237,17 +290,17 @@ void RE_DrawBackground_TexSubImage(int cols, int rows, int bgr, byte* data) {
format = GL_RGB;
}
GL_BindToTMU(tr.scratchImage[0], TB_COLORMAP);
GL_Bind(tr.scratchImage);
if (cols == tr.scratchImage[0]->width && rows == tr.scratchImage[0]->height && format == tr.scratchImage[0]->internalFormat)
if (cols == tr.scratchImage->width && rows == tr.scratchImage->height && format == tr.scratchImage->internalFormat)
{
qglTexSubImage2D(3553, 0, 0, 0, cols, rows, format, 5121, data);
}
else
{
tr.scratchImage[0]->uploadWidth = cols;
tr.scratchImage[0]->uploadHeight = rows;
tr.scratchImage[0]->internalFormat = format;
tr.scratchImage->uploadWidth = cols;
tr.scratchImage->uploadHeight = rows;
tr.scratchImage->internalFormat = format;
qglTexImage2D(GL_TEXTURE_2D, 0, 3, cols, rows, 0, format, 5121, data);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9729.0);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9729.0);
@ -257,22 +310,22 @@ void RE_DrawBackground_TexSubImage(int cols, int rows, int bgr, byte* data) {
qglDisable(GL_DEPTH_TEST);
qglEnable(GL_TEXTURE_2D);
VectorSet4(quadVerts[0], 0.0f, 0.0f, 0.0f, 1.0f);
VectorSet4(quadVerts[1], w, 0.0f, 0.0f, 1.0f);
VectorSet4(quadVerts[2], w, h, 0.0f, 1.0f);
VectorSet4(quadVerts[3], 0.0f, h, 0.0f, 1.0f);
qglBegin(GL_QUADS);
VectorSet2(texCoords[0], 0.5f / cols, (rows - 0.5f) / rows);
VectorSet2(texCoords[1], (cols - 0.5f) / cols, (rows - 0.5f) / rows);
VectorSet2(texCoords[2], (cols - 0.5f) / cols, 0.5f / rows);
VectorSet2(texCoords[3], 0.5f / cols, 0.5f / rows);
qglTexCoord2f(0.5 / (GLfloat)cols, ((GLfloat)rows - 0.5) / rows);
qglVertex2f(0, 0);
GLSL_BindProgram(&tr.textureColorShader);
qglTexCoord2f(((GLfloat)cols - 0.5) / cols, ((GLfloat)rows - 0.5) / rows);
qglVertex2f(w, 0);
GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite);
qglTexCoord2f(((GLfloat)cols - 0.5) / cols, 0.5 / (GLfloat)rows);
qglVertex2f(w, h);
RB_InstantQuad2(quadVerts, texCoords);
qglTexCoord2f(0.5 / (GLfloat)rows, 0.5 / (GLfloat)rows);
qglVertex2f(0, h);
qglEnd();
#endif
}
/*
@ -281,7 +334,25 @@ RE_DrawBackground_DrawPixels
================
*/
void RE_DrawBackground_DrawPixels(int cols, int rows, int bgr, byte* data) {
// FIXME: stub
// FIXME: unimplemented (GL2)
#if 0
R_IssuePendingRenderCommands();
GL_State(0);
qglDisable(GL_TEXTURE_2D);
qglPixelZoom(glConfig.vidWidth / rows, glConfig.vidHeight / cols);
if (bgr) {
qglDrawPixels(cols, rows, GL_BGR, GL_UNSIGNED_BYTE, data);
} else {
qglDrawPixels(cols, rows, GL_RGB, GL_UNSIGNED_BYTE, data);
}
qglPixelZoom(1.0, 1.0);
qglEnable(GL_TEXTURE_2D);
#endif
}
/*
@ -290,36 +361,25 @@ AddBox
================
*/
void AddBox(float x, float y, float w, float h) {
R_SyncRenderThread();
// FIXME: unimplemented (GL2)
#if 0
R_IssuePendingRenderCommands();
qglColor4ubv(backEnd.color2D);
qglDisable(GL_TEXTURE_2D);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
{
shaderProgram_t* sp = &tr.textureColorShader;
vec4_t color = { backEnd.color2D[0] / 255.0f, backEnd.color2D[1] / 255.0f, backEnd.color2D[2] / 255.0f, backEnd.color2D[3] / 255.0f };
vec4_t quadVerts[4];
vec2_t texCoords[4];
qglBegin(GL_QUADS);
VectorSet4(quadVerts[0], x, y, 0.0f, 1.0f);
VectorSet4(quadVerts[1], x + w, y, 0.0f, 1.0f);
VectorSet4(quadVerts[2], x + w, y + h, 0.0f, 1.0f);
VectorSet4(quadVerts[3], x, y + h, 0.0f, 1.0f);
qglVertex2f(x, y);
qglVertex2f(x + w, y);
qglVertex2f(x + w, y + h);
qglVertex2f(x, y + h);
VectorSet2(texCoords[0], 0.0f, 0.0f);
VectorSet2(texCoords[1], 1.0f, 0.0f);
VectorSet2(texCoords[2], 1.0f, 1.0f);
VectorSet2(texCoords[3], 0.0f, 1.0f);
GLSL_BindProgram(sp);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color);
RB_InstantQuad2(quadVerts, texCoords);
}
qglEnd();
qglEnable(GL_TEXTURE_2D);
#endif
}
/*
@ -328,36 +388,25 @@ DrawBox
================
*/
void DrawBox(float x, float y, float w, float h) {
R_SyncRenderThread();
// FIXME: unimplemented (GL2)
#if 0
R_IssuePendingRenderCommands();
qglColor4ubv(backEnd.color2D);
qglDisable(GL_TEXTURE_2D);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA);
{
shaderProgram_t* sp = &tr.textureColorShader;
vec4_t color = { backEnd.color2D[0] / 255.0f, backEnd.color2D[1] / 255.0f, backEnd.color2D[2] / 255.0f, backEnd.color2D[3] / 255.0f };
vec4_t quadVerts[4];
vec2_t texCoords[4];
qglBegin(GL_QUADS);
VectorSet4(quadVerts[0], x, y, 0.0f, 1.0f);
VectorSet4(quadVerts[1], x + w, y, 0.0f, 1.0f);
VectorSet4(quadVerts[2], x + w, y + h, 0.0f, 1.0f);
VectorSet4(quadVerts[3], x, y + h, 0.0f, 1.0f);
qglVertex2f(x, y);
qglVertex2f(x + w, y);
qglVertex2f(x + w, y + h);
qglVertex2f(x, y + h);
VectorSet2(texCoords[0], 0.0f, 0.0f);
VectorSet2(texCoords[1], 1.0f, 0.0f);
VectorSet2(texCoords[2], 1.0f, 1.0f);
VectorSet2(texCoords[3], 0.0f, 1.0f);
GLSL_BindProgram(sp);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color);
RB_InstantQuad2(quadVerts, texCoords);
}
qglEnd();
qglEnable(GL_TEXTURE_2D);
#endif
}
/*
@ -366,19 +415,19 @@ DrawLineLoop
================
*/
void DrawLineLoop(const vec2_t* points, int count, int stipple_factor, int stipple_mask) {
// FIXME: unimplemented (GL2)
#if 0
int i;
R_SyncRenderThread();
R_IssuePendingRenderCommands();
qglDisable(GL_TEXTURE_2D);
if (stipple_factor) {
qglEnable(GL_LINE_STIPPLE);
glLineStipple(stipple_factor, stipple_mask);
qglLineStipple(stipple_factor, stipple_mask);
}
// FIXME: unimplemented
/*
qglBegin(GL_LINE_LOOP);
for (i = 0; i < count; i++) {
@ -386,13 +435,13 @@ void DrawLineLoop(const vec2_t* points, int count, int stipple_factor, int stipp
}
qglEnd();
*/
qglEnable(GL_TEXTURE_2D);
if (stipple_factor) {
qglDisable(GL_LINE_STIPPLE);
}
#endif
}
/*
@ -401,32 +450,36 @@ Set2DWindow
================
*/
void Set2DWindow(int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f) {
mat4_t matrix;
R_SyncRenderThread();
// FIXME: unimplemented (GL2)
#if 0
R_IssuePendingRenderCommands();
qglViewport(x, y, w, h);
qglScissor(x, y, w, h);
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity();
qglOrtho(left, right, bottom, top, n, f);
qglMatrixMode(GL_MODELVIEW);
Mat4Ortho(left, right, bottom, top, n, f, matrix);
GL_SetProjectionMatrix(matrix);
Mat4Identity(matrix);
GL_SetModelviewMatrix(matrix);
qglLoadIdentity();
GL_State(GLS_DEPTHTEST_DISABLE | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA);
qglEnable(GL_BLEND);
qglDisable(GL_CULL_FACE);
qglDisable(GL_CLIP_PLANE0);
// Make sure to disable the fog to avoid messing up with the UI
qglDisable(GL_FOG);
qglFogf(GL_FOG_START, 0);
//if (r_reset_tc_array->integer) {
// qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
//}
if (r_reset_tc_array->integer) {
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (!backEnd.projection2D)
if (!backEnd.in2D)
{
backEnd.refdef.time = ri.Milliseconds();
backEnd.projection2D = qtrue;
backEnd.in2D = qtrue;
backEnd.refdef.floatTime = backEnd.refdef.time / 1000.0;
}
#endif
}
/*
@ -435,6 +488,9 @@ RE_Scissor
================
*/
void RE_Scissor(int x, int y, int width, int height) {
// FIXME: unimplemented (GL2)
#if 0
qglEnable(GL_SCISSOR_TEST);
qglScissor(x, y, width, height);
#endif
}

View file

@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@ -22,16 +22,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// tr_font.cpp -- font rendering
#include "../tr_local.h"
#include "tr_local.h"
#define MAX_LOADED_FONTS 255
static fontheader_sgl_t s_loadedFonts_sgl[MAX_LOADED_FONTS];
static int s_numLoadedFonts_sgl = 0;
static fontheader_t s_loadedFonts[MAX_LOADED_FONTS];
static int s_numLoadedFonts = 0;
static float s_fontHeightScale = 1.0;
static float s_fontGeneralScale = 1.0;
static float s_fontZ = 0.0;
void R_ShutdownFont() {
int i;
fontheader_t *header;
fontheader_sgl_t *header_sgl;
for (i = 0; i < s_numLoadedFonts; i++)
{
header = &s_loadedFonts[i];
if (header->charTable) {
ri.Free(header->charTable);
header->charTable = NULL;
}
memset(header, 0, sizeof(*header));
}
for (i = 0; i < s_numLoadedFonts_sgl; i++)
{
header_sgl = &s_loadedFonts_sgl[i];
memset(header_sgl, 0, sizeof(*header_sgl));
}
}
void R_SetFontHeightScale(float scale)
{
s_fontHeightScale = scale;
@ -47,20 +72,75 @@ void R_SetFontZ(float zed)
s_fontZ = zed;
}
fontheader_t* R_LoadFont(const char* name)
static int CodeSearch(const fontheader_t* font, unsigned short uch) {
int mid;
int l, r;
r = font->charTableLength;
l = 0;
while (l < r) {
mid = (l + r) / 2;
if (font->charTable[mid].cp > uch) {
r = (l + r) / 2;
continue;
}
if (uch == font->charTable[mid].cp) {
return (l + r) / 2;
}
l = mid + 1;
}
if (uch != font->charTable[l].cp) {
return -1;
}
return l;
}
static qboolean DBCSIsLeadByte(const fontheader_t* font, unsigned short uch) {
// Byte ranges found in Wikipedia articles with relevant search strings in each case
switch (font->codePage) {
case 932:
// Shift_jis
return ((uch >= 0x81) && (uch <= 0x9F)) ||
((uch >= 0xE0) && (uch <= 0xFC));
// Lead bytes F0 to FC may be a Microsoft addition.
case 936:
// GBK
return (uch >= 0x81) && (uch <= 0xFE);
case 949:
// Korean Wansung KS C-5601-1987
return (uch >= 0x81) && (uch <= 0xFE);
case 950:
// Big5
return (uch >= 0x81) && (uch <= 0xFE);
case 1361:
// Korean Johab KS C-5601-1992
return
((uch >= 0x84) && (uch <= 0xD3)) ||
((uch >= 0xD8) && (uch <= 0xDE)) ||
((uch >= 0xE0) && (uch <= 0xF9));
}
return false;
}
fontheader_sgl_t* R_LoadFont_sgl(const char* name)
{
int i;
char* theFile;
fontheader_t* header;
fontheader_sgl_t* header;
char* ref;
const char* token;
qboolean error;
error = qfalse;
for (i = 0; i < s_numLoadedFonts; i++)
for (i = 0; i < s_numLoadedFonts_sgl; i++)
{
header = &s_loadedFonts[i];
header = &s_loadedFonts_sgl[i];
if (!Q_stricmp(name, header->name)) {
return header;
}
@ -72,14 +152,13 @@ fontheader_t* R_LoadFont(const char* name)
return NULL;
}
va("fonts/%s.RitualFont", name);
if (ri.FS_ReadFile(va("fonts/%s.RitualFont", name), (void**)&theFile) == -1)
{
ri.Printf(PRINT_WARNING, "LoadFont: Couldn't load font %s\n", name);
return 0;
return NULL;
}
header = &s_loadedFonts[s_numLoadedFonts];
header = &s_loadedFonts_sgl[s_numLoadedFonts_sgl];
header->height = 0.0;
header->aspectRatio = 0.0;
Q_strncpyz(header->name, name, sizeof(header->name));
@ -152,7 +231,7 @@ fontheader_t* R_LoadFont(const char* name)
header->locations[i].pos[1] = atof(COM_Parse(&ref)) * header->aspectRatio / 256.0;
header->locations[i].size[0] = atof(COM_Parse(&ref)) / 256.0;
header->locations[i].size[1] = atof(COM_Parse(&ref)) * header->aspectRatio / 256.0;
token = COM_Parse(&ref);
if (Q_stricmp(token, "}"))
{
@ -211,14 +290,228 @@ fontheader_t* R_LoadFont(const char* name)
}
else
{
s_numLoadedFonts++;
s_numLoadedFonts_sgl++;
return header;
}
return NULL;
}
void R_LoadFontShader(fontheader_t* font)
fontheader_t* R_LoadFont(const char* name) {
int i;
char* theFile;
fontheader_t* header;
char* ref;
const char* token;
qboolean error;
char* pRitFontNames[32];
error = qfalse;
for (i = 0; i < s_numLoadedFonts; i++)
{
header = &s_loadedFonts[i];
if (!Q_stricmp(name, header->name)) {
return header;
}
}
if (s_numLoadedFonts >= MAX_LOADED_FONTS)
{
ri.Printf(PRINT_WARNING, "LoadFont: Too many fonts loaded! Couldn't load %s\n", name);
return NULL;
}
if (ri.FS_ReadFile(va("fonts/%s.RitualFont", name), (void**)&theFile) == -1)
{
ri.Printf(PRINT_WARNING, "LoadFont: Couldn't load font %s\n", name);
return NULL;
}
memset(pRitFontNames, 0, sizeof(pRitFontNames));
ref = theFile;
header = &s_loadedFonts[s_numLoadedFonts];
token = COM_Parse(&ref);
if (Q_stricmp(token, "RitFontList"))
{
if (Q_stricmp(token, "RitFont"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Not actual font %s\n", name);
return NULL;
}
header->numPages = 0;
}
else
{
while (ref && !error)
{
token = COM_Parse(&ref);
if (!Q_stricmp(token, "CodePage"))
{
header->codePage = atoi(COM_Parse(&ref));
}
else if (!Q_stricmp(token, "Chars"))
{
header->charTableLength = atoi(COM_Parse(&ref));
header->charTable = (fontchartable_t*)ri.Malloc(header->charTableLength * sizeof(fontchartable_t));
if (!header->charTable)
{
ri.Printf(PRINT_WARNING, "LoadFont: Couldn't alloc mem %s\n", name);
error = qtrue;
break;
}
}
else if (!Q_stricmp(token, "Pages"))
{
header->numPages = atoi(COM_Parse(&ref));
}
else if (!Q_stricmp(token, "RitFontName"))
{
token = COM_Parse(&ref);
if (Q_stricmp(token, "{"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Format %s\n", name);
error = qtrue;
break;
}
for (i = 0; i < header->numPages; i++)
{
token = COM_Parse(&ref);
if (!token[0])
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Token %s\n", name);
error = qtrue;
break;
}
pRitFontNames[i] = (char*)ri.Malloc(strlen(token) + 1);
if (!pRitFontNames[i])
{
ri.Printf(PRINT_WARNING, "LoadFont: Couldn't alloc mem %s\n", name);
error = qtrue;
break;
}
strcpy(pRitFontNames[i], token);
}
if (error) {
break;
}
token = COM_Parse(&ref);
if (Q_stricmp(token, "}"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Format %s\n", name);
error = qtrue;
break;
}
}
else if (!Q_stricmp(token, "CharTable"))
{
token = COM_Parse(&ref);
if (Q_stricmp(token, "{"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Format %s\n", name);
error = qtrue;
break;
}
for (i = 0; i < header->charTableLength; i++) {
token = COM_Parse(&ref);
if (Q_stricmp(token, "{"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Token %s\n", name);
error = qtrue;
break;
}
header->charTable[i].cp = atoi(COM_Parse(&ref));
header->charTable[i].index = atoi(COM_Parse(&ref));
header->charTable[i].loc = atoi(COM_Parse(&ref));
atoi(COM_Parse(&ref));
token = COM_Parse(&ref);
if (Q_stricmp(token, "}"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Format %s\n", name);
error = qtrue;
break;
}
}
if (error) {
break;
}
token = COM_Parse(&ref);
if (Q_stricmp(token, "}"))
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Format %s\n", name);
error = qtrue;
break;
}
}
else
{
ri.Printf(PRINT_WARNING, "LoadFont: Bad Token %s\n", name);
error = qtrue;
break;
}
}
}
ri.FS_FreeFile(theFile);
if (!header->numPages)
{
header->charTableLength = 0;
header->charTable = NULL;
header->sgl[0] = R_LoadFont_sgl(name);
if (!header->sgl[0])
{
ri.Printf(PRINT_WARNING, "LoadFont: failed %s\n", name);
return NULL;
}
}
else
{
for (i = 0; i < header->numPages; i++)
{
header->sgl[i] = R_LoadFont_sgl(pRitFontNames[i]);
if (!header->sgl[i])
{
ri.Printf(PRINT_WARNING, "LoadFont: failed %s(%s)\n", pRitFontNames[i], name);
error = qtrue;
break;
}
}
// Free all allocated strings
for (i = 0; i < header->numPages; i++) {
ri.Free(pRitFontNames[i]);
}
if (error)
{
if (header->charTable) {
ri.Free(header->charTable);
}
header->numPages = 0;
header->charTableLength = 0;
header->charTable = NULL;
}
}
strcpy(header->name, name);
s_numLoadedFonts++;
return header;
}
void R_LoadFontShader(fontheader_sgl_t* font)
{
int i;
int save;
@ -255,7 +548,7 @@ void R_LoadFontShader(fontheader_t* font)
}
}
void R_DrawString(fontheader_t* font, const char* text, float x, float y, int maxlen, qboolean bVirtualScreen) {
void R_DrawString_sgl(fontheader_sgl_t* font, const char* text, float x, float y, int maxlen, const float *pvVirtualScreen) {
float charHeight;
float startx, starty;
int i;
@ -264,14 +557,25 @@ void R_DrawString(fontheader_t* font, const char* text, float x, float y, int ma
i = 0;
startx = x;
starty = y;
fWidthScale = (double)glConfig.vidWidth / 640.0;
fHeightScale = (double)glConfig.vidHeight / 480.0;
if (pvVirtualScreen) {
if (pvVirtualScreen[0]) {
fWidthScale = pvVirtualScreen[0];
} else {
fWidthScale = (double)glConfig.vidWidth / 640.0;
}
if (pvVirtualScreen[1]) {
fHeightScale = pvVirtualScreen[1];
} else {
fHeightScale = (double)glConfig.vidHeight / 480.0;
}
}
if (!font) {
return;
}
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (font->trhandle != r_sequencenumber) {
font->shader = NULL;
@ -300,9 +604,8 @@ void R_DrawString(fontheader_t* font, const char* text, float x, float y, int ma
case '\t':
indirected = font->indirection[32];
if (indirected == -1) {
Com_DPrintf("R_DrawString: no space-character in font!\n");
}
else {
ri.Printf(PRINT_DEVELOPER, "R_DrawString: no space-character in font!\n");
} else {
x = s_fontGeneralScale * font->locations[indirected].size[0] * 256.0 * 3.0 + x;
}
break;
@ -321,19 +624,17 @@ void R_DrawString(fontheader_t* font, const char* text, float x, float y, int ma
indirected = font->indirection[c];
if (indirected == -1)
{
Com_DPrintf("R_DrawString: no 0x%02x-character in font!\n", c);
ri.Printf(PRINT_DEVELOPER, "R_DrawString: no 0x%02x-character in font!\n", c);
indirected = font->indirection['?'];
if (indirected == -1) {
Com_DPrintf("R_DrawString: no '?' character in font!\n");
ri.Printf(PRINT_DEVELOPER, "R_DrawString: no '?' character in font!\n");
break;
}
}
// set the indirection for the next time
font->indirection[c] = indirected;
font->indirection[c] = indirected;
}
if (tess.numVertexes + 4 >= SHADER_MAX_VERTEXES || tess.numIndexes + 6 >= SHADER_MAX_INDEXES) {
RB_CheckOverflow(4, 6);
}
RB_CHECKOVERFLOW(4, 6);
loc = &font->locations[indirected];
@ -369,7 +670,7 @@ void R_DrawString(fontheader_t* font, const char* text, float x, float y, int ma
tess.indexes[tess.numIndexes + 4] = tess.numVertexes + 3;
tess.indexes[tess.numIndexes + 5] = tess.numVertexes + 2;
if (bVirtualScreen)
if (pvVirtualScreen)
{
// scale the string properly if virtual screen
tess.xyz[tess.numVertexes][0] *= fWidthScale;
@ -392,7 +693,96 @@ void R_DrawString(fontheader_t* font, const char* text, float x, float y, int ma
RB_EndSurface();
}
void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org, const vec4_t color, float scale, int maxlen) {
void R_DrawString(fontheader_t* font, const char* text, float x, float y, int maxlen, const float *pvVirtualScreen) {
int i;
int code;
unsigned short uch;
char buffer[512];
size_t buflen;
int cursgl;
float curX, curY;
float curHeight;
if (!font->numPages) {
if (font->sgl[0]) {
R_DrawString_sgl(font->sgl[0], text, x, y, maxlen, pvVirtualScreen);
}
return;
}
if (maxlen < 0) {
maxlen = strlen(text);
}
curX = x;
curY = y;
curHeight = 0.f;
cursgl = -1;
buflen = 0;
i = 0;
while(i < maxlen) {
fontchartable_t* ct;
uch = text[i];
i++;
if (DBCSIsLeadByte(font, uch)) {
uch = (uch << 8) | text[i];
i++;
}
if (!uch) {
break;
}
if (uch == '\n' || uch == '\r') {
buffer[buflen] = 0;
R_DrawString_sgl(font->sgl[cursgl], buffer, curX, curY, maxlen, pvVirtualScreen);
curX = x;
curHeight = 0.f;
buflen = 0;
if (uch == '\n') {
curY += font->sgl[0]->height * s_fontGeneralScale * s_fontHeightScale;
}
continue;
}
code = CodeSearch(font, uch);
if (code < 0) {
continue;
}
if (cursgl == -1) {
cursgl = font->charTable[code].index;
}
ct = &font->charTable[code];
if (cursgl != ct->index || buflen >= ARRAY_LEN(buffer) - 2) {
buffer[buflen] = 0;
R_DrawString_sgl(font->sgl[cursgl], buffer, curX, curY, maxlen, pvVirtualScreen);
curX += curHeight;
curHeight = 0.f;
buflen = 0;
ct = &font->charTable[code];
cursgl = ct->index;
}
buffer[buflen++] = ct->loc;
curHeight += font->sgl[cursgl]->locations[ct->loc].size[0] * 256.0f;
}
if (buflen)
{
buffer[buflen] = 0;
R_DrawString_sgl(font->sgl[cursgl], buffer, curX, y, buflen, pvVirtualScreen);
}
}
void R_DrawFloatingString_sgl(fontheader_sgl_t* font, const char* text, const vec3_t org, const vec4_t color, float scale, int maxlen) {
shader_t* fontshader;
qhandle_t fsh;
float charWidth, charHeight;
@ -404,8 +794,7 @@ void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org
return;
}
R_SyncRenderThread();
R_IssuePendingRenderCommands();
if (font->trhandle != r_sequencenumber) {
font->shader = NULL;
}
@ -435,12 +824,12 @@ void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org
unsigned char c;
int indirected;
letterloc_t* loc;
c = text[i];
indirected = font->indirection[c];
if (indirected == -1)
{
Com_Printf("R_DrawFloatingString: no 0x%02x-character in font!\n", c);
ri.Printf(PRINT_ALL, "R_DrawFloatingString: no 0x%02x-character in font!\n", c);
continue;
}
@ -485,8 +874,10 @@ void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org
verts[0].xyz[1] = verts[1].xyz[1] + tr.refdef.viewaxis[1][1] * charWidth;
verts[0].xyz[2] = verts[1].xyz[2] + tr.refdef.viewaxis[1][2] * charWidth;
verts[0].xyz[0] = verts[1].xyz[0] + tr.refdef.viewaxis[1][0] * charWidth;
RE_AddPolyToScene(fsh, 4, verts, 1);
if (RE_AddPolyToScene2(fsh, 4, verts, 0)) {
++tr.refdef.numPolys;
}
pos[0] = verts[2].xyz[0];
pos[1] = verts[2].xyz[1];
@ -494,16 +885,20 @@ void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org
}
}
void R_DrawFloatingString(fontheader_t* font, const char* text, const vec3_t org, const vec4_t color, float scale, int maxlen) {
return R_DrawFloatingString_sgl(font->sgl[0], text, org, color, scale, maxlen);
}
float R_GetFontHeight(const fontheader_t* font)
{
if (!font) {
if (!font || !font->sgl[0]) {
return 0.0;
}
return font->height * s_fontGeneralScale * s_fontHeightScale;
return font->sgl[0]->height * s_fontGeneralScale * s_fontHeightScale;
}
float R_GetFontStringWidth(const fontheader_t* font, const char* s)
float R_GetFontStringWidth_sgl(const fontheader_sgl_t* font, const char* s)
{
float widths;
int i;
@ -519,14 +914,13 @@ float R_GetFontStringWidth(const fontheader_t* font, const char* s)
int indirected;
char c = *s;
if (c == 9)
if (c == '\t')
{
indirected = font->indirection[32];
if (indirected != -1) {
widths += font->locations[indirected].size[0] * 3.0;
}
else {
Com_Printf("R_GetFontStringWidth: no space-character in font!\n");
} else {
ri.Printf(PRINT_ALL, "R_GetFontStringWidth: no space-character in font!\n");
}
}
else
@ -534,12 +928,52 @@ float R_GetFontStringWidth(const fontheader_t* font, const char* s)
indirected = font->indirection[c];
if (indirected != -1) {
widths += font->locations[indirected].size[0];
}
else {
Com_Printf("R_GetFontStringWidth: no 0x%02x-character in font!\n", c);
} else {
ri.Printf(PRINT_ALL, "R_GetFontStringWidth: no 0x%02x-character in font!\n", c);
}
}
}
return widths * s_fontGeneralScale * 256.0;
}
float R_GetFontStringWidth(const fontheader_t* font, const char* s)
{
int i;
int code;
fontchartable_t* ct;
float width = 0.f;
if (!font->numPages) {
return R_GetFontStringWidth_sgl(font->sgl[0], s);
}
i = 0;
while(s[i]) {
unsigned char uch = s[i++];
if (DBCSIsLeadByte(font, uch)) {
uch = (uch << 8) | s[i++];
if (!uch) {
break;
}
}
if (uch == '\t') {
code = CodeSearch(font, ' ');
if (code >= 0) {
ct = &font->charTable[code];
width += font->sgl[ct->index]->locations[ct->loc].size[0] * 3.f;
}
}
else {
code = CodeSearch(font, uch);
if (code >= 0) {
ct = &font->charTable[code];
width += font->sgl[ct->index]->locations[ct->loc].size[0];
}
}
}
return width;
}

File diff suppressed because it is too large Load diff

300
code/renderergl2/tr_ghost.h Normal file
View file

@ -0,0 +1,300 @@
/*
===========================================================================
Copyright (C) 2023-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#pragma once
#include "tr_local.h"
#include "../qcommon/vector.h"
#include "../qcommon/container.h"
#include "../qcommon/str.h"
using outcode = unsigned int;
class Particle
{
private:
float m_startTime;
float m_dieTime;
Vector m_velocity;
Vector m_acceleration;
Vector m_perp;
qboolean m_wavy;
float m_wavyDist;
float m_wavyOffset;
int m_srcColor;
int m_dstColor;
int m_deltaR;
int m_deltaG;
int m_deltaB;
int m_srcR;
int m_srcG;
int m_srcB;
int m_dstR;
int m_dstG;
int m_dstB;
float m_colorRate;
Vector m_realposition;
float m_life;
float m_maxspeed;
qboolean m_swarm;
int m_swarmfrequency;
int m_swarmdelta;
Vector m_parentOrigin;
public:
Vector m_position;
int m_color;
public:
Particle(
Vector pos,
Vector vel,
Vector acc,
int srcColor,
int dstColor,
float colorRate,
qboolean wavy,
float wavyDist,
float currentTime,
float dieTime,
float maxspeed,
Vector parentOrg,
qboolean swarm,
int freq,
int delta
);
void Update(float currentTime);
float GetDieTime();
};
class ParticleEmitter
{
private:
float m_time;
float m_lasttime;
Vector m_position;
int m_srcColor;
int m_dstColor;
float m_minColorRate;
float m_maxColorRate;
float m_minRate;
float m_maxRate;
float m_minLife;
float m_maxLife;
float m_angle;
float m_angleVar;
float m_minSpeed;
float m_maxSpeed;
float m_accAngle;
float m_accAngleVar;
float m_minAccSpeed;
float m_maxAccSpeed;
float m_minWavyDist;
float m_maxWavyDist;
qboolean m_wavy;
qboolean m_gravityWell;
float m_gravityWellStrength;
qboolean m_particles;
Vector m_gravityEffectVector;
qboolean m_ballLightning;
int m_minBallLightningRadius;
int m_maxBallLightningRadius;
float m_lightningVar;
int m_lightningSubdivisions;
qboolean m_swarm;
int m_swarmfrequency;
int m_swarmdelta;
int m_maxspeed;
public:
Container<Particle *> particleList;
public:
ParticleEmitter(
Vector position,
float minSpeed,
float maxSpeed,
float angle,
float angleVar,
float minAccSpeed,
float maxAccSpeed,
float accAngle,
float accAngleVar,
float minRate,
float maxRate,
int srcColor,
int dstColor,
float minColorRate,
float maxColorRate,
qboolean wavy,
float minWavyDist,
float maxWavyDist,
float minLife,
float maxLife,
qboolean particles,
qboolean gravityWell,
float gravityWellStrength,
qboolean ballLightning,
int minBallLightningRadius,
int maxBallLightningRadius,
float lightningVar,
int lightningSubdivisions,
qboolean swarm,
int swarmfreq,
int swarmdelta
);
ParticleEmitter();
~ParticleEmitter();
void Emit(float currentTime);
void UpdateValues();
Vector GetPosition();
Vector GetVelocity();
Vector GetVelocityDirection();
Vector GetVelocityDirectionMin();
Vector GetVelocityDirectionMax();
Vector GetAcceleration();
Vector GetAccelerationDirection();
Vector GetAccelerationDirectionMin();
Vector GetAccelerationDirectionMax();
int GetSrcColor();
int GetDstColor();
float GetGravityWellStrength();
float GetRate();
float GetColorRate();
float GetWavyDistance();
float GetDieTime(float currentTime);
int GetBallLightningRadius();
float GetLightningVar();
int GetLightningSubdivisions();
qboolean IsWavy();
qboolean IsGravityWell();
qboolean IsParticles();
qboolean IsBallLightning();
qboolean IsSwarm();
void SetMinSpeed(float value);
void SetMaxSpeed(float value);
void SetAngle(float value);
void SetAngleVar(float value);
void SetMinAccSpeed(float value);
void SetMaxAccSpeed(float value);
void SetAccAngle(float value);
void SetAccAngleVar(float value);
void SetMinRate(float value);
void SetMaxRate(float value);
void SetSrcColor(int value);
void SetDstColor(int value);
void SetMinColorRate(float value);
void SetMaxColorRate(float value);
void SetWavy(int value);
void SetParticles(int value);
void SetGravityWell(int value);
void SetMinWavyDist(float value);
void SetMaxWavyDist(float value);
void SetMinLife(float value);
void SetMaxLife(float value);
void SetGravityWellStrength(float value);
void SetGravityEffectVector(Vector value);
void SetBallLightning(int value);
void SetMinBallLightningRadius(int value);
void SetMaxBallLightningRadius(int value);
void SetLightningVar(float value);
void SetLightningSubdivisions(int value);
float RandomizeRange(float minRange, float maxRange);
float RandomizeAngle(float minAngle, float maxAngle);
Vector CalculateDirection(float value);
void Load(char **buf_p);
};
class GhostTexture
{
public:
Container<ParticleEmitter *> m_emitterList;
int m_width;
int m_height;
image_t *m_image;
unsigned int *m_texture;
str m_name;
qboolean m_isburn;
qboolean m_isfade;
int m_faderate;
int m_burnrate;
public:
GhostTexture();
void Update();
void SetTexel(int x, int y, unsigned int color);
void Burn();
void GenerateLightning(Vector p1, Vector p2, int color, float angleVar, int numSubdivisions, int maxSubdivisions);
Vector RotateVector(Vector v, float angle);
void ClipAndDrawLine(Vector p0, Vector p1, int color);
outcode ComputeOutCode(int x, int y, int xmin, int xmax, int ymin, int ymax);
};
class GhostManager
{
public:
Container<GhostTexture *> m_textureList;
};

View file

@ -3388,4 +3388,99 @@ void R_SkinList_f( void ) {
ri.Printf (PRINT_ALL, "------------------\n");
}
//
// OPENMOHAA-specific stuff
//
image_t* R_RefreshImageFile(const char* name, imgType_t type, imgFlags_t flags) {
// FIXME: unimplemented (GL2)
return NULL;
}
/*
================
R_ImageExists
================
*/
qboolean R_ImageExists(const char* name) {
image_t* image;
long int hash;
if (name)
{
hash = generateHashValue(name);
image = hashTable[hash];
if (hash)
{
for (; image != NULL; image = image->next)
{
if (!strcmp(name, image->imgName)) {
return qtrue;
}
}
}
}
return qfalse;
}
/*
===============
R_DumpTextureMemory
===============
*/
void R_DumpTextureMemory() {
int i;
char str_buffer[32];
char* Label1, * Label2;
fileHandle_t stat_file;
stat_file = ri.FS_OpenFileWrite("textureuse.csv");
Label1 = "Texture Name,";
ri.FS_Write(Label1, strlen(Label1), stat_file);
Label2 = "Size (kb),";
ri.FS_Write(Label2, strlen(Label2), stat_file);
Label1 = "Num Uses,";
ri.FS_Write(Label1, strlen(Label1), stat_file);
Label2 = "Miplevels\n";
ri.FS_Write(Label2, strlen(Label2), stat_file);
for (i = 0; i < tr.numImages; i++) {
image_t* image = tr.images[i];
ri.FS_Write(image->imgName, strlen(image->imgName), stat_file);
ri.FS_Write(", ", 2, stat_file);
// Write the number of bytes (in KiB)
Q_snprintf(str_buffer, sizeof(str_buffer), "%d", image->bytesUsed >> 10);
ri.FS_Write(str_buffer, strlen(str_buffer), stat_file);
ri.FS_Write(", ", 2, stat_file);
// Write the sequence
Q_snprintf(str_buffer, sizeof(str_buffer), "%d", image->r_sequence);
ri.FS_Write(str_buffer, strlen(str_buffer), stat_file);
ri.FS_Write(", ", 2, stat_file);
}
}
/*
===============
R_CountTextureMemory
===============
*/
int R_CountTextureMemory() {
int total_bytes;
int i;
R_DumpTextureMemory();
total_bytes = 0;
for (i = 0; i < tr.numImages; i++) {
total_bytes = tr.images[i]->bytesUsed;
}
return total_bytes;
}

View file

@ -236,6 +236,86 @@ int max_polys;
cvar_t *r_maxpolyverts;
int max_polyverts;
//
// OPENMOHAA-specific stuff
//=========================
int r_sequencenumber;
// DRAWING
cvar_t *r_drawentitypoly;
cvar_t *r_drawstaticmodels;
cvar_t *r_drawstaticmodelpoly;
cvar_t *r_drawstaticdecals;
cvar_t *r_drawterrain;
cvar_t *r_drawsprites;
cvar_t *r_drawspherelights;
cvar_t *r_numdebuglines;
cvar_t *r_stipplelines;
cvar_t *r_debuglines_depthmask;
cvar_t *r_maxpolys;
int max_polys;
cvar_t *r_maxpolyverts;
int max_polyverts;
cvar_t* r_maxtermarks;
int max_termarks;
cvar_t* r_skyportal;
cvar_t* r_skyportal_origin;
cvar_t* r_lightcoronasize;
// LOD
cvar_t* r_staticlod;
cvar_t* r_lodscale;
cvar_t* r_lodcap;
cvar_t* r_lodviewmodelcap;
cvar_t* r_uselod;
cvar_t* lod_LOD;
cvar_t* lod_minLOD;
cvar_t* lod_maxLOD;
cvar_t* lod_LOD_slider;
cvar_t* lod_curve_0_val;
cvar_t* lod_curve_1_val;
cvar_t* lod_curve_2_val;
cvar_t* lod_curve_3_val;
cvar_t* lod_curve_4_val;
cvar_t* lod_edit_0;
cvar_t* lod_edit_1;
cvar_t* lod_edit_2;
cvar_t* lod_edit_3;
cvar_t* lod_edit_4;
cvar_t* lod_curve_0_slider;
cvar_t* lod_curve_1_slider;
cvar_t* lod_curve_2_slider;
cvar_t* lod_curve_3_slider;
cvar_t* lod_curve_4_slider;
cvar_t* lod_pitch_val;
cvar_t* lod_zee_val;
cvar_t* lod_mesh;
cvar_t* lod_meshname;
cvar_t* lod_tikiname;
cvar_t* lod_metric;
cvar_t* lod_tris;
cvar_t* lod_position;
cvar_t* lod_save;
cvar_t* lod_tool;
// Utils
cvar_t* r_developer;
cvar_t* r_fps;
cvar_t* r_showstaticbboxes;
cvar_t* r_showcull;
cvar_t* r_showlod;
cvar_t* r_showstaticlod;
//=========================
/*
** InitOpenGL
**
@ -1452,6 +1532,77 @@ void R_Register( void )
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f );
//
// OPENMOHAA-specific stuff
//
// Draw
r_drawentitypoly = ri.Cvar_Get("r_drawentitypoly", "1", CVAR_CHEAT);
r_drawstaticmodels = ri.Cvar_Get("r_drawstaticmodels", "1", CVAR_CHEAT);
r_drawstaticmodelpoly = ri.Cvar_Get("r_drawstaticmodelpoly", "1", CVAR_CHEAT);
r_drawstaticdecals = ri.Cvar_Get("r_drawstaticdecals", "0", 0);
r_drawterrain = ri.Cvar_Get("r_drawterrain", "1", CVAR_CHEAT);
r_drawsprites = ri.Cvar_Get("r_drawsprites", "1", CVAR_CHEAT);
r_drawspherelights = ri.Cvar_Get("r_drawspherelights", "1", CVAR_CHEAT);
r_debuglines_depthmask = ri.Cvar_Get("r_debuglines_depthmask", "0", CVAR_ARCHIVE);
r_stipplelines = ri.Cvar_Get("r_stipplelines", "1", CVAR_ARCHIVE);
r_numdebuglines = ri.Cvar_Get("g_numdebuglines", "4096", CVAR_LATCH);
r_maxtermarks = ri.Cvar_Get("r_maxtermarks", va("%d", MAX_TERMARKS), 0);
r_skyportal = ri.Cvar_Get("r_skyportal", "0", 0);
r_skyportal_origin = ri.Cvar_Get("r_skyportal_origin", "0 0 0", 0);
r_lightcoronasize = ri.Cvar_Get("r_lightcoronasize", ".1", CVAR_ARCHIVE);
// LOD
r_staticlod = ri.Cvar_Get("r_staticlod", "1", CVAR_CHEAT);
r_lodscale = ri.Cvar_Get("r_lodscale", "5", CVAR_ARCHIVE);
r_lodcap = ri.Cvar_Get("r_lodcap", "0.35", CVAR_ARCHIVE);
r_lodviewmodelcap = ri.Cvar_Get("r_lodviewmodelcap", "0.25", CVAR_ARCHIVE);
r_uselod = ri.Cvar_Get("r_uselod", "1", CVAR_TEMP);
lod_LOD = ri.Cvar_Get("lod_LOD", "0", CVAR_TEMP);
lod_minLOD = ri.Cvar_Get("lod_minLOD", "1.0", CVAR_TEMP);
lod_maxLOD = ri.Cvar_Get("lod_maxLOD", "0.3", CVAR_TEMP);
lod_LOD_slider = ri.Cvar_Get("lod_LOD_slider", "0.5", CVAR_TEMP);
lod_edit_0 = ri.Cvar_Get("lod_edit_0", "0", CVAR_TEMP);
lod_edit_1 = ri.Cvar_Get("lod_edit_1", "0", CVAR_TEMP);
lod_edit_2 = ri.Cvar_Get("lod_edit_2", "0", CVAR_TEMP);
lod_edit_3 = ri.Cvar_Get("lod_edit_3", "0", CVAR_TEMP);
lod_edit_4 = ri.Cvar_Get("lod_edit_4", "0", CVAR_TEMP);
lod_curve_0_val = ri.Cvar_Get("lod_curve_0_val", "0", CVAR_TEMP);
lod_curve_1_val = ri.Cvar_Get("lod_curve_1_val", "0", CVAR_TEMP);
lod_curve_2_val = ri.Cvar_Get("lod_curve_2_val", "0", CVAR_TEMP);
lod_curve_3_val = ri.Cvar_Get("lod_curve_3_val", "0", CVAR_TEMP);
lod_curve_4_val = ri.Cvar_Get("lod_curve_4_val", "0", CVAR_TEMP);
lod_curve_0_slider = ri.Cvar_Get("lod_curve_0_slider", "0", CVAR_TEMP);
lod_curve_1_slider = ri.Cvar_Get("lod_curve_1_slider", "0", CVAR_TEMP);
lod_curve_2_slider = ri.Cvar_Get("lod_curve_2_slider", "0", CVAR_TEMP);
lod_curve_3_slider = ri.Cvar_Get("lod_curve_3_slider", "0", CVAR_TEMP);
lod_curve_4_slider = ri.Cvar_Get("lod_curve_4_slider", "0", CVAR_TEMP);
lod_pitch_val = ri.Cvar_Get("lod_pitch_val", "0", CVAR_TEMP);
lod_zee_val = ri.Cvar_Get("lod_zee_val", "0", CVAR_TEMP);
lod_mesh = ri.Cvar_Get("lod_mesh", "0", CVAR_TEMP);
lod_meshname = ri.Cvar_Get("lod_meshname", "", CVAR_TEMP);
lod_tikiname = ri.Cvar_Get("lod_tikiname", "", CVAR_TEMP);
lod_metric = ri.Cvar_Get("lod_metric", "0.0", CVAR_TEMP);
lod_tris = ri.Cvar_Get("lod_tris", "", CVAR_TEMP);
lod_save = ri.Cvar_Get("lod_save", "0", CVAR_TEMP);
lod_position = ri.Cvar_Get("lod_position", "0 0 0", CVAR_TEMP);
lod_tool = ri.Cvar_Get("lod_tool", "0", CVAR_TEMP);
// Utils
r_fps = ri.Cvar_Get("fps", "0", 0);
r_developer = ri.Cvar_Get("developer", "", 0);
r_showstaticbboxes = ri.Cvar_Get("r_showstaticbboxes", "0", CVAR_CHEAT);
r_showcull = ri.Cvar_Get("r_showcull", "0", CVAR_CHEAT);
r_showlod = ri.Cvar_Get("r_showlod", "0", CVAR_TEMP);
r_showstaticlod = ri.Cvar_Get("r_showstaticlod", "0", CVAR_TEMP);
}
void R_InitQueries(void)
@ -1628,6 +1779,28 @@ void RE_Shutdown( qboolean destroyWindow ) {
tr.registered = qfalse;
}
//
// OPENMOHAA-specific stuff
//=========================
/*
** RE_BeginRegistration
*/
void RE_BeginRegistration(glconfig_t* glconfigOut) {
R_Init();
*glconfigOut = glConfig;
R_IssuePendingRenderCommands();
tr.viewCluster = -1; // force markleafs to regenerate
R_ClearFlares();
RE_ClearScene();
tr.registered = qtrue;
}
//=========================
/*
=============
@ -1643,6 +1816,52 @@ void RE_EndRegistration( void ) {
}
}
//
// OPENMOHAA-specific stuff
//=========================
/*
==================
R_SetMode
==================
*/
qboolean R_SetMode(int mode, const glconfig_t* glConfig) {
// FIXME: unimplemented (GL2)
ri.Printf(PRINT_WARNING, "R_SetMode is unimplemented. To change the video mode, set the \"r_mode\" variable and execute the \"vid_restart\" command.\n");
return qfalse;
}
/*
==================
R_SetFullscreen
==================
*/
void R_SetFullscreen(qboolean fullscreen) {
// FIXME: unimplemented (GL2)
ri.Printf(PRINT_WARNING, "R_SetFullscreen is unimplemented. To change the fullscreen mode, set the \"r_fullscreen\" variable and execute the \"vid_restart\" command.\n");
}
/*
=============
RE_SetRenderTime
=============
*/
void RE_SetRenderTime(int t) {
backEnd.refdef.floatTime = (long double)t / 1000.0;
R_UpdateGhostTextures();
}
/*
==================
RE_GetGraphicsInfo
==================
*/
const char* RE_GetGraphicsInfo() {
// FIXME: unimplemented (GL2)
// Looks like it's unused anyway
}
//=========================
/*
@@@@@@@@@@@@@@@@@@@@@
@ -1708,5 +1927,70 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
re.TakeVideoFrame = RE_TakeVideoFrame;
//
// After ioquake3 imports
//
re.FreeModels = RE_FreeModels;
re.EndRegistration = RE_EndRegistration;
re.SpawnEffectModel = RE_SpawnEffectModel;
re.RegisterServerModel = RE_RegisterServerModel;
re.UnregisterServerModel = RE_UnregisterServerModel;
re.RefreshShaderNoMip = RE_RefreshShaderNoMip;
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
re.MapVersion = RE_MapVersion;
re.LoadFont = R_LoadFont;
re.MarkFragmentsForInlineModel = R_MarkFragmentsForInlineModel;
re.GetInlineModelBounds = R_GetInlineModelBounds;
re.GetLightingForDecal = R_GetLightingForDecal;
re.GetLightingForSmoke = R_GetLightingForSmoke;
re.R_GatherLightSources = R_GatherLightSources;
re.ModelRadius = R_ModelRadius;
re.AddRefSpriteToScene = RE_AddRefSpriteToScene;
re.AddTerrainMarkToScene = RE_AddTerrainMarkToScene;
re.GetRenderEntity = RE_GetRenderEntity;
re.SavePerformanceCounters = R_SavePerformanceCounters;
re.R_Model_GetHandle = R_Model_GetHandle;
re.SetColor = Draw_SetColor;
re.DrawStretchPic = Draw_StretchPic;
re.DrawStretchPic2 = Draw_StretchPic2;
re.DrawStretchRaw = RE_StretchRaw;
re.DebugLine = R_DebugLine;
re.DrawTilePic = Draw_TilePic;
re.DrawTilePicOffset = Draw_TilePicOffset;
re.DrawTrianglePic = Draw_TrianglePic;
re.DrawBox = DrawBox;
re.AddBox = AddBox;
re.Set2DWindow = Set2DWindow;
re.Scissor = RE_Scissor;
re.DrawLineLoop = DrawLineLoop;
re.DrawString = R_DrawString;
re.GetFontHeight = R_GetFontHeight;
re.GetFontStringWidth = R_GetFontStringWidth;
re.SwipeBegin = RE_SwipeBegin;
re.SwipeEnd = RE_SwipeEnd;
re.SetRenderTime = RE_SetRenderTime;
re.Noise = R_NoiseGet4f;
re.SetMode = R_SetMode;
re.SetFullscreen = R_SetFullscreen;
re.GetShaderHeight = RE_GetShaderHeight;
re.GetShaderWidth = RE_GetShaderWidth;
re.GetShaderName = RE_GetShaderName;
re.GetModelName = RE_GetModelName;
re.GetGraphicsInfo = RE_GetGraphicsInfo;
re.ForceUpdatePose = RE_ForceUpdatePose;
re.TIKI_Orientation = RE_TIKI_Orientation;
re.TIKI_IsOnGround = RE_TIKI_IsOnGround;
re.SetFrameNumber = RE_SetFrameNumber;
re.ImageExists = R_ImageExists;
re.CountTextureMemory = R_CountTextureMemory;
return &re;
}

View file

@ -509,3 +509,27 @@ int R_CubemapForPoint( vec3_t point )
return cubemapIndex + 1;
}
//
// OPENMOHAA-specific stuff
//
/*
===============
R_GetLightingForDecal
===============
*/
void R_GetLightingForDecal(vec3_t vLight, const vec3_t vFacing, const vec3_t vOrigin)
{
// FIXME: unimplemented (GL2)
}
/*
===============
R_GetLightingForSmoke
===============
*/
void R_GetLightingForSmoke(vec3_t vLight, const vec3_t vOrigin)
{
// FIXME: unimplemented (GL2)
}

File diff suppressed because it is too large Load diff

View file

@ -1729,6 +1729,220 @@ void R_DebugGraphics( void ) {
ri.CM_DrawDebugSurface( R_DebugPolygon );
}
#define CIRCLE_LENGTH 25
/*
================
R_DebugCircle
================
*/
void R_DebugCircle(const vec3_t org, float radius, float r, float g, float b, float alpha, qboolean horizontal) {
int i;
float ang;
debugline_t* line;
vec3_t forward, right;
vec3_t pos, lastpos;
if (!ri.DebugLines || !ri.numDebugLines) {
return;
}
if (horizontal)
{
VectorSet(forward, 1, 0, 0);
VectorSet(right, 0, 1, 0);
}
else
{
VectorCopy(tr.refdef.viewaxis[1], right);
VectorCopy(tr.refdef.viewaxis[2], forward);
}
VectorClear(pos);
VectorClear(lastpos);
for (i = 0; i < CIRCLE_LENGTH; i++) {
VectorCopy(pos, lastpos);
ang = DEG2RAD((float)(i * 15));
pos[0] = (org[0] + sin(ang) * radius * forward[0]) +
cos(ang) * radius * right[0];
pos[1] = (org[1] + sin(ang) * radius * forward[1]) +
cos(ang) * radius * right[1];
pos[2] = (org[2] + sin(ang) * radius * forward[2]) +
cos(ang) * radius * right[2];
if (i > 0)
{
if (*ri.numDebugLines >= r_numdebuglines->integer) {
ri.Printf(PRINT_ALL, "R_DebugCircle: Exceeded MAX_DEBUG_LINES\n");
return;
}
line = &(*ri.DebugLines)[*ri.numDebugLines];
(*ri.numDebugLines)++;
VectorCopy(lastpos, line->start);
VectorCopy(pos, line->end);
VectorSet(line->color, r, g, b);
line->alpha = alpha;
line->width = 1.0;
line->factor = 1;
line->pattern = -1;
}
}
}
/*
================
R_DebugLine
================
*/
void R_DebugLine(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha) {
debugline_t* line;
if (!ri.DebugLines || !ri.numDebugLines) {
return;
}
if (*ri.numDebugLines >= r_numdebuglines->integer) {
ri.Printf(PRINT_ALL, "R_DebugLine: Exceeded MAX_DEBUG_LINES\n");
return;
}
line = &(*ri.DebugLines)[*ri.numDebugLines];
(*ri.numDebugLines)++;
VectorCopy(start, line->start);
VectorCopy(end, line->end);
VectorSet(line->color, r, g, b);
line->alpha = alpha;
line->width = 1.0;
line->factor = 1;
line->pattern = -1;
}
/*
================
R_DrawDebugLines
================
*/
void R_DrawDebugLines(void) {
debugline_t* line;
int i;
float width;
int factor;
unsigned short pattern;
if (!ri.DebugLines || !ri.numDebugLines) {
return;
}
if (!*ri.numDebugLines) {
return;
}
if (tr.refdef.rdflags & RDF_NOWORLDMODEL) {
return;
}
if (tr.viewParms.isPortalSky) {
return;
}
R_IssuePendingRenderCommands();
GL_BindToTMU(tr.whiteImage, 0);
if (r_debuglines_depthmask->integer) {
GL_State(GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE);
} else {
GL_State(GLS_POLYMODE_LINE);
}
qglDisableClientState(GL_COLOR_ARRAY);
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
width = 1.0;
factor = 4;
pattern = -1;
if (r_stipplelines->integer)
{
qglEnable(GL_LINE_STIPPLE);
qglLineStipple(4, -1);
qglLineWidth(1.0f);
}
qglBegin(GL_LINES);
for (i = 0; i < *ri.numDebugLines; i++) {
line = &(*ri.DebugLines)[i];
if (r_stipplelines->integer) {
if (line->width != width || line->factor != factor || line->pattern != pattern) {
qglEnd();
qglLineStipple(line->factor, line->pattern);
qglLineWidth(line->width);
qglBegin(GL_LINES);
factor = line->factor;
width = line->width;
pattern = line->pattern;
}
}
qglColor4f(line->color[0], line->color[1], line->color[2], line->alpha);
qglVertex3fv(line->start);
qglVertex3fv(line->end);
}
qglEnd();
if (r_stipplelines->integer)
{
qglDisable(GL_LINE_STIPPLE);
qglLineStipple(1, -1);
qglLineWidth(1.0);
}
qglDepthRange(0.0, 1.0);
}
/*
================
R_DrawDebugLines
================
*/
void R_DrawDebugStrings(void) {
int i;
debugstring_t* string;
if (!ri.DebugStrings || !ri.numDebugStrings) {
return;
}
if (!*ri.numDebugStrings) {
return;
}
if (tr.refdef.rdflags & RDF_NOWORLDMODEL) {
return;
}
if (tr.viewParms.isPortalSky) {
return;
}
for (i = 0; i < *ri.numDebugStrings; i++) {
string = &(*ri.DebugStrings)[i];
R_DrawFloatingString(
tr.pFontDebugStrings,
string->szText,
string->pos,
string->color,
string->scale,
64
);
}
}
/*
================
@ -2672,3 +2886,207 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
if (!subscene)
RE_EndScene();
}
//
// OPENMOHAA-specific stuff
//
/*
=================
R_RotateForStaticModel
Generates an orientation for a static model and viewParms
=================
*/
void R_RotateForStaticModel( cStaticModelUnpacked_t *SM, const viewParms_t *viewParms,
orientationr_t *ori ) {
float glMatrix[16];
vec3_t delta;
float tiki_scale;
tiki_scale = SM->tiki->load_scale * SM->scale;
VectorCopy( SM->origin, ori->origin );
VectorCopy( SM->axis[0], ori->axis[0] );
VectorCopy( SM->axis[1], ori->axis[1] );
VectorCopy( SM->axis[2], ori->axis[2] );
glMatrix[0] = ori->axis[0][0] * tiki_scale;
glMatrix[4] = ori->axis[1][0] * tiki_scale;
glMatrix[8] = ori->axis[2][0] * tiki_scale;
glMatrix[12] = ori->origin[0];
glMatrix[1] = ori->axis[0][1] * tiki_scale;
glMatrix[5] = ori->axis[1][1] * tiki_scale;
glMatrix[9] = ori->axis[2][1] * tiki_scale;
glMatrix[13] = ori->origin[1];
glMatrix[2] = ori->axis[0][2] * tiki_scale;
glMatrix[6] = ori->axis[1][2] * tiki_scale;
glMatrix[10] = ori->axis[2][2] * tiki_scale;
glMatrix[14] = ori->origin[2];
glMatrix[3] = 0;
glMatrix[7] = 0;
glMatrix[11] = 0;
glMatrix[15] = 1;
myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, ori->modelMatrix );
// calculate the viewer origin in the model's space
// needed for fog, specular, and environment mapping
VectorSubtract( viewParms->or.origin, ori->origin, delta );
ori->viewOrigin[0] = DotProduct( delta, ori->axis[0] );
ori->viewOrigin[1] = DotProduct( delta, ori->axis[1] );
ori->viewOrigin[2] = DotProduct( delta, ori->axis[2] );
}
int R_DistanceCullLocalPointAndRadius(float fDist, const vec3_t pt, float radius) {
vec3_t transformed;
R_LocalPointToWorld(pt, transformed);
return R_DistanceCullPointAndRadius(fDist, transformed, radius);
}
int R_DistanceCullPointAndRadius(float fDist, const vec3_t pt, float radius) {
if (!r_nocull->integer)
{
vec3_t vDelta;
float fLengthSquared;
float fTotalDistSquared;
VectorSubtract(pt, tr.viewParms.or.origin, vDelta);
fLengthSquared = VectorLengthSquared(vDelta);
fTotalDistSquared = Square(fDist + radius);
if (Square(fDist + radius) < Square(vDelta[2]) + fLengthSquared) {
return CULL_OUT;
} else if (Square(fDist - radius) > Square(vDelta[2]) + fLengthSquared) {
return CULL_IN;
}
}
return CULL_CLIP;
}
/*
** SurfIsOffscreen
**
** Determines if a surface is completely offscreen.
*/
qboolean SurfIsOffscreen2(const srfBspSurface_t* surface, shader_t* shader, int entityNum) {
float shortest = 100000000;
int numTriangles;
qboolean doRange;
orientationr_t surfOr;
unsigned int* indices;
vec4_t clip, eye;
int i;
unsigned int pointOr = 0;
unsigned int pointAnd = (unsigned int)~0;
if (surface->surfaceType != SF_FACE) {
ri.Printf(PRINT_WARNING, "WARNING: SurfIsOffscreen called on non-bmodel!\n");
return qfalse;
}
if ( glConfig.smpActive ) { // FIXME! we can't do RB_BeginSurface/RB_EndSurface stuff with smp!
return qfalse;
}
if (entityNum == ENTITYNUM_WORLD) {
surfOr = tr.viewParms.world;
} else {
R_RotateForEntity(&tr.refdef.entities[entityNum], &tr.viewParms, &surfOr);
}
for ( i = 0; i < surface->numVerts; i++ )
{
int j;
unsigned int pointFlags = 0;
R_TransformModelToClip( surface->verts[i].xyz, surfOr.modelMatrix, tr.viewParms.projectionMatrix, eye, clip );
for ( j = 0; j < 3; j++ )
{
if ( clip[j] >= clip[3] )
{
pointFlags |= (1 << (j*2));
}
else if ( clip[j] <= -clip[3] )
{
pointFlags |= ( 1 << (j*2+1));
}
}
pointAnd &= pointFlags;
pointOr |= pointFlags;
}
// trivially reject
if ( pointAnd )
{
return qtrue;
}
// determine if this surface is backfaced and also determine the distance
// to the nearest vertex so we can cull based on portal range. Culling
// based on vertex distance isn't 100% correct (we should be checking for
// range to the surface), but it's good enough for the types of portals
// we have in the game right now.
numTriangles = surface->numIndexes / 3;
for ( i = 0; i < surface->numIndexes; i += 3 )
{
vec3_t normal;
float dot;
float len;
unsigned* indices;
indices = surface->indexes; // (unsigned*)(((char*)surface) + surface->ofsIndices);
VectorSubtract( surface->verts[indices[i]].xyz, surfOr.viewOrigin, normal);
if (shader->fDistRange > 0) {
len = VectorLengthSquared(normal); // lose the sqrt
if (len < shortest)
{
shortest = len;
}
}
if ( ( dot = DotProduct( normal, surface->cullPlane.normal ) ) >= 0 )
{
numTriangles--;
}
}
if ( !numTriangles )
{
return qtrue;
}
if (shader->fDistRange > 0.0)
{
if (shortest > Square(shader->fDistRange))
{
return qtrue;
}
}
return qfalse;
}
static qboolean DrawSurfIsOffscreen(drawSurf_t* drawSurf) {
// FIXME: unimplemented (GL2)
#if 0
int entityNum;
shader_t* shader;
int dlighted;
qboolean bStaticModel;
R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &dlighted, &bStaticModel);
return SurfIsOffscreen2((srfBspSurface_t*)drawSurf->surface, shader, entityNum);
#endif
}

View file

@ -469,7 +469,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
return returnedFragments;
}
int R_MarkFragmentsForInlineModel(clipHandle_t bmodel, const vec3_t vAngles, const vec3_t vOrigin, int numPoints,
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t* fragmentBuffer, float fRadiusSquared)
{
// FIXME: unimplemented (GL2)
return 0;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,17 @@ int r_firstScenePoly;
int r_numpolyverts;
//
// OPENMOHAA-specific stuff
//=========================
int r_numsprites;
int r_firstSceneSprite;
int r_numtermarks;
int r_firstSceneTerMark;
//=========================
/*
====================
@ -57,6 +68,16 @@ void R_InitNextFrame( void ) {
r_firstScenePoly = 0;
r_numpolyverts = 0;
//
// OPENMOHAA-specific stuff
//
r_numsprites = 0;
r_firstSceneSprite = 0;
r_numtermarks = 0;
r_firstSceneTerMark = 0;
}
@ -571,3 +592,134 @@ void RE_RenderScene( const refdef_t *fd ) {
tr.frontEndMsec += ri.Milliseconds() - startTime;
}
//
// OPENMOHAA-specific stuff
//
void RE_AddRefSpriteToScene(const refEntity_t* ent) {
refSprite_t* spr;
int i;
if (!tr.registered) {
return;
}
if (r_numsprites >= MAX_SPRITES) {
return;
}
spr = &backEndData->sprites[r_numsprites];
VectorCopy(ent->origin, spr->origin);
spr->surftype = SF_SPRITE;
spr->hModel = ent->hModel;
spr->scale = ent->scale;
spr->renderfx = ent->renderfx;
spr->shaderTime = ent->shaderTime;
AxisCopy(ent->axis, spr->axis);
for (i = 0; i < 4; ++i) {
spr->shaderRGBA[i] = ent->shaderRGBA[i];
}
++r_numsprites;
}
/*
=====================
RE_AddPolyToScene
=====================
*/
qboolean RE_AddPolyToScene2(qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx) {
srfPoly_t *poly;
if ( !tr.registered ) {
return qfalse;
}
if (numVerts + r_numpolyverts > max_polyverts || r_numpolys >= max_polys) {
ri.Printf(PRINT_WARNING, "Exceeded MAX POLYS\n");
return qfalse;
}
poly = &backEndData->polys[r_numpolys];
poly->surfaceType = SF_POLY;
poly->hShader = hShader;
poly->numVerts = numVerts;
poly->verts = &backEndData->polyVerts[r_numpolyverts];
poly->renderfx = renderfx;
Com_Memcpy(poly->verts, verts, sizeof(polyVert_t) * numVerts);
++r_numpolys;
r_numpolyverts += numVerts;
return qtrue;
}
/*
=====================
R_AddTerrainMarkSurfaces
=====================
*/
void R_AddTerrainMarkSurfaces(void) {
srfMarkFragment_t* terMark;
int j;
shader_t* shader;
for (j = 0; j < tr.refdef.numTerMarks; j++)
{
terMark = &tr.refdef.terMarks[j];
shader = R_GetShaderByHandle(terMark->surfaceType);
terMark->surfaceType = SF_MARK_FRAG;
R_AddDrawSurf(&terMark->surfaceType, shader, 0, 0, 0, 0);
}
}
/*
=====================
RE_AddTerrainMarkToScene
=====================
*/
void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx) {
srfMarkFragment_t* terMark;
if (!tr.registered) {
return;
}
if (numVerts + r_numpolyverts > max_polyverts || r_numtermarks >= max_termarks) {
ri.Printf(PRINT_WARNING, "Exceeded MAX TERRAIN MARKS\n");
return;
}
terMark = &backEndData->terMarks[r_numtermarks];
terMark->surfaceType = hShader;
terMark->iIndex = iTerrainIndex;
terMark->numVerts = numVerts;
terMark->verts = &backEndData->polyVerts[r_numpolyverts];
memcpy(terMark->verts, verts, sizeof(polyVert_t) * numVerts);
r_numtermarks++;
r_numpolyverts += numVerts;
}
//=================================================================================
/*
=====================
RE_GetRenderEntity
=====================
*/
refEntity_t* RE_GetRenderEntity(int entityNumber) {
int i;
for (i = 0; i < r_numentities; i++) {
if (backEndData->entities[i].e.entityNumber == entityNumber) {
return &backEndData->entities[i].e;
}
}
return NULL;
}

View file

@ -4025,3 +4025,38 @@ void R_InitShaders( void ) {
CreateExternalShaders();
}
qhandle_t RE_RefreshShaderNoMip(const char* name) {
shader_t* sh;
char strippedName[64];
int hash;
if (!name || !*name) {
return 0;
}
COM_StripExtension(name, strippedName, sizeof(strippedName));
hash = generateHashValue(strippedName, FILE_HASH_SIZE);
for (sh = hashTable[hash]; sh; sh = sh->next) {
if (Q_stricmp(sh->name, strippedName) == 0) {
image_t* image;
image = sh->stages[0]->bundle[0].image[0];
if (image) {
sh->stages[0]->bundle[0].image[0] = R_RefreshImageFile(image->imgName, IMGTYPE_COLORALPHA, image->flags);
}
return sh->index;
}
}
sh = R_FindShader(name, -4, qfalse);
if (sh->defaultShader) {
return 0;
}
return sh->index;
}

View file

@ -0,0 +1,254 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sky_portal.cpp: sky portal
#include "tr_local.h"
/*
=================
R_Sky_Init
=================
*/
void R_Sky_Init()
{
tr.viewParms.isPortalSky = qfalse;
tr.portalsky.numSurfs = 0;
}
/*
=================
R_Sky_Reset
=================
*/
void R_Sky_Reset()
{
if (tr.viewParms.isPortalSky) {
return;
}
tr.portalsky.mins[0] = 8192.0;
tr.portalsky.mins[1] = 8192.0;
tr.portalsky.mins[2] = 8192.0;
tr.portalsky.maxs[0] = -8192.0;
tr.portalsky.maxs[1] = -8192.0;
tr.portalsky.maxs[2] = -8192.0;
tr.portalsky.cntNode = 0;
tr.portalsky.numSurfs = 0;
}
/*
=================
R_Sky_AddSurf
=================
*/
void R_Sky_AddSurf(msurface_t *surf)
{
if (tr.viewParms.isPortalSky) {
static int last_sky_warning = 0;
if (tr.refdef.time - 1000 > last_sky_warning) {
ri.Printf(3, "WARNING: sky being drawn in a sky portal! Bad! Bad!\n");
last_sky_warning = tr.refdef.time;
}
return;
}
if (tr.portalsky.numSurfs < 32) {
tr.portalsky.skySurfs[tr.portalsky.numSurfs++] = surf;
}
if (tr.portalsky.cntNode) {
int i;
for (i = 0; i < 3; i++) {
if (tr.portalsky.mins[i] >= tr.portalsky.cntNode->mins[i]) {
tr.portalsky.mins[i] = tr.portalsky.cntNode->mins[i];
}
if (tr.portalsky.maxs[i] >= tr.portalsky.cntNode->maxs[i]) {
tr.portalsky.maxs[i] = tr.portalsky.cntNode->maxs[i];
}
}
}
}
/*
=================
R_Sky_Render
=================
*/
void R_Sky_Render()
{
int i;
viewParms_t newParms, oldParms;
mnode_t *leaf;
if (!tr.portalsky.numSurfs) {
return;
}
if (!tr.refdef.sky_portal) {
return;
}
if (tr.skyRendered) {
// already rendered
return;
}
if (tr.viewParms.isPortalSky) {
return;
}
for (i = 0; i < tr.portalsky.numSurfs; i++) {
if (!SurfIsOffscreen2(
(const srfBspSurface_t*)tr.portalsky.skySurfs[i]->data,
tr.portalsky.skySurfs[i]->shader,
ENTITYNUM_WORLD
)) {
break;
}
}
if (i == tr.portalsky.numSurfs) {
return;
}
oldParms = tr.viewParms;
newParms = tr.viewParms;
if (r_skyportal->integer) {
if (sscanf(
r_skyportal_origin->string,
"%f %f %f",
&newParms.or.origin[0],
&newParms.or.origin[1],
&newParms.or.origin[2]
)
!= 3) {
ri.Printf(PRINT_WARNING, "WARNING: Invalid sky portal origin: %s\n", r_skyportal_origin->string);
return;
}
} else {
VectorCopy(tr.refdef.sky_origin, newParms.or.origin);
MatrixMultiply(newParms.or.axis, tr.refdef.sky_axis, newParms.or.axis);
}
VectorCopy(newParms.or.origin, newParms.pvsOrigin);
newParms.isPortalSky = qtrue;
newParms.farplane_distance = tr.refdef.skybox_farplane;
newParms.renderTerrain = tr.refdef.render_terrain;
if (oldParms.farplane_bias == 0.0 || oldParms.farplane_distance == 0.0) {
newParms.farplane_bias = 0.0;
} else {
newParms.farplane_bias = newParms.farplane_distance / oldParms.farplane_distance * oldParms.farplane_bias;
}
leaf = R_PointInLeaf(newParms.pvsOrigin);
if (leaf) {
R_RenderView(&newParms);
}
tr.viewParms = oldParms;
tr.portalsky.numSurfs = 0;
tr.skyRendered = qtrue;
R_RotateForViewer();
R_SetupFrustum();
}
/*
=================
R_Sky_ChangeFrustum
=================
*/
void R_Sky_ChangeFrustum()
{
cplane_t *frust;
int i;
vec3_t bounds[2];
vec3_t origin;
cplane_t abouts[4];
VectorCopy(tr.portalsky.mins, bounds[0]);
VectorCopy(tr.portalsky.maxs, bounds[1]);
VectorCopy(tr.viewParms.or.origin, origin);
VectorCopy(tr.viewParms.or.axis[2], abouts[0].normal);
VectorNegate(tr.viewParms.or.axis[2], abouts[1].normal);
VectorCopy(tr.viewParms.or.axis[1], abouts[2].normal);
VectorNegate(tr.viewParms.or.axis[1], abouts[3].normal);
for (i = 0; i < 4; i++) {
cplane_t out;
int i1;
float leastfov = 99999;
frust = &tr.viewParms.frustum[i];
abouts[i].dist = DotProduct(tr.viewParms.or.origin, abouts[i].normal);
CrossProduct(frust->normal, abouts[i].normal, out.normal);
for (i1 = 0; i1 < 8; i1++) {
vec3_t point;
vec_t distFromFrustum;
float angle;
int i2;
for (i2 = 0; i2 < 3; i2++) {
point[i2] = bounds[i1 % 3][i2];
}
VectorSubtract(point, origin, point);
distFromFrustum = DotProduct(point, frust->normal);
if (distFromFrustum <= 0) {
break;
}
angle = atan2(DotProduct(point, out.normal), distFromFrustum);
if (angle >= 0) {
angle = RAD2DEG(angle);
if (leastfov > angle) {
leastfov = angle;
}
}
}
if (leastfov > 0 && leastfov < 180) {
RotatePointAroundVector(frust->normal, abouts[i].normal, frust->normal, leastfov);
VectorNormalize(frust->normal);
frust->type = PLANE_NON_AXIAL;
frust->dist = DotProduct(origin, frust->normal);
SetPlaneSignbits(frust);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,218 @@
/*
===========================================================================
Copyright (C) 2010 su44
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sprite.c - MoHAA sprite system
#include "tr_local.h"
/*
=====================
SPR_RegisterSprite
=====================
*/
sprite_t *SPR_RegisterSprite(const char *name)
{
image_t *spriteImage;
shader_t *shader;
sprite_t *spr;
char shadername[256];
COM_StripExtension(name,shadername,sizeof(shadername));
shader = R_FindShader(shadername,-1,qfalse);
if(shader) {
spriteImage = 0;
if(shader->stages[0])
spriteImage = shader->stages[0]->bundle[0].image[0];
if ( !spriteImage ) {
ri.Printf(1, "Could not find image for sprite in shader %s\n", name);
return 0;
}
spr = ri.Hunk_Alloc(sizeof(sprite_t), h_dontcare);
spr->height = spriteImage->height;
spr->width = spriteImage->width;
spr->origin_x = spr->width * 0.5;
spr->origin_y = spr->height * 0.5;
spr->shader = shader;
spr->scale = spr->shader->sprite.scale;
return spr;
}
return 0;
}
static int CullSprite(const vec3_t* points) {
int i, j;
for (i = 0; i < backEnd.viewParms.fog.extrafrustums + 4; i++) {
for (j = 0; j < 4; j++) {
if (DotProduct(points[j], backEnd.viewParms.frustum[i].normal) - backEnd.viewParms.frustum[i].dist > 0.0f) {
break;
}
}
if (j == 4) {
return CULL_CLIP;
}
}
return CULL_IN;
}
/*
=====================
RB_DrawSprite
=====================
*/
void RB_DrawSprite( const refSprite_t *spr ) {
model_t* model;
vec3_t norm;
vec3_t up, right;
vec3_t points[4];
float org_x, org_y;
float scale;
int i;
if (!spr->hModel)
{
ri.Printf(PRINT_WARNING, "No model found for Sprite\n");
return;
}
model = tr.models;
if (spr->hModel > 0 && spr->hModel < tr.numModels) {
model = &tr.models[spr->hModel];
}
scale = spr->scale * model->d.sprite->scale;
switch (model->d.sprite->shader->sprite.type)
{
case SPRITE_PARALLEL_ORIENTED:
{
float invmag;
float cr, sr;
int i;
invmag = 1.0 / sqrt(spr->axis[1][2] * spr->axis[1][2] + spr->axis[1][1] * spr->axis[1][1]);
cr = invmag * spr->axis[1][1];
sr = invmag * spr->axis[1][2];
for (i = 0; i < 3; i++)
{
up[i] = backEnd.viewParms.or.axis[2][i] * cr - backEnd.viewParms.or.axis[1][i] * sr;
right[i] = backEnd.viewParms.or.axis[1][i] * cr + backEnd.viewParms.or.axis[2][i] * sr;
}
}
break;
case SPRITE_PARALLEL:
VectorCopy(backEnd.viewParms.or.axis[2], up);
if (!backEnd.viewParms.isMirror) {
VectorNegate(backEnd.viewParms.or.axis[1], right);
} else {
VectorCopy(backEnd.viewParms.or.axis[1], right);
}
break;
case SPRITE_ORIENTED:
VectorCopy(spr->axis[1], right);
VectorCopy(spr->axis[2], up);
break;
case SPRITE_PARALLEL_UPRIGHT:
VectorCopy(backEnd.viewParms.or.axis[0], norm);
VectorCopy(backEnd.viewParms.or.axis[1], right);
VectorCopy(backEnd.viewParms.or.axis[2], up);
if (backEnd.viewParms.or.axis[0][2] > 0.999) {
return;
} else if (backEnd.viewParms.or.axis[0][2] < -0.999) {
return;
}
VectorSet(up, 0.0f, 0.0f, 1.0f);
VectorSet(right, backEnd.viewParms.or.axis[0][1], -backEnd.viewParms.or.axis[0][0], 0.0f);
VectorNormalize(right);
VectorSet(norm, -right[1], right[0], 0.0f);
break;
}
org_x = model->d.sprite->origin_x * scale;
org_y = model->d.sprite->origin_y * scale;
VectorScale(up, org_y, up);
VectorScale(right, org_x, right);
points[0][0] = spr->origin[0] + up[0] - right[0];
points[1][0] = spr->origin[0] + up[0] + right[0];
points[2][0] = spr->origin[0] - up[0] - right[0];
points[3][0] = spr->origin[0] - up[0] + right[0];
points[0][1] = spr->origin[1] + up[1] - right[1];
points[1][1] = spr->origin[1] + up[1] + right[1];
points[2][1] = spr->origin[1] - up[1] - right[1];
points[3][1] = spr->origin[1] - up[1] + right[1];
points[0][2] = spr->origin[2] + up[2] - right[2];
points[1][2] = spr->origin[2] + up[2] + right[2];
points[2][2] = spr->origin[2] - up[2] - right[2];
points[3][2] = spr->origin[2] - up[2] + right[2];
if (CullSprite(points) == CULL_OUT) {
return;
}
RB_CHECKOVERFLOW(4, 6);
for (i = 0; i < 4; i++) {
tess.color[tess.numVertexes + i][0] = spr->shaderRGBA[0] * 0xffff / 0xff;
tess.color[tess.numVertexes + i][1] = spr->shaderRGBA[1] * 0xffff / 0xff;
tess.color[tess.numVertexes + i][2] = spr->shaderRGBA[2] * 0xffff / 0xff;
tess.color[tess.numVertexes + i][3] = spr->shaderRGBA[3] * 0xffff / 0xff;
}
tess.texCoords[tess.numVertexes][0] = 0.0f;
tess.texCoords[tess.numVertexes][1] = 0.0f;
tess.texCoords[tess.numVertexes + 1][0] = 1.0f;
tess.texCoords[tess.numVertexes + 1][1] = 0.0f;
tess.texCoords[tess.numVertexes + 2][0] = 0.0f;
tess.texCoords[tess.numVertexes + 2][1] = 1.0f;
tess.texCoords[tess.numVertexes + 3][0] = 1.0f;
tess.texCoords[tess.numVertexes + 3][1] = 1.0f;
tess.xyz[tess.numVertexes][0] = points[0][0];
tess.xyz[tess.numVertexes][1] = points[0][1];
tess.xyz[tess.numVertexes][2] = points[0][2];
tess.xyz[tess.numVertexes + 1][0] = points[1][0];
tess.xyz[tess.numVertexes + 1][1] = points[1][1];
tess.xyz[tess.numVertexes + 1][2] = points[1][2];
tess.xyz[tess.numVertexes + 2][0] = points[2][0];
tess.xyz[tess.numVertexes + 2][1] = points[2][1];
tess.xyz[tess.numVertexes + 2][2] = points[2][2];
tess.xyz[tess.numVertexes + 3][0] = points[3][0];
tess.xyz[tess.numVertexes + 3][1] = points[3][1];
tess.xyz[tess.numVertexes + 3][2] = points[3][2];
tess.indexes[tess.numIndexes] = tess.numVertexes + 2;
tess.indexes[tess.numIndexes + 1] = tess.numVertexes + 1;
tess.indexes[tess.numIndexes + 2] = tess.numVertexes;
tess.indexes[tess.numIndexes + 3] = tess.numVertexes + 2;
tess.indexes[tess.numIndexes + 4] = tess.numVertexes + 3;
tess.indexes[tess.numIndexes + 5] = tess.numVertexes + 1;
tess.numVertexes += 4;
tess.numIndexes += 6;
}

View file

@ -0,0 +1,586 @@
/*
===========================================================================
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_staticmodels.cpp -- static model rendering
#include "tr_local.h"
#include "tiki.h"
#define MAX_STATIC_MODELS_SURFS 8192
#define MAX_DISTINCT_STATIC_MODELS 1000
int g_nStaticSurfaces;
staticSurface_t g_staticSurfaces[MAX_STATIC_MODELS_SURFS];
qboolean g_bInfostaticmodels = qfalse;
/*
==============
R_InitStaticModels
==============
*/
void R_InitStaticModels(void)
{
cStaticModelUnpacked_t *pSM;
char szTemp[1024];
skelBoneCache_t bones[128];
float radius;
int i, j, k, l;
g_bInfostaticmodels = qfalse;
if (tr.overbrightShift) {
for (i = 0; i < tr.world->numStaticModelData; i++) {
int r, g, b;
r = (int)((float)tr.world->staticModelData[i * 4] * tr.overbrightMult);
g = (int)((float)tr.world->staticModelData[i * 4 + 1] * tr.overbrightMult);
b = (int)((float)tr.world->staticModelData[i * 4 + 2] * tr.overbrightMult);
if (r > 0xFF || g > 0xFF || b > 0xFF) {
float t;
t = 255.0 / (float)Q_max(r, Q_max(g, b));
r = (int)((float)r * t);
g = (int)((float)g * t);
b = (int)((float)b * t);
}
tr.world->staticModelData[i * 4] = r;
tr.world->staticModelData[i * 4 + 1] = g;
tr.world->staticModelData[i * 4 + 2] = b;
}
}
for (i = 0; i < tr.world->numStaticModels; i++) {
vec3_t mins, maxs;
pSM = &tr.world->staticModels[i];
pSM->bRendered = qfalse;
AngleVectorsLeft(pSM->angles, pSM->axis[0], pSM->axis[1], pSM->axis[2]);
if (!strnicmp(pSM->model, "models", 6)) {
Q_strncpyz(szTemp, pSM->model, sizeof(szTemp));
} else {
Com_sprintf(szTemp, sizeof(szTemp), "models/%s", pSM->model);
}
ri.FS_CanonicalFilename(szTemp);
//const bool exists = ri.TIKI_FindTiki(szTemp) != NULL;
pSM->tiki = ri.TIKI_RegisterTikiFlags(szTemp, qfalse);
if (!pSM->tiki) {
ri.Printf(PRINT_WARNING, "^~^~^: Warning: Cannot Load Static Model %s\n", szTemp);
continue;
}
pSM->radius = ri.TIKI_GlobalRadius(pSM->tiki);
//
// register shaders
//
for (j = 0; j < pSM->tiki->num_surfaces; j++) {
dtikisurface_t *surf = &pSM->tiki->surfaces[j];
for (k = 0; k < surf->numskins; k++) {
if (surf->shader[k][0]) {
shader_t *sh = R_FindShader(surf->shader[k], -1, !(surf->flags & TIKI_SURF_NOMIPMAPS));
surf->hShader[k] = sh->index;
} else {
surf->hShader[k] = 0;
}
}
}
// prepare the skeleton frame for the static model
ri.TIKI_GetSkelAnimFrame(pSM->tiki, bones, &radius, &mins, &maxs);
pSM->cull_radius = radius * pSM->tiki->load_scale * pSM->scale;
// Suggestion:
// It would be cool to have animated static model in the future
// Removed in 2.0
// This only leads to issues where pStaticXyz is not initialized
// and it can occurs if the TIKI model is registered before the static model
//if (exists) {
// continue;
//}
for (j = 0; j < pSM->tiki->numMeshes; j++) {
skelHeaderGame_t *skelmodel = ri.TIKI_GetSkel(pSM->tiki->mesh[j]);
skelSurfaceGame_t *surf;
if (!skelmodel) {
ri.Printf(PRINT_WARNING, "^~^~^: Warning: Missing mesh in Static Model %s\n", skelmodel->name);
continue;
}
surf = skelmodel->pSurfaces;
for (k = 0; k < skelmodel->numSurfaces; k++, surf = surf->pNext) {
byte *buf;
byte *p;
skelWeight_t *weight;
skeletorVertex_t *vert;
if (surf->pStaticXyz) {
continue;
}
// allocate static vectors
p = buf =
(byte *)ri.TIKI_Alloc((sizeof(vec4_t) + sizeof(vec4_t) + sizeof(vec2_t) * 2) * surf->numVerts);
surf->pStaticXyz = (vec4_t *)p;
p += sizeof(vec4_t) * surf->numVerts;
surf->pStaticNormal = (vec4_t *)p;
p += sizeof(vec4_t) * surf->numVerts;
surf->pStaticTexCoords = (vec2_t(*)[2])p;
vert = surf->pVerts;
for (l = 0; l < surf->numVerts; l++) {
int channel;
skelBoneCache_t *bone;
weight = (skelWeight_t *)((byte *)vert + sizeof(skeletorVertex_t)
+ vert->numMorphs * sizeof(skeletorMorph_t));
if (j > 0) {
channel = ri.TIKI_GetLocalChannel(pSM->tiki, skelmodel->pBones[weight->boneIndex].channel);
} else {
channel = weight->boneIndex;
}
bone = &bones[channel];
surf->pStaticXyz[l][0] =
((weight->offset[0] * bone->matrix[0][0] + weight->offset[1] * bone->matrix[1][0]
+ weight->offset[2] * bone->matrix[2][0])
+ bone->offset[0])
* weight->boneWeight;
surf->pStaticXyz[l][1] =
((weight->offset[0] * bone->matrix[0][1] + weight->offset[1] * bone->matrix[1][1]
+ weight->offset[2] * bone->matrix[2][1])
+ bone->offset[1])
* weight->boneWeight;
surf->pStaticXyz[l][2] =
((weight->offset[0] * bone->matrix[0][2] + weight->offset[1] * bone->matrix[1][2]
+ weight->offset[2] * bone->matrix[2][2])
+ bone->offset[2])
* weight->boneWeight;
surf->pStaticXyz[l][3] = 0.f;
surf->pStaticNormal[l][0] = vert->normal[0] * bone->matrix[0][0]
+ vert->normal[1] * bone->matrix[1][0]
+ vert->normal[2] * bone->matrix[2][0];
surf->pStaticNormal[l][1] = vert->normal[0] * bone->matrix[0][1]
+ vert->normal[1] * bone->matrix[1][1]
+ vert->normal[2] * bone->matrix[2][1];
surf->pStaticNormal[l][2] = vert->normal[0] * bone->matrix[0][2]
+ vert->normal[1] * bone->matrix[1][2]
+ vert->normal[2] * bone->matrix[2][2];
surf->pStaticNormal[l][3] = 0.f;
surf->pStaticTexCoords[l][0][0] = vert->texCoords[0];
surf->pStaticTexCoords[l][0][1] = vert->texCoords[1];
surf->pStaticTexCoords[l][1][0] = vert->texCoords[0];
surf->pStaticTexCoords[l][1][1] = vert->texCoords[1];
vert = (skeletorVertex_t *)((byte *)vert + sizeof(skeletorVertex_t)
+ sizeof(skeletorMorph_t) * vert->numMorphs
+ sizeof(skelWeight_t) * vert->numWeights);
}
}
}
}
tr.refdef.numStaticModels = tr.world->numStaticModels;
tr.refdef.staticModels = tr.world->staticModels;
tr.refdef.numStaticModelData = tr.world->numStaticModelData;
tr.refdef.staticModelData = tr.world->staticModelData;
}
/*
==============
R_CullStaticModel
==============
*/
static int R_CullStaticModel(dtiki_t *tiki, float fScale, const vec3_t vLocalOrg)
{
vec3_t bounds[2];
int i;
int cull;
for (i = 0; i < 3; i++) {
bounds[0][i] = vLocalOrg[i] + tiki->a->mins[i] * fScale;
bounds[1][i] = vLocalOrg[i] + tiki->a->maxs[i] * fScale;
}
cull = R_CullLocalBox(bounds);
if (r_showcull->integer & 4) {
float fR, fG, fB;
vec3_t vAngles;
switch (cull) {
case CULL_CLIP:
fR = 1.0f;
fG = 1.0f;
fB = 0.0f;
break;
case CULL_IN:
fR = 0.0f;
fG = 1.0f;
fB = 0.0f;
break;
case CULL_OUT:
fR = 1.0f;
fG = 0.2f;
fB = 0.2f;
for (i = 0; i < 2; i++) {
bounds[0][i] = bounds[0][i] - 16.0;
bounds[1][i] = bounds[1][i] + 16.0;
}
break;
default:
break;
}
MatrixToEulerAngles(tr.or.axis, vAngles);
R_DebugRotatedBBox(tr.or.origin, vAngles, bounds[0], bounds[1], fR, fG, fB, 0.5);
}
switch (cull) {
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
break;
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
break;
case CULL_OUT:
tr.pc.c_box_cull_md3_out++;
break;
}
return cull;
}
/*
==============
R_AddStaticModelSurfaces
==============
*/
void R_AddStaticModelSurfaces(void)
{
cStaticModelUnpacked_t *SM;
int i, j, k;
int ofsStaticData;
int iRadiusCull;
dtiki_t *tiki;
float tiki_scale;
vec3_t tiki_localorigin;
vec3_t tiki_worldorigin;
if (!tr.world->numStaticModels) {
return;
}
tr.shiftedIsStatic = (1 << QSORT_STATICMODEL_SHIFT);
for (i = 0; i < tr.world->numStaticModels; i++) {
SM = &tr.world->staticModels[i];
//if( SM->visCount != tr.visCounts[ tr.visIndex ] ) {
// continue;
//}
tiki = SM->tiki;
if (!tiki) {
continue;
}
tr.currentEntityNum = i;
tr.shiftedEntityNum = i << QSORT_REFENTITYNUM_SHIFT;
R_RotateForStaticModel(SM, &tr.viewParms, &tr.or);
ofsStaticData = 0;
// get the world position
tiki_scale = tiki->load_scale * SM->scale;
VectorScale(tiki->load_origin, tiki_scale, tiki_localorigin);
R_LocalPointToWorld(tiki_localorigin, tiki_worldorigin);
iRadiusCull = R_CullPointAndRadius(tiki_worldorigin, SM->cull_radius);
if (r_showcull->integer & 8) {
switch (iRadiusCull) {
case CULL_IN:
R_DebugCircle(tiki_worldorigin, SM->cull_radius * 1.2, 0.0, 1.0, 0.0, 0.5, 0);
break;
case CULL_OUT:
R_DebugCircle(tiki_worldorigin, SM->cull_radius * 1.4 + 16.0, 1.0, 0.2, 0.2, 0.5, 0);
break;
}
}
if (iRadiusCull != CULL_OUT
&& (iRadiusCull != CULL_CLIP || R_CullStaticModel(SM->tiki, tiki_scale, tiki_localorigin) != CULL_OUT)) {
dtikisurface_t *dsurf;
if (tr.viewParms.isPortal) {
SM->lodpercentage[1] = R_CalcLod(tiki_worldorigin, SM->cull_radius / SM->scale);
} else {
SM->lodpercentage[0] = R_CalcLod(tiki_worldorigin, SM->cull_radius / SM->scale);
}
//
// draw all meshes
//
dsurf = tiki->surfaces;
for (int mesh = 0; mesh < tiki->numMeshes; mesh++) {
skelHeaderGame_t *skelmodel = ri.TIKI_GetSkel(tiki->mesh[mesh]);
skelSurfaceGame_t *surface;
staticSurface_t *s_surface;
shader_t *shader;
float fDist;
vec3_t vDelta;
if (!skelmodel) {
continue;
}
//
// draw all surfaces
//
surface = skelmodel->pSurfaces;
for (j = 0; j < skelmodel->numSurfaces;
j++, ofsStaticData += surface->numVerts, surface = surface->pNext, dsurf++) {
if (g_nStaticSurfaces >= MAX_STATIC_MODELS_SURFS) {
ri.Printf(
PRINT_DEVELOPER,
"^~^~^ ERROR: MAX_STATIC_MODELS_SURFS exceeded - surface of '%s' skipped\n",
tiki->a->name
);
continue;
}
s_surface = &g_staticSurfaces[g_nStaticSurfaces++];
s_surface->ident = SF_TIKI_STATIC;
s_surface->ofsStaticData = ofsStaticData;
s_surface->surface = surface;
s_surface->meshNum = mesh;
shader = tr.shaders[dsurf->hShader[0]];
if (shader->numUnfoggedPasses == 1 && !r_nocull->integer) {
switch (shader->stages[0]->alphaGen) {
case AGEN_DIST_FADE:
if (R_DistanceCullPointAndRadius(
shader->fDistNear + shader->fDistRange, tiki_worldorigin, SM->cull_radius
)
== CULL_OUT) {
continue;
}
break;
case AGEN_ONE_MINUS_DIST_FADE:
if (R_DistanceCullPointAndRadius(shader->fDistNear, tiki_worldorigin, SM->cull_radius)
== CULL_IN) {
continue;
}
break;
case AGEN_TIKI_DIST_FADE:
fDist = (shader->fDistNear + shader->fDistRange);
VectorSubtract(tiki_worldorigin, tr.viewParms.or.origin, vDelta);
if (VectorLengthSquared(vDelta) >= Square(fDist)) {
continue;
}
break;
case AGEN_ONE_MINUS_TIKI_DIST_FADE:
fDist = (shader->fDistNear + shader->fDistRange);
VectorSubtract(tiki_worldorigin, tr.viewParms.or.origin, vDelta);
if (VectorLengthSquared(vDelta) <= Square(shader->fDistNear)) {
continue;
}
break;
}
}
SM->bRendered = qtrue;
R_AddDrawSurf((surfaceType_t *)s_surface, shader, 0, 0, 0, 0);
if (r_showstaticlod->integer) {
vec3_t org;
int render_count, total_tris;
VectorCopy(SM->origin, org);
org[2] += 100.0;
R_DrawDebugNumber(org, SM->lodpercentage[0], r_showstaticlod->value * 2, 1.0, 1.0, 0.0, 3);
org[2] += 125.0;
R_CountTikiLodTris(tiki, SM->lodpercentage[0], &render_count, &total_tris);
R_DrawDebugNumber(org, render_count, r_showstaticlod->value * 2, 1.0, 1.0, 0.0, 0);
}
if (r_showstaticbboxes->integer) {
vec3_t vMins, vMaxs;
for (k = 0; k < 3; k++) {
vMins[k] = tiki->a->mins[k] * tiki->load_scale * SM->scale;
vMaxs[k] = tiki->a->maxs[k] * tiki->load_scale * SM->scale;
}
R_DebugRotatedBBox(SM->origin, SM->angles, vMins, vMaxs, 1.0, 0.0, 1.0, 0.75);
}
}
}
}
}
tr.shiftedIsStatic = 0;
}
/*
==============
RB_Static_BuildDLights
==============
*/
void RB_Static_BuildDLights()
{
int i;
backEnd.currentStaticModel->useSpecialLighting = backEnd.refdef.num_dlights > 0;
backEnd.currentStaticModel->numdlights = 0;
if (!backEnd.currentStaticModel->useSpecialLighting) {
return;
}
for (i = 0; i < backEnd.refdef.num_dlights && backEnd.currentStaticModel->numdlights != 32; i++) {
vec3_t lightorigin, delta;
VectorCopy(backEnd.refdef.dlights[i].origin, lightorigin);
VectorSubtract(lightorigin, backEnd.currentStaticModel->origin, delta);
if (backEnd.refdef.dlights[i].radius * 2.0 >= VectorLength(delta)) {
MatrixTransformVectorRight(
backEnd.currentStaticModel->axis,
delta,
backEnd.currentStaticModel->dlights[backEnd.currentStaticModel->numdlights].transformed
);
backEnd.currentStaticModel->dlights[backEnd.currentStaticModel->numdlights++].index = i;
}
}
if (!backEnd.currentStaticModel->numdlights) {
backEnd.currentStaticModel->useSpecialLighting = qfalse;
}
}
/*
==============
R_InfoStaticModels_f
==============
*/
void R_InfoStaticModels_f(void)
{
g_bInfostaticmodels = qtrue;
}
/*
==============
R_PrintInfoStaticModels
==============
*/
void R_PrintInfoStaticModels()
{
int iRenderCount;
int i, j;
cStaticModelUnpacked_t *SM;
dtiki_t *tikis[MAX_DISTINCT_STATIC_MODELS];
int tiki_count[MAX_DISTINCT_STATIC_MODELS];
cStaticModelUnpacked_t *pSM[MAX_DISTINCT_STATIC_MODELS];
int count;
ri.Printf(PRINT_ALL, "Static model info:\n");
ri.Printf(PRINT_ALL, "------------------\n");
count = 0;
iRenderCount = 0;
for (i = 0; i < tr.world->numStaticModels; i++) {
SM = &tr.world->staticModels[i];
if (!SM->bRendered) {
continue;
}
SM->bRendered = qfalse;
iRenderCount++;
if (!SM->tiki) {
ri.Printf(PRINT_ALL, "ERROR: static model with no tiki\n");
continue;
}
for (j = 0; j < count; j++) {
if (SM->tiki == tikis[j]) {
tiki_count[j]++;
break;
}
}
if (count >= MAX_DISTINCT_STATIC_MODELS) {
ri.Printf(PRINT_ALL, "R_PrintInfoStaticModels: MAX_DISTINCT_STATIC_MODELS exceeded - increase and recompile\n");
break;
}
if (j == count) {
tikis[count] = SM->tiki;
pSM[count] = SM;
tiki_count[count] = 1;
count++;
}
}
ri.Printf(PRINT_ALL, "Total static models rendered: %d\n", iRenderCount);
for (i = 0; i < count; i++) {
skelHeaderGame_t *skelmodel = ri.TIKI_GetSkel(tikis[i]->mesh[0]);
ri.Printf(PRINT_ALL,
"model: %s, version: %d, count: %d,\n culling min %.1f %.1f %.1f, max %.1f %.1f %.1f, radius %.1f\n",
tikis[i]->a->name,
skelmodel ? skelmodel->version : -1,
tiki_count[i],
tikis[i]->a->mins[0],
tikis[i]->a->mins[1],
tikis[i]->a->mins[2],
tikis[i]->a->maxs[0],
tikis[i]->a->maxs[1],
tikis[i]->a->maxs[2],
pSM[i]->cull_radius
);
}
}

View file

@ -0,0 +1,732 @@
/*
===========================================================================
Copyright (C) 2023-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sun_flare.cpp: Sun flares
#include "tr_local.h"
#define MAX_FLARES 20
class flare_s
{
public:
float size;
float where;
shader_t *shader;
float alphascale;
};
class lens_flare
{
public:
static int max_flares;
float dot_min;
float fullscale;
// List of flares
int num_flares;
flare_s flares[MAX_FLARES];
shader_t *fullscreen;
int fullfade;
qboolean blend_active;
// Flare location
vec3_t trace_v;
vec3_t v;
// Color and alpha
vec3_t color;
float alpha;
// Screen projection
vec2_t screen;
float dot;
int lasttime;
float lastbright;
// Whether or not it's inside a portal sky
bool inportalsky;
qboolean initted;
public:
lens_flare()
{
color[0] = 1.0;
color[1] = 1.0;
color[2] = 1.0;
alpha = 1.0;
initted = false;
}
bool CheckRange();
bool CheckRay();
bool ScreenCalc();
virtual void Try();
virtual void Init(const char *which);
void ScreenBlend();
void InPortalSky();
void NotInPortalSky();
void SetVect(const float *vect);
void SetColor(const float *c) { VectorCopy(c, color); }
void SetAlpha(float a) { alpha = a; }
};
class dlight_lens_flare : public lens_flare
{
public:
shader_t *corona_shader;
public:
dlight_lens_flare() { corona_shader = NULL; }
void Try() override;
void Init(const char *which) override
{
lens_flare::Init(which);
corona_shader = R_FindShader("textures/sprites/corona", -1, qfalse);
}
};
class sun_flare_class : public lens_flare
{
public:
bool SunCheckRay();
void SunScreenCalc();
void SunTry();
};
lens_flare torches;
dlight_lens_flare dlights;
sun_flare_class sunFlare;
int lens_flare::max_flares;
void lens_flare::SetVect(const float *vect)
{
if (inportalsky) {
vec3_t offset;
vec3_t rot_offset;
VectorSubtract(vect, tr.refdef.sky_origin, offset);
VectorRotate(offset, tr.refdef.sky_axis, rot_offset);
VectorAdd(tr.refdef.vieworg, rot_offset, v);
VectorNormalize(offset);
VectorMA(tr.refdef.vieworg, 16384, offset, trace_v);
} else {
VectorCopy(vect, v);
VectorCopy(vect, trace_v);
}
}
void lens_flare::InPortalSky()
{
inportalsky = true;
}
void lens_flare::NotInPortalSky()
{
inportalsky = false;
}
bool lens_flare::CheckRange()
{
vec3_t diff;
VectorSubtract(v, backEnd.viewParms.or.origin, diff);
VectorNormalizeFast(diff);
dot = DotProduct(backEnd.viewParms.or.axis[0], diff);
return dot > dot_min;
}
bool lens_flare::CheckRay()
{
trace_t trace;
ri.CM_BoxTrace(&trace, backEnd.viewParms.or.origin, trace_v, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, qfalse);
if (inportalsky) {
return (trace.surfaceFlags & 4) != 0;
}
return trace.fraction == 1.0;
}
bool lens_flare::ScreenCalc()
{
vec4_t eye;
vec4_t clip;
vec4_t point;
bool retval;
int i, j;
retval = true;
VectorCopy(v, point);
point[3] = 1.0;
VectorClear4(eye);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
eye[i] += point[j] * tr.or.modelMatrix[i + j * 4];
}
}
VectorClear4(clip);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
clip[i] += eye[j] * tr.viewParms.projectionMatrix[i + j * 4];
}
}
for (i = 0; i < 3; i++) {
if (clip[i] >= clip[3] || clip[i] <= -clip[3]) {
retval = false;
}
}
for (i = 0; i < 2; i++) {
screen[i] = clip[i] / clip[3];
}
return retval;
}
void lens_flare::Try()
{
vec2_t diff;
vec2_t point;
float alpha;
int i;
if (!ScreenCalc()) {
return;
}
if (!CheckRange()) {
return;
}
if (!CheckRay()) {
return;
}
VectorScale2D(screen, -2.0, diff);
alpha = (dot - dot_min) / (1.0 - dot_min);
for (i = 0; i < num_flares; i++) {
flare_s *flare = &flares[i];
VectorMA2D(screen, flare->where, diff, point);
RB_Color4f(color[0], color[1], color[2], alpha * this->alpha * flare->alphascale);
RB_StreamBegin(flare->shader);
RB_Texcoord2f(0.0, 0.0);
RB_Vertex2f(point[0] - flare->size, point[1] + flare->size);
RB_Texcoord2f(1.0, 0.0);
RB_Vertex2f(point[0] + flare->size, point[1] + flare->size);
RB_Texcoord2f(0.0, 1.0);
RB_Vertex2f(point[0] - flare->size, point[1] - flare->size);
RB_Texcoord2f(1.0, 1.0);
RB_Vertex2f(point[0] + flare->size, point[1] - flare->size);
RB_StreamEnd();
}
lasttime = backEnd.refdef.time;
blend_active = true;
lastbright = Square(alpha) * Square(alpha) * this->fullscale;
}
void dlight_lens_flare::Try()
{
float size;
size = r_lightcoronasize->value;
lens_flare::Try();
lens_flare::CheckRange();
if (dot <= 0) {
return;
}
if (!CheckRay()) {
return;
}
RB_Color4f(color[0], color[1], color[2], alpha);
RB_StreamBegin(corona_shader);
RB_Texcoord2f(0.0, 0.0);
RB_Vertex2f(screen[0] - size, screen[1] + size);
RB_Texcoord2f(1.0, 0.0);
RB_Vertex2f(screen[0] + size, screen[1] + size);
RB_Texcoord2f(0.0, 1.0);
RB_Vertex2f(screen[0] - size, screen[1] - size);
RB_Texcoord2f(1.0, 1.0);
RB_Vertex2f(screen[0] + size, screen[1] - size);
RB_StreamEnd();
}
void lens_flare::ScreenBlend()
{
float alpha;
int timediff;
if (!fullscreen || !blend_active) {
return;
}
timediff = backEnd.refdef.time - lasttime;
if (timediff > fullfade) {
blend_active = false;
return;
}
alpha = (float)(fullfade - timediff) / fullfade * lastbright;
if (alpha <= 0.0001) {
blend_active = false;
return;
}
RB_Color4f(1.0, 1.0, 1.0, alpha);
RB_StreamBegin(fullscreen);
RB_Vertex2f(-1.0, -1.0);
RB_Vertex2f(1.0, -1.0);
RB_Vertex2f(-1.0, 1.0);
RB_Vertex2f(1.0, 1.0);
RB_StreamEnd();
}
class tmpRiFile
{
private:
bool file_exists;
void *buf;
public:
tmpRiFile()
{
file_exists = false;
buf = NULL;
}
~tmpRiFile() { close(); }
int open(const char *which, void **buffer)
{
close();
if (ri.FS_ReadFile(which, buffer) != -1) {
file_exists = true;
buf = *buffer;
}
return file_exists;
}
bool exists() const { return file_exists; }
void close()
{
if (file_exists) {
ri.FS_FreeFile(buf);
file_exists = false;
}
}
};
void lens_flare::Init(const char *which)
{
char *file;
const char *token;
tmpRiFile theFile;
initted = false;
theFile.open("global/lensflaredefs.txt", (void **)&file);
if (!theFile.exists()) {
ri.Printf(PRINT_WARNING, "WARNING: Could not open lens flare info file!\n");
return;
}
while ((token = COM_ParseExt(&file, qtrue))) {
if (!file) {
ri.Printf(PRINT_WARNING, "WARNING: could not find begin for section '%s' in lensflares\n", which);
return;
}
if (!Q_stricmp(token, "begin")) {
token = COM_ParseExt(&file, qfalse);
if (!Q_stricmp(token, which)) {
break;
}
}
}
dot_min = 0.8f;
fullscale = 0.7f;
num_flares = 0;
fullscreen = NULL;
initted = true;
fullfade = 0;
blend_active = false;
while ((token = COM_ParseExt(&file, qtrue))) {
if (!file) {
ri.Printf(PRINT_WARNING, "WARNING: could not find end for section '%s' in lensflares\n", which);
break;
}
if (!Q_stricmp(token, "dot_min")) {
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: invalid dot_min in lensflares\n");
continue;
}
dot_min = atof(token);
} else if (!Q_stricmp(token, "flare")) {
assert(num_flares < MAX_FLARES);
flares[num_flares].alphascale = 1.0;
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 1 for flare '%d' in lensflares\n", num_flares);
continue;
}
flares[num_flares].size = atof(token);
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 2 for flare '%d' in lensflares\n", num_flares);
continue;
}
flares[num_flares].where = atof(token);
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 3 for flare '%d' in lensflares\n", num_flares);
continue;
}
flares[num_flares].shader = R_FindShader(token, -1, qfalse);
token = COM_ParseExt(&file, qfalse);
if (token[0]) {
flares[num_flares].alphascale = atof(token);
}
num_flares++;
} else if (!Q_stricmp(token, "fullscale")) {
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullscale, assuming default (in lensflares)\n");
continue;
}
fullscale = atof(token);
} else if (!Q_stricmp(token, "fullscreen")) {
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullsreen in lensflares\n");
continue;
}
fullscreen = R_FindShader(token, -1, qfalse);
} else if (!Q_stricmp(token, "fullfade")) {
token = COM_ParseExt(&file, qfalse);
if (!token[0]) {
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullfade in lensflares\n");
continue;
}
fullfade = atof(token);
} else if (!Q_stricmp(token, "end")) {
break;
}
}
if (!num_flares) {
ri.Printf(PRINT_WARNING, "WARNING: no lensflares defined!\n");
}
lasttime = backEnd.refdef.time - fullfade;
}
static void R_DrawSunFlare()
{
if (!s_sun.exists) {
return;
}
if (!sunFlare.initted) {
if (!s_sun.szFlareName[0]) {
return;
}
if (Q_stricmp(s_sun.szFlareName, "none")) {
sunFlare.Init(s_sun.szFlareName);
}
}
if (!sunFlare.initted) {
s_sun.szFlareName[0] = 0;
return;
}
if (!sunFlare.num_flares) {
return;
}
VectorMA(backEnd.viewParms.or.origin, 16384, s_sun.flaredirection, sunFlare.trace_v);
VectorMA(backEnd.viewParms.or.origin, 128, s_sun.flaredirection, sunFlare.v);
sunFlare.SunTry();
}
static void R_DrawSunFlareBlend()
{
if (!s_sun.exists) {
return;
}
if (!sunFlare.initted) {
return;
}
sunFlare.ScreenBlend();
}
void R_DrawLensFlares()
{
// FIXME: unimplemented (GL2)
#if 0
int i;
R_RotateForViewer();
qglPushMatrix();
qglLoadIdentity();
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglLoadIdentity();
qglOrtho(-1.0, 1.0, -1.0, 1.0, -99999.0, 99999.0);
tess.no_global_fog = true;
R_DrawSunFlare();
for (i = 0; i < backEnd.refdef.num_entities; i++) {
if ((backEnd.viewParms.isPortalSky && !(backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY))
|| (!backEnd.viewParms.isPortalSky && (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY))) {
continue;
}
if (backEnd.refdef.entities[i].e.renderfx & RF_LENSFLARE) {
vec3_t rgb;
if (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY) {
dlights.InPortalSky();
} else {
dlights.NotInPortalSky();
}
dlights.SetVect(backEnd.refdef.entities[i].e.origin);
//
// Set the dlight color from entity
//
rgb[0] = backEnd.refdef.entities[i].e.shaderRGBA[0] / 255.0;
rgb[1] = backEnd.refdef.entities[i].e.shaderRGBA[1] / 255.0;
rgb[2] = backEnd.refdef.entities[i].e.shaderRGBA[2] / 255.0;
dlights.SetColor(rgb);
dlights.Try();
}
if (backEnd.refdef.entities[i].e.renderfx & RF_VIEWLENSFLARE) {
vec3_t rgb;
if (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY) {
torches.InPortalSky();
} else {
torches.NotInPortalSky();
}
torches.SetVect(backEnd.refdef.entities[i].e.origin);
rgb[0] = backEnd.refdef.entities[i].e.shaderRGBA[0] / 255.0;
rgb[1] = backEnd.refdef.entities[i].e.shaderRGBA[1] / 255.0;
rgb[2] = backEnd.refdef.entities[i].e.shaderRGBA[2] / 255.0;
torches.SetColor(rgb);
torches.Try();
}
}
for (i = 0; i < backEnd.refdef.num_dlights; i++) {
if ((backEnd.refdef.dlights[i].type & dlighttype_t::lensflare)
|| (backEnd.refdef.dlights[i].type & dlighttype_t::additive)) {
dlights.NotInPortalSky();
dlights.SetVect(backEnd.refdef.dlights[i].origin);
dlights.SetColor(backEnd.refdef.dlights[i].color);
dlights.Try();
}
}
R_DrawSunFlareBlend();
tess.no_global_fog = qfalse;
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
#endif
}
void R_InitLensFlare()
{
torches.Init("entity");
dlights.Init("dlight");
sunFlare.initted = false;
}
bool sun_flare_class::SunCheckRay()
{
mnode_t *pViewLeaf;
trace_t trace;
pViewLeaf = R_PointInLeaf(tr.refdef.vieworg);
if (pViewLeaf->area == -1 || !tr.world->vis || tr.sSunLight.leaf != (mnode_s *)-1
|| pViewLeaf->numlights && pViewLeaf->lights[0] == &tr.sSunLight) {
ri.CM_BoxTrace(
&trace, backEnd.viewParms.or.origin, trace_v, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, qfalse
);
if (trace.surfaceFlags & SURF_SKY) {
return true;
}
}
return false;
}
void sun_flare_class::SunScreenCalc()
{
vec4_t eye;
vec4_t clip;
vec4_t point;
int i, j;
VectorCopy(v, point);
point[3] = 1.0;
VectorClear4(eye);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
eye[i] += point[j] * tr.or.modelMatrix[i + j * 4];
}
}
VectorClear4(clip);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
clip[i] += eye[j] * tr.viewParms.projectionMatrix[i + j * 4];
}
}
for (i = 0; i < 2; i++) {
screen[i] = clip[i] / clip[3];
}
}
void sun_flare_class::SunTry()
{
vec2_t diff;
vec2_t point;
float alpha;
int i;
qboolean bDrawingFade = qfalse;
if (!CheckRange()) {
return;
}
if (SunCheckRay()) {
alpha = (dot - dot_min) / (1.0 - dot_min);
} else {
int timediff;
if (!fullscreen) {
return;
}
if (!blend_active) {
return;
}
timediff = backEnd.refdef.time - lasttime;
alpha = (float)(fullfade - timediff) / fullfade * lastbright;
if (alpha <= 0.0001) {
return;
}
bDrawingFade = qtrue;
}
SunScreenCalc();
VectorScale2D(screen, -2.0, diff);
for (i = 0; i < num_flares; i++) {
flare_s *flare = &flares[i];
VectorMA2D(screen, flare->where, diff, point);
RB_Color4f(color[0], color[1], color[2], alpha * this->alpha * flare->alphascale);
RB_StreamBegin(flare->shader);
RB_Texcoord2f(0.0, 0.0);
RB_Vertex2f(point[0] - flare->size, point[1] + flare->size);
RB_Texcoord2f(1.0, 0.0);
RB_Vertex2f(point[0] + flare->size, point[1] + flare->size);
RB_Texcoord2f(0.0, 1.0);
RB_Vertex2f(point[0] - flare->size, point[1] - flare->size);
RB_Texcoord2f(1.0, 1.0);
RB_Vertex2f(point[0] + flare->size, point[1] - flare->size);
RB_StreamEnd();
}
if (!bDrawingFade) {
lasttime = backEnd.refdef.time;
blend_active = true;
lastbright = Square(alpha) * Square(alpha) * fullscale;
}
}

View file

@ -0,0 +1,183 @@
/*
===========================================================================
Copyright (C) 2023-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_swipe.cpp -- swipe rendering
#include "tr_local.h"
#define MAX_SWIPE_POINTS 1024
#define MAX_SWIPES 32
typedef struct {
vec3_t points[2];
float time;
} rswipepoint_t;
typedef struct {
surfaceType_t surftype;
float life;
float time;
int lastrendtime;
qhandle_t shader;
int numswipes;
rswipepoint_t swipes[MAX_SWIPE_POINTS];
} rendswipe_t;
static int lastswipeframe;
static int numswipes;
static rendswipe_t swipes[MAX_SWIPES];
/*
======================
RE_SwipeBegin
======================
*/
void RE_SwipeBegin(float thistime, float life, qhandle_t shader)
{
rendswipe_t *swipe;
if (tr.frameCount != lastswipeframe) {
swipe = &swipes[0];
numswipes = 0;
}
if (numswipes >= MAX_SWIPES) {
return;
}
swipe = &swipes[numswipes++];
swipe->life = life;
swipe->time = thistime;
swipe->surftype = SF_SWIPE;
swipe->numswipes = 0;
swipe->lastrendtime = 0;
swipe->shader = shader;
if (shader < 0 && life) {
ri.Printf(PRINT_DEVELOPER, "RE_SwipeBegin: Invalid shader handle\n");
}
lastswipeframe = tr.frameCount;
}
/*
======================
RE_SwipePoint
======================
*/
void RE_SwipePoint(vec3_t point1, vec3_t point2, float time)
{
rendswipe_t *swipe = &swipes[numswipes - 1];
if (swipe->numswipes >= MAX_SWIPE_POINTS) {
return;
}
VectorCopy(point1, swipe->swipes[swipe->numswipes - 1].points[0]);
VectorCopy(point2, swipe->swipes[swipe->numswipes - 1].points[1]);
}
/*
======================
RE_SwipeEnd
======================
*/
void RE_SwipeEnd() {}
/*
======================
R_AddSwipeSurfaces
======================
*/
void R_AddSwipeSurfaces()
{
shader_t *shader;
int at;
if (!numswipes) {
return;
}
tr.currentEntityNum = ENTITYNUM_WORLD;
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
for (at = 0; at < numswipes; at++) {
rendswipe_t *swipe = &swipes[at];
int timedelta = 0;
if (!swipe->numswipes) {
continue;
}
if (swipe->lastrendtime) {
timedelta = tr.refdef.time - swipe->lastrendtime;
}
swipe->lastrendtime = tr.refdef.time;
if (timedelta) {
swipe->time += timedelta;
}
shader = R_GetShaderByHandle(swipe->shader);
R_AddDrawSurf(&swipe->surftype, shader, 0, 0, 0, 0);
}
}
/*
======================
RB_DrawSwipeSurface
======================
*/
void RB_DrawSwipeSurface(surfaceType_t *pswipe)
{
int i;
float oolife;
rendswipe_t *swipe = (rendswipe_t *)pswipe;
oolife = 1.0 / swipe->life;
RB_CHECKOVERFLOW(swipe->numswipes * 2, swipe->numswipes * 6);
RB_StreamBeginDrawSurf();
for (i = 0; i < swipe->numswipes; i++) {
rswipepoint_t *swipepoint = &swipe->swipes[i];
float alpha;
float f;
f = 1.0 - (swipe->time - swipepoint->time) * oolife;
if (f > 0 && swipe->time >= swipepoint->time) {
alpha = f - Q_max(f - 1.0, 0);
RB_Color4f(alpha, alpha, alpha, alpha);
RB_Texcoord2f(i / (float)swipe->numswipes, 1.0);
RB_Vertex3fv(swipepoint->points[0]);
RB_Texcoord2f(i / (float)swipe->numswipes, 1.0);
RB_Vertex3fv(swipepoint->points[1]);
} else if (i == swipe->numswipes - 1) {
swipe->numswipes = 0;
}
}
RB_StreamEndDrawSurf();
}

View file

@ -0,0 +1,388 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_util.c -- renderer utility
#include "tr_local.h"
#include "../qcommon/str.h"
static byte cntColor[4];
static float cntSt[2];
static int Numbers[12][8] = {
{1, 3, 4, 5, 6, 7, 0, 0},
{4, 5, 0, 0, 0, 0, 0, 0},
{1, 4, 2, 7, 3, 0, 0, 0},
{1, 4, 2, 5, 3, 0, 0, 0},
{6, 4, 2, 5, 0, 0, 0, 0},
{1, 6, 2, 5, 3, 0, 0, 0},
{1, 6, 2, 5, 7, 3, 0, 0},
{1, 8, 0, 0, 0, 0, 0, 0},
{1, 2, 3, 4, 5, 6, 7, 0},
{1, 6, 4, 2, 5, 3, 0, 0},
{9, 10, 11, 12, 0, 0, 0, 0},
{2, 0, 0, 0, 0, 0, 0, 0}
};
static float Lines[13][4] = {
{0.0, 0.0, 0.0, 0.0},
{-4.0, 8.0, 4.0, 8.0},
{-4.0, 4.0, 4.0, 4.0},
{-4.0, 0.0, 4.0, 0.0},
{4.0, 8.0, 4.0, 4.0},
{4.0, 4.0, 4.0, 0.0},
{-4.0, 8.0, -4.0, 4.0},
{-4.0, 4.0, -4.0, 0.0},
{4.0, 8.0, -4.0, 0.0},
{-1.0, 2.0, 1.0, 2.0},
{1.0, 2.0, 1.0, 0.0},
{-1.0, 0.0, 1.0, 0.0},
{-1.0, 0.0, -1.0, 2.0}
};
/*
===============
RB_StreamBegin
===============
*/
void RB_StreamBegin(shader_t *shader)
{
RB_BeginSurface(shader, 0, 0);
}
/*
===============
RB_StreamEnd
===============
*/
void RB_StreamEnd(void)
{
int i;
if (tess.numVertexes <= 2) {
RB_EndSurface();
return;
}
tess.indexes[0] = 0;
tess.indexes[1] = 1;
tess.indexes[2] = 2;
for (i = 0; i < tess.numVertexes - 2; i++) {
tess.indexes[i * 3 + 0] = (i & 1) + i;
tess.indexes[i * 3 + 1] = i - ((i & 1) - 1);
tess.indexes[i * 3 + 2] = i + 2;
tess.numIndexes += 3;
}
RB_EndSurface();
}
/*
===============
RB_StreamBeginDrawSurf
===============
*/
void RB_StreamBeginDrawSurf(void)
{
// FIXME: unimplemented (GL2)
}
/*
===============
RB_StreamEndDrawSurf
===============
*/
void RB_StreamEndDrawSurf(void)
{
// FIXME: unimplemented (GL2)
}
/*
===============
addTriangle
===============
*/
static void addTriangle(void)
{
tess.texCoords[tess.numVertexes][0] = cntSt[0];
tess.texCoords[tess.numVertexes][1] = cntSt[1];
tess.color[tess.numVertexes][0] = cntColor[0];
tess.color[tess.numVertexes][1] = cntColor[1];
tess.color[tess.numVertexes][2] = cntColor[2];
tess.color[tess.numVertexes][3] = cntColor[3];
tess.numVertexes++;
}
/*
===============
RB_Vertex3fv
===============
*/
void RB_Vertex3fv(vec3_t v)
{
VectorCopy(v, tess.xyz[tess.numVertexes]);
addTriangle();
}
/*
===============
RB_Vertex3f
===============
*/
void RB_Vertex3f(vec_t x, vec_t y, vec_t z)
{
tess.xyz[tess.numVertexes][0] = x;
tess.xyz[tess.numVertexes][1] = y;
tess.xyz[tess.numVertexes][2] = z;
addTriangle();
}
/*
===============
RB_Vertex2f
===============
*/
void RB_Vertex2f(vec_t x, vec_t y)
{
RB_Vertex3f(x, y, 0);
}
/*
===============
RB_Color4f
===============
*/
void RB_Color4f(vec_t r, vec_t g, vec_t b, vec_t a)
{
cntColor[0] = r * tr.identityLightByte;
cntColor[1] = g * tr.identityLightByte;
cntColor[2] = b * tr.identityLightByte;
cntColor[3] = a * 255.0;
}
/*
===============
RB_Color3f
===============
*/
void RB_Color3f(vec_t r, vec_t g, vec_t b)
{
RB_Color4f(r, g, b, 1.0);
}
/*
===============
RB_Color3fv
===============
*/
void RB_Color3fv(vec3_t col)
{
RB_Color3f(col[0], col[1], col[2]);
}
/*
===============
RB_Color4bv
===============
*/
void RB_Color4bv(unsigned char *colors)
{
cntColor[0] = colors[0];
cntColor[1] = colors[1];
cntColor[2] = colors[2];
cntColor[3] = colors[3];
}
/*
===============
RB_Texcoord2f
===============
*/
void RB_Texcoord2f(float s, float t)
{
cntSt[0] = s;
cntSt[1] = t;
}
/*
===============
RB_Texcoord2fv
===============
*/
void RB_Texcoord2fv(vec2_t st)
{
cntSt[0] = st[0];
cntSt[1] = st[1];
}
/*
===============
R_DrawDebugNumber
===============
*/
void R_DrawDebugNumber(const vec3_t org, float number, float scale, float r, float g, float b, int precision)
{
vec3_t up, right;
vec3_t pos1, pos2;
vec3_t start;
str text;
char format[20];
int i;
int j;
int l;
int num;
VectorCopy(tr.viewParms.or.axis[2], up);
VectorCopy(tr.viewParms.or.axis[1], right);
VectorNegate(right, right);
VectorNormalize(up);
VectorNormalize(right);
VectorScale(up, scale, up);
VectorScale(right, scale, right);
if (precision > 0) {
Com_sprintf(format, sizeof(format), "%%.%df", precision);
text = va(format, number);
} else {
text = va("%d", (int)number);
}
// NOTE: this cast here is needed!
// Otherwise the compiler will do very nasty implicit casting of negative
// numbers to unsigned numbers, resulting in incorrect values.
// -------------------v
VectorMA(org, 5 - 5 * (int)text.length(), right, start);
// Draw each character/digit of the text
for (i = 0; i < text.length(); i++) {
if (text[i] == '.') {
num = 10;
} else if (text[i] == '-') {
num = 11;
} else {
num = text[i] - '0';
}
// Get the first line index for the number to be drawn
l = Numbers[num][0];
// Draw each line of the character/digit
for (j = 0; j < 8 && l; ++j, l = Numbers[num][j]) {
pos1[0] = start[0] + Lines[l][0] * right[0] + Lines[l][1] * up[0];
pos1[1] = start[1] + Lines[l][0] * right[1] + Lines[l][1] * up[1];
pos1[2] = start[2] + Lines[l][0] * right[2] + Lines[l][1] * up[2];
pos2[0] = start[0] + Lines[l][2] * right[0] + Lines[l][3] * up[0];
pos2[1] = start[1] + Lines[l][2] * right[1] + Lines[l][3] * up[1];
pos2[2] = start[2] + Lines[l][2] * right[2] + Lines[l][3] * up[2];
R_DebugLine(pos1, pos2, r, g, b, 1.0);
}
VectorMA(start, 10.0, right, start);
}
}
/*
===============
R_DebugRotatedBBox
===============
*/
void R_DebugRotatedBBox(
const vec3_t org, const vec3_t ang, const vec3_t mins, const vec3_t maxs, float r, float g, float b, float alpha
)
{
}
/*
===============
RE_GetShaderWidth
===============
*/
int RE_GetShaderWidth(qhandle_t hShader)
{
shader_t *shader;
if (hShader) {
shader = R_GetShaderByHandle(hShader);
} else {
shader = tr.defaultShader;
}
return shader->stages[0]->bundle[0].image[0]->uploadWidth;
}
/*
===============
RE_GetShaderHeight
===============
*/
int RE_GetShaderHeight(qhandle_t hShader)
{
shader_t *shader;
if (hShader) {
shader = R_GetShaderByHandle(hShader);
} else {
shader = tr.defaultShader;
}
return shader->stages[0]->bundle[0].image[0]->uploadHeight;
}
/*
===============
RE_GetShaderName
===============
*/
const char *RE_GetShaderName(qhandle_t hShader)
{
shader_t *shader;
if (hShader) {
shader = R_GetShaderByHandle(hShader);
} else {
shader = tr.defaultShader;
}
return shader->name;
}
/*
===============
RE_GetModelName
===============
*/
const char *RE_GetModelName(qhandle_t hModel)
{
model_t *model;
if (!hModel) {
return "";
}
model = R_GetModelByHandle(hModel);
return model->name;
}

View file

@ -589,7 +589,7 @@ static void R_RecursiveWorldNode( mnode_t *node, uint32_t planeBits, uint32_t dl
R_PointInLeaf
===============
*/
static mnode_t *R_PointInLeaf( const vec3_t p ) {
mnode_t *R_PointInLeaf( const vec3_t p ) {
mnode_t *node;
float d;
cplane_t *plane;
@ -807,3 +807,16 @@ void R_AddWorldSurfaces (void) {
tr.refdef.dlightMask = ~tr.refdef.dlightMask;
}
}
//
// OPENMOHAA-specific stuff
//
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs)
{
bmodel_t* bmodel;
bmodel = &tr.world->bmodels[iIndex];
VectorCopy(bmodel->bounds[0], vMins);
VectorCopy(bmodel->bounds[1], vMaxs);
}