forked from valve/halflife-sdk
363 lines
9.3 KiB
C++
363 lines
9.3 KiB
C++
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
|
|
// Triangle rendering, if any
|
|
|
|
#include "hud.h"
|
|
#include "cl_util.h"
|
|
|
|
// Triangle rendering apis are in gEngfuncs.pTriAPI
|
|
|
|
#include "const.h"
|
|
#include "entity_state.h"
|
|
#include "cl_entity.h"
|
|
#include "triangleapi.h"
|
|
#include "ref_params.h"
|
|
#include "pm_defs.h"
|
|
#include "pmtrace.h"
|
|
#include "event_api.h"
|
|
#include "r_efx.h"
|
|
#include "ParseBspEnt.h"
|
|
#include "ParseBsp.h"
|
|
#include <time.h>
|
|
|
|
#include "in_defs.h"
|
|
#include "twm.h"
|
|
#include "twmmanager.h"
|
|
|
|
#include "../common/com_model.h"
|
|
|
|
#include "ParticleBase.h"
|
|
|
|
extern "C"
|
|
{
|
|
void DLLEXPORT HUD_DrawNormalTriangles( void );
|
|
void DLLEXPORT HUD_DrawTransparentTriangles( void );
|
|
};
|
|
|
|
// This should be all the muzzleflashes we need,
|
|
// assuming everyone on the server shoots akimbo weapons at the same time and you see it :)
|
|
twm_clientinfo_t g_MuzzleflashModels[64];
|
|
int g_iNumMuzzleflashModels;
|
|
|
|
/*
|
|
=================
|
|
R_TwmModel
|
|
|
|
Render a TWM model with
|
|
given origin and angles
|
|
=================
|
|
*/
|
|
void R_TwmModel(twm_clientinfo_t *twm_clientinfo,vec3_t origin,vec3_t angles)
|
|
{
|
|
int i,k,j;
|
|
const twm_info_t *twm_info = twm_clientinfo->twm_info;
|
|
float *color = twm_clientinfo->color;
|
|
vec3_t forward,right,up;
|
|
|
|
gEngfuncs.pTriAPI->RenderMode(twm_clientinfo->render_mode);
|
|
gEngfuncs.pTriAPI->CullFace(TRI_NONE); // TODO: Cull something?
|
|
|
|
// Render model by materialgroup
|
|
for(k = 0;k < twm_info->num_materialgroups;k++)
|
|
{
|
|
twm_materialgroup_t *cur_mat = &twm_info->materialgroup_lump[k];
|
|
|
|
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)gEngfuncs.GetSpritePointer(cur_mat->sprite_handle),twm_clientinfo->sprite_frame);
|
|
|
|
// Render each triangle
|
|
for(i = 0;i < cur_mat->num_triangles;i++)
|
|
{
|
|
twm_triangle_t *cur_tri = &twm_info->triangle_lump[cur_mat->tris_indices[i]];
|
|
|
|
gEngfuncs.pTriAPI->Begin(TRI_TRIANGLES);
|
|
gEngfuncs.pTriAPI->Color4f(color[0],color[1],color[2],color[3]);
|
|
// Add vertex information
|
|
for(j = 0;j < 3;j++)
|
|
{
|
|
vec3_t vec;
|
|
|
|
vec[0] = twm_info->vertex_lump[cur_tri->vert_indices[j]][0];
|
|
vec[1] = twm_info->vertex_lump[cur_tri->vert_indices[j]][1];
|
|
vec[2] = twm_info->vertex_lump[cur_tri->vert_indices[j]][2];
|
|
|
|
// Add in angles
|
|
VectorMA(vec,1,angles,vec);
|
|
|
|
// Add in origin
|
|
// VectorAdd(origin,vec,vec);
|
|
|
|
gEngfuncs.pTriAPI->Brightness(twm_clientinfo->brightness);
|
|
gEngfuncs.pTriAPI->TexCoord2f(cur_tri->u[j],cur_tri->v[j]);
|
|
gEngfuncs.pTriAPI->Vertex3fv(vec);
|
|
}
|
|
gEngfuncs.pTriAPI->End();
|
|
}
|
|
}
|
|
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
R_Billboard
|
|
|
|
Render a quad that always faces the camera
|
|
=================
|
|
*/
|
|
void R_Billboard(const struct model_s *sprite,int sprite_frame,int render_mode,float r,float g,float b,float alpha,float *origin,float *v_up,float *v_right,float scale)
|
|
{
|
|
gEngfuncs.pTriAPI->RenderMode(render_mode);
|
|
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
|
|
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)sprite,sprite_frame);
|
|
|
|
// Render the sprite
|
|
gEngfuncs.pTriAPI->Begin(TRI_QUADS);
|
|
gEngfuncs.pTriAPI->Color4f(r,g,b,alpha);
|
|
|
|
gEngfuncs.pTriAPI->Brightness(1);
|
|
gEngfuncs.pTriAPI->TexCoord2f(0,1);
|
|
gEngfuncs.pTriAPI->Vertex3f(origin[0]+((-v_right[0]+v_up[0])*scale),origin[1]+((-v_right[1]+v_up[1])*scale),origin[2]+((-v_right[2]+v_up[2])*scale));
|
|
|
|
gEngfuncs.pTriAPI->Brightness(1);
|
|
gEngfuncs.pTriAPI->TexCoord2f(0,0);
|
|
gEngfuncs.pTriAPI->Vertex3f(origin[0]+((v_right[0]+v_up[0])*scale),origin[1]+((v_right[1]+v_up[1])*scale),origin[2]+((v_right[2]+v_up[2])*scale));
|
|
|
|
gEngfuncs.pTriAPI->Brightness(1);
|
|
gEngfuncs.pTriAPI->TexCoord2f(1,0);
|
|
gEngfuncs.pTriAPI->Vertex3f(origin[0]+((v_right[0]-v_up[0])*scale),origin[1]+((v_right[1]-v_up[1])*scale),origin[2]+((v_right[2]-v_up[2])*scale));
|
|
|
|
gEngfuncs.pTriAPI->Brightness(1);
|
|
gEngfuncs.pTriAPI->TexCoord2f(1,1);
|
|
gEngfuncs.pTriAPI->Vertex3f(origin[0]+((-v_right[0]-v_up[0])*scale),origin[1]+((-v_right[1]-v_up[1])*scale),origin[2]+((-v_right[2]-v_up[2])*scale));
|
|
gEngfuncs.pTriAPI->End();
|
|
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
|
}
|
|
|
|
static cl_entity_t laser_beams[2]; // The beams :)
|
|
int g_iClientLasersEnabled[32];
|
|
|
|
extern int cam_thirdperson;
|
|
extern vec3_t v_origin,v_angles;
|
|
|
|
/*
|
|
=================
|
|
R_LaserBeam
|
|
|
|
Draw a laser beam
|
|
Parts contributed by Stuart Crouch
|
|
=================
|
|
*/
|
|
void R_LaserBeam( cl_entity_t *player )
|
|
{
|
|
float end[ 3 ], start[ 3 ];
|
|
int beamindex;
|
|
struct model_s *laserbeam;
|
|
vec3_t forward, up, right;
|
|
vec3_t origin, vecSrc, vecDest, angles;
|
|
pmtrace_t tr;
|
|
float dotscale;
|
|
int dotindex;
|
|
struct model_s *dotmodel;
|
|
vec3_t v_forward,v_up,v_right;
|
|
float beam_r,beam_g,beam_b;
|
|
float dot_r,dot_g,dot_b;
|
|
BEAM *pBeam1;
|
|
|
|
// Load it up with some bogus data
|
|
//player = gEngfuncs.GetLocalPlayer();
|
|
cl_entity_t *localplayer = gEngfuncs.GetLocalPlayer();
|
|
|
|
if ( !localplayer )
|
|
return; // paranioa
|
|
if ( !player )
|
|
return;
|
|
if ( !player->player )
|
|
return; // Player isnt a player.
|
|
|
|
// we cancel if its intermission time and
|
|
// trying to draw the local laserbeam
|
|
if(g_pparams->intermission && !cam_thirdperson && gEngfuncs.pEventAPI->EV_IsLocal(player->index-1))
|
|
return;
|
|
|
|
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( true, true );
|
|
gEngfuncs.pEventAPI->EV_PushPMStates();
|
|
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( player->index -1 );
|
|
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
|
|
|
if(!cam_thirdperson && gEngfuncs.pEventAPI->EV_IsLocal(player->index - 1))
|
|
{
|
|
// First person starting points are
|
|
// different so they line up
|
|
cl_entity_t *pView = gEngfuncs.GetViewModel();
|
|
|
|
VectorCopy(pView->attachment[1],vecSrc);
|
|
VectorCopy(pView->angles,angles);
|
|
|
|
// Use Attachment 3 on the view model to get the forward axis
|
|
VectorSubtract(pView->attachment[1],pView->attachment[2],forward);
|
|
VectorNormalize(forward);
|
|
VectorMA(vecSrc,8192,forward,vecDest);
|
|
}
|
|
else
|
|
{
|
|
// Third person starting points
|
|
VectorCopy( player->origin, vecSrc );
|
|
VectorCopy( player->angles, angles );
|
|
angles[ PITCH ] *= -3;
|
|
vecSrc[2] += 20;
|
|
|
|
AngleVectors (angles, forward, right, up);
|
|
|
|
// Draw from player model
|
|
for (int i = 0; i < 3; i++ )
|
|
vecSrc[ i ] += 20 * forward[ i ];
|
|
|
|
VectorMA(vecSrc,8192,forward,vecDest);
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_GLASS_IGNORE|PM_STUDIO_BOX, -1, &tr );
|
|
|
|
if(!cam_thirdperson && gEngfuncs.pEventAPI->EV_IsLocal(player->index - 1))
|
|
{
|
|
// Draw from view models attachment
|
|
cl_entity_t *pView = gEngfuncs.GetViewModel();
|
|
|
|
if(pView != NULL)
|
|
{
|
|
// Attachment 1
|
|
start[0] = pView->attachment[1].x;
|
|
start[1] = pView->attachment[1].y;
|
|
start[2] = pView->attachment[1].z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Draw from players attachment point
|
|
start [ 0 ] = player->attachment[1].x;
|
|
start [ 1 ] = player->attachment[1].y;
|
|
start [ 2 ] = player->attachment[1].z;
|
|
}
|
|
|
|
end [ 0 ] = tr.endpos.x;
|
|
end [ 1 ] = tr.endpos.y;
|
|
end [ 2 ] = tr.endpos.z;
|
|
|
|
laserbeam = gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &beamindex );
|
|
if ( !laserbeam )
|
|
return;
|
|
|
|
// Easter Egg ;D
|
|
time_t Time;
|
|
time(&Time);
|
|
|
|
// Josh's Birthday, July 9th
|
|
if(localtime(&Time)->tm_mday == 9 && localtime(&Time)->tm_mon == 6)
|
|
{
|
|
beam_r = dot_r = 0.0;
|
|
beam_g = dot_g = 1.0;
|
|
beam_b = dot_b = 0.0;
|
|
}
|
|
else
|
|
{
|
|
// normal :)
|
|
beam_r = 1.0;
|
|
beam_g = 0.0;
|
|
beam_b = 0.0;
|
|
|
|
dot_r = 1.0;
|
|
dot_g = 1.0;
|
|
dot_b = 1.0;
|
|
}
|
|
|
|
pBeam1 = gEngfuncs.pEfxAPI->R_BeamPoints( start, end, beamindex,
|
|
0.0001, 0.3, 0.0, 0.14, 5.0, 0.0, 1.0, beam_r,beam_g,beam_b );
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
|
|
// Now to render a halo around the light beginning point. :)
|
|
dotscale = 4; // TODO: make like a lenticular halo and resize for distance?
|
|
|
|
AngleVectors (v_angles, v_forward, v_right, v_up);
|
|
|
|
dotmodel = gEngfuncs.CL_LoadModel( "sprites/hand_laser_dot.spr", &dotindex );
|
|
if(dotmodel == NULL)
|
|
gEngfuncs.Con_DPrintf("Bogus laser sprite, check R_LaserBeam");
|
|
|
|
R_Billboard(dotmodel,0,kRenderTransAdd,dot_r,dot_g,dot_b,1.0,start,v_up,v_right,dotscale);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
R_SetFog
|
|
|
|
Set current fog state
|
|
=================
|
|
*/
|
|
void R_SetFog(float r,float g,float b,float start,float end,int enable)
|
|
{
|
|
float color[3];
|
|
|
|
color[0] = r;
|
|
color[1] = g;
|
|
color[2] = b;
|
|
|
|
gEngfuncs.pTriAPI->Fog(color,start,end,enable);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
HUD_DrawNormalTriangles
|
|
|
|
Non-transparent triangles-- add them here
|
|
=================
|
|
*/
|
|
void DLLEXPORT HUD_DrawNormalTriangles( void )
|
|
{
|
|
// Render particle effects
|
|
g_ParticleSystemManager.RenderNormal();
|
|
|
|
gHUD.m_Spectator.DrawOverview();
|
|
}
|
|
|
|
/*
|
|
=================
|
|
HUD_DrawTransparentTriangles
|
|
|
|
Render any triangles with transparent rendermode needs here
|
|
=================
|
|
*/
|
|
void DLLEXPORT HUD_DrawTransparentTriangles( void )
|
|
{
|
|
// Render particle effects
|
|
g_ParticleSystemManager.RenderTransparent();
|
|
|
|
// Render laser beams
|
|
int i;
|
|
for(i = 0;i < gEngfuncs.GetMaxClients();i++)
|
|
{
|
|
cl_entity_t *player = gEngfuncs.GetEntityByIndex(i);
|
|
if(player != NULL && g_iClientLasersEnabled[i])
|
|
R_LaserBeam(player);
|
|
}
|
|
|
|
// Render 3d muzzleflashes
|
|
for(i = 0;i < g_iNumMuzzleflashModels;i++)
|
|
{
|
|
twm_clientinfo_t *clientinfo = &g_MuzzleflashModels[i];
|
|
|
|
// TODO: Perhaps relink
|
|
// entities at the end of the
|
|
// array here, so we dont have
|
|
// dead links
|
|
if(clientinfo->dead)
|
|
continue;
|
|
|
|
// Render it
|
|
cl_entity_t *attached_ent = clientinfo->attached_ent;
|
|
R_TwmModel(clientinfo,attached_ent->attachment[clientinfo->attachment_num],attached_ent->angles);
|
|
}
|
|
}
|