/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "d3d_local.h" #include "resource.h" #define NUM_CYLINDER_VERTS 152 // this is a dump from a radius 1, 75 slices, 1 stacks gluCylinder call and it's rotated, positioned and scaled on the GPU // per http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node17.html a quad strip and a triangle strip have the same layout and winding float cylinderverts[NUM_CYLINDER_VERTS * 3] = { 0.000000, 1.000000, 1.000000, 0.000000, 1.000000, 0.000000, 0.083678, 0.996493, 1.000000, 0.083678, 0.996493, 0.000000, 0.166769, 0.985996, 1.000000, 0.166769, 0.985996, 0.000000, 0.248690, 0.968583, 1.000000, 0.248690, 0.968583, 0.000000, 0.328867, 0.944376, 1.000000, 0.328867, 0.944376, 0.000000, 0.406737, 0.913545, 1.000000, 0.406737, 0.913545, 0.000000, 0.481754, 0.876307, 1.000000, 0.481754, 0.876307, 0.000000, 0.553392, 0.832921, 1.000000, 0.553392, 0.832921, 0.000000, 0.621148, 0.783693, 1.000000, 0.621148, 0.783693, 0.000000, 0.684547, 0.728969, 1.000000, 0.684547, 0.728969, 0.000000, 0.743145, 0.669131, 1.000000, 0.743145, 0.669131, 0.000000, 0.796530, 0.604599, 1.000000, 0.796530, 0.604599, 0.000000, 0.844328, 0.535827, 1.000000, 0.844328, 0.535827, 0.000000, 0.886204, 0.463296, 1.000000, 0.886204, 0.463296, 0.000000, 0.921863, 0.387516, 1.000000, 0.921863, 0.387516, 0.000000, 0.951057, 0.309017, 1.000000, 0.951057, 0.309017, 0.000000, 0.973579, 0.228351, 1.000000, 0.973579, 0.228351, 0.000000, 0.989272, 0.146083, 1.000000, 0.989272, 0.146083, 0.000000, 0.998027, 0.062790, 1.000000, 0.998027, 0.062790, 0.000000, 0.999781, -0.020942, 1.000000, 0.999781, -0.020942, 0.000000, 0.994522, -0.104529, 1.000000, 0.994522, -0.104529, 0.000000, 0.982287, -0.187381, 1.000000, 0.982287, -0.187381, 0.000000, 0.963163, -0.268920, 1.000000, 0.963163, -0.268920, 0.000000, 0.937282, -0.348572, 1.000000, 0.937282, -0.348572, 0.000000, 0.904827, -0.425779, 1.000000, 0.904827, -0.425779, 0.000000, 0.866025, -0.500000, 1.000000, 0.866025, -0.500000, 0.000000, 0.821149, -0.570714, 1.000000, 0.821149, -0.570714, 0.000000, 0.770513, -0.637424, 1.000000, 0.770513, -0.637424, 0.000000, 0.714473, -0.699663, 1.000000, 0.714473, -0.699663, 0.000000, 0.653421, -0.756995, 1.000000, 0.653421, -0.756995, 0.000000, 0.587785, -0.809017, 1.000000, 0.587785, -0.809017, 0.000000, 0.518027, -0.855364, 1.000000, 0.518027, -0.855364, 0.000000, 0.444635, -0.895712, 1.000000, 0.444635, -0.895712, 0.000000, 0.368125, -0.929776, 1.000000, 0.368125, -0.929776, 0.000000, 0.289032, -0.957319, 1.000000, 0.289032, -0.957319, 0.000000, 0.207912, -0.978148, 1.000000, 0.207912, -0.978148, 0.000000, 0.125333, -0.992115, 1.000000, 0.125333, -0.992115, 0.000000, 0.041876, -0.999123, 1.000000, 0.041876, -0.999123, 0.000000, -0.041876, -0.999123, 1.000000, -0.041876, -0.999123, 0.000000, -0.125333, -0.992115, 1.000000, -0.125333, -0.992115, 0.000000, -0.207912, -0.978148, 1.000000, -0.207912, -0.978148, 0.000000, -0.289032, -0.957319, 1.000000, -0.289032, -0.957319, 0.000000, -0.368125, -0.929776, 1.000000, -0.368125, -0.929776, 0.000000, -0.444635, -0.895712, 1.000000, -0.444635, -0.895712, 0.000000, -0.518027, -0.855364, 1.000000, -0.518027, -0.855364, 0.000000, -0.587785, -0.809017, 1.000000, -0.587785, -0.809017, 0.000000, -0.653421, -0.756995, 1.000000, -0.653421, -0.756995, 0.000000, -0.714473, -0.699663, 1.000000, -0.714473, -0.699663, 0.000000, -0.770513, -0.637424, 1.000000, -0.770513, -0.637424, 0.000000, -0.821149, -0.570714, 1.000000, -0.821149, -0.570714, 0.000000, -0.866025, -0.500000, 1.000000, -0.866025, -0.500000, 0.000000, -0.904827, -0.425779, 1.000000, -0.904827, -0.425779, 0.000000, -0.937282, -0.348572, 1.000000, -0.937282, -0.348572, 0.000000, -0.963163, -0.268920, 1.000000, -0.963163, -0.268920, 0.000000, -0.982287, -0.187381, 1.000000, -0.982287, -0.187381, 0.000000, -0.994522, -0.104528, 1.000000, -0.994522, -0.104528, 0.000000, -0.999781, -0.020943, 1.000000, -0.999781, -0.020943, 0.000000, -0.998027, 0.062791, 1.000000, -0.998027, 0.062791, 0.000000, -0.989272, 0.146083, 1.000000, -0.989272, 0.146083, 0.000000, -0.973579, 0.228351, 1.000000, -0.973579, 0.228351, 0.000000, -0.951056, 0.309017, 1.000000, -0.951056, 0.309017, 0.000000, -0.921863, 0.387515, 1.000000, -0.921863, 0.387515, 0.000000, -0.886204, 0.463296, 1.000000, -0.886204, 0.463296, 0.000000, -0.844328, 0.535827, 1.000000, -0.844328, 0.535827, 0.000000, -0.796530, 0.604599, 1.000000, -0.796530, 0.604599, 0.000000, -0.743145, 0.669131, 1.000000, -0.743145, 0.669131, 0.000000, -0.684547, 0.728969, 1.000000, -0.684547, 0.728969, 0.000000, -0.621148, 0.783693, 1.000000, -0.621148, 0.783693, 0.000000, -0.553392, 0.832921, 1.000000, -0.553392, 0.832921, 0.000000, -0.481754, 0.876307, 1.000000, -0.481754, 0.876307, 0.000000, -0.406736, 0.913546, 1.000000, -0.406736, 0.913546, 0.000000, -0.328867, 0.944376, 1.000000, -0.328867, 0.944376, 0.000000, -0.248690, 0.968583, 1.000000, -0.248690, 0.968583, 0.000000, -0.166769, 0.985996, 1.000000, -0.166769, 0.985996, 0.000000, -0.083678, 0.996493, 1.000000, -0.083678, 0.996493, 0.000000, 0.000000, 1.000000, 1.000000, 0.000000, 1.000000, 0.000000 }; IDirect3DVertexShader9 *d3d_BeamVS = NULL; IDirect3DPixelShader9 *d3d_BeamPS = NULL; IDirect3DVertexDeclaration9 *d3d_BeamDecl = NULL; IDirect3DVertexBuffer9 *d3d_BeamBuffer = NULL; void Beam_LoadObjects (void) { float *beamverts = NULL; d3d_Device->CreateVertexBuffer ( sizeof (cylinderverts), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &d3d_BeamBuffer, NULL ); d3d_BeamBuffer->Lock (0, 0, (void **) &beamverts, 0); memcpy (beamverts, cylinderverts, sizeof (cylinderverts)); d3d_BeamBuffer->Unlock (); D3DVERTEXELEMENT9 decllayout[] = { VDECL (0, 0, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0), D3DDECL_END () }; d3d_Device->CreateVertexDeclaration (decllayout, &d3d_BeamDecl); d3d_BeamVS = D3D_CreateVertexShader (IDR_BEAMFX, "BeamVS"); d3d_BeamPS = D3D_CreatePixelShader (IDR_BEAMFX, "BeamPS"); } void Beam_Shutdown (void) { SAFE_RELEASE (d3d_BeamBuffer); SAFE_RELEASE (d3d_BeamDecl); SAFE_RELEASE (d3d_BeamVS); SAFE_RELEASE (d3d_BeamPS); } void R_DrawBeam (entity_t *e) { float dir[3], len, ang, rad; const float beam_epsilon = 0.000001f; VectorSubtract (e->oldorigin, e->origin, dir); // catch 0 length beams if ((len = DotProduct (dir, dir)) < beam_epsilon) return; // handle the degenerate case of z1 == z2 with an approximation // (should we not just rotate around a different axis instead?) if (fabs (dir[2]) < beam_epsilon) dir[2] = beam_epsilon; // we already got the dotproduct so we just need to sqrt it here ang = 57.2957795f * acos (dir[2] / (len = sqrt (len))) * ((dir[2] < 0.0f) ? -1.0f : 1.0f); // get proper radius rad = (float) e->frame / 2.0f; // we can't scale the matrix as scaling needs to be done before the matrix multiply so we do it separately in the vs instead QMATRIX LocalMatrix (&d3d_MVPMatrix); LocalMatrix.Translate (e->origin); LocalMatrix.Rotate (ang, -dir[1] * dir[2], dir[0] * dir[2], 0.0f); d3d_State->SetVertexShaderConstant4fv (8, LocalMatrix.m16, 4); d3d_State->SetVertexShaderConstant3f (12, rad, rad, len); d3d_State->SetVertexShaderConstant4f ( 13, ((byte *) &d_8to24table_rgba[e->skinnum & 0xff])[0] / 255.0f, ((byte *) &d_8to24table_rgba[e->skinnum & 0xff])[1] / 255.0f, ((byte *) &d_8to24table_rgba[e->skinnum & 0xff])[2] / 255.0f, e->alpha ); d3d_State->SetVertexShader (d3d_BeamVS); d3d_State->SetPixelShader (d3d_BeamPS); d3d_State->SetVertexDeclaration (d3d_BeamDecl); d3d_State->SetStreamSource (0, d3d_BeamBuffer, 0, sizeof (float) * 3); d3d_Device->DrawPrimitive (D3DPT_TRIANGLESTRIP, 0, NUM_CYLINDER_VERTS - 2); c_draw_calls++; }