//========= 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 #include "in_defs.h" #include "twm.h" #include "twmmanager.h" #include "../common/com_model.h" #include "ParticleBase.h" #define DLLEXPORT __declspec( dllexport ) 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 for(int 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); } }