halflife-thewastes-sdk/cl_dll/tri.cpp

364 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);
}
}