├── .gitattributes ├── .gitignore ├── App.config ├── Bloom.cs ├── Client.cs ├── ClientEffect.cs ├── ClientEntity.cs ├── ClientMain.cs ├── ClientParse.cs ├── ClientView.cs ├── Common.cs ├── Config.cs ├── Content ├── Q2BSPContent.contentproj ├── SpriteFont1.spritefont ├── bloom.fx ├── blur.fx ├── effects20.fx ├── effects30.fx ├── generic.fx ├── skins.fx └── textures.fx ├── Files.cs ├── Game.ico ├── GameThumbnail.png ├── Gamma.cs ├── Image.cs ├── Input.cs ├── Library ├── Command.cs ├── Script.cs └── TargaImage.cs ├── Light.cs ├── Local.cs ├── Main.cs ├── Model.cs ├── PointLight.cs ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── Q2BSP.cs ├── Q2BSP.csproj ├── Q2BSP.sln ├── Q2Game.cs ├── Q2MD2.cs ├── Server.cs ├── Shared.cs ├── Sky.cs └── Surface.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 105 | -------------------------------------------------------------------------------- /Bloom.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Graphics; 31 | using System.Text; 32 | 33 | namespace Q2BSP 34 | { 35 | public class CBloom 36 | { 37 | public int BlurAmount; 38 | private SpriteBatch spriteBatch; 39 | 40 | private RenderTarget2D RenderTargetScene; 41 | private RenderTarget2D RenderTarget1; 42 | private RenderTarget2D RenderTarget2; 43 | 44 | /// 45 | /// Setup 46 | /// ----- 47 | /// Create the render targets used by the bloom postprocess 48 | /// 49 | public void Setup() 50 | { 51 | int Width; 52 | int Height; 53 | SurfaceFormat Format; 54 | 55 | // get the resolution and format of our main backbuffer 56 | PresentationParameters pp = CProgram.gQ2Game.gGraphicsDevice.PresentationParameters; 57 | 58 | Width = pp.BackBufferWidth; 59 | Height = pp.BackBufferHeight; 60 | Format = pp.BackBufferFormat; 61 | 62 | // create a texture for rendering the main scene, prior to applying bloom. 63 | RenderTargetScene = new RenderTarget2D(CProgram.gQ2Game.gGraphicsDevice, Width, Height, false, Format, pp.DepthStencilFormat, pp.MultiSampleCount, RenderTargetUsage.DiscardContents); 64 | 65 | // create two render targets for bloom processing half the size of the backbuffer 66 | Width /= 2; 67 | Height /= 2; 68 | RenderTarget1 = new RenderTarget2D(CProgram.gQ2Game.gGraphicsDevice, Width, Height); 69 | RenderTarget2 = new RenderTarget2D(CProgram.gQ2Game.gGraphicsDevice, Width, Height); 70 | 71 | BlurAmount = 4; 72 | spriteBatch = new SpriteBatch(CProgram.gQ2Game.gGraphicsDevice); 73 | } 74 | 75 | /// 76 | /// DrawBloom 77 | /// --------- 78 | /// This should be called at the very start of the scene rendering. The bloom component uses it to redirect drawing into its custom rendertarget, 79 | /// so it can capture the scene image in preparation for applying the bloom filter. 80 | /// 81 | public void DrawBloom() 82 | { 83 | if (CProgram.gQ2Game.gCMain.r_bloom == false) 84 | return; 85 | 86 | if (CProgram.gQ2Game.gCMain.r_wireframe == true) 87 | return; 88 | 89 | CProgram.gQ2Game.gGraphicsDevice.SetRenderTarget(RenderTargetScene); 90 | } 91 | 92 | /// 93 | /// Draw 94 | /// ---- 95 | /// Process and draw the bloom postprocess 96 | /// 97 | public void Draw() 98 | { 99 | if (CProgram.gQ2Game.gCMain.r_bloom == false) 100 | return; 101 | 102 | if (CProgram.gQ2Game.gCMain.r_wireframe == true) 103 | return; 104 | 105 | CProgram.gQ2Game.gGraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp; 106 | 107 | 108 | // pass 1 109 | // draw the scene into render target 1, using a shader that extracts only the brightest pixels 110 | DrawQuad(RenderTargetScene, RenderTarget1, "BloomExtract", IntermediateBuffer.PreBloom); 111 | 112 | 113 | // pass 2 114 | // draw from render target 1 into render target 2, applying a horizontal gaussian blur filter 115 | SetBlurEffectParameters(1.0f / (float)RenderTarget1.Width, 0.0f); 116 | DrawQuad(RenderTarget1, RenderTarget2, "GaussianBlur", IntermediateBuffer.BlurredHorizontally); 117 | 118 | 119 | // pass 3 120 | // draw from render target 2 back into render target 1, applying a vertical gaussian blur filter 121 | SetBlurEffectParameters(0.0f, 1.0f / (float)RenderTarget1.Height); 122 | DrawQuad(RenderTarget2, RenderTarget1, "GaussianBlur", IntermediateBuffer.BlurredBothWays); 123 | 124 | 125 | // pass 4 126 | // draw both render target 1 and the original scene texture back into the backbuffer 127 | // using a shader that combines them to produce the final bloomed result 128 | CProgram.gQ2Game.gGraphicsDevice.SetRenderTarget(null); 129 | CProgram.gQ2Game.gGraphicsDevice.Textures[1] = RenderTargetScene; 130 | 131 | 132 | CProgram.gQ2Game.gGraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0); 133 | DrawQuad(RenderTarget1, CProgram.gQ2Game.gGraphicsDevice.Viewport.Width, CProgram.gQ2Game.gGraphicsDevice.Viewport.Height, "BloomCombine", IntermediateBuffer.FinalResult); 134 | } 135 | 136 | private void DrawQuad(Texture2D texture, RenderTarget2D RenderTarget, string Technique, IntermediateBuffer currentBuffer) 137 | { 138 | CProgram.gQ2Game.gGraphicsDevice.SetRenderTarget(RenderTarget); 139 | DrawQuad(texture, RenderTarget.Width, RenderTarget.Height, Technique, currentBuffer); 140 | CProgram.gQ2Game.gGraphicsDevice.SetRenderTarget(null); 141 | } 142 | 143 | private void DrawQuad(Texture2D texture, int Width, int Height, string Technique, IntermediateBuffer currentBuffer) 144 | { 145 | // if the user has selected one of the show intermediate buffer options, we still draw the quad to make sure the image will end up on the screen, 146 | // but might need to skip applying the custom pixel shader. 147 | if (IntermediateBuffer.FinalResult < currentBuffer) 148 | CProgram.gQ2Game.gEffect = null; 149 | else 150 | CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques[Technique]; 151 | 152 | spriteBatch.Begin(0, BlendState.Opaque, null, null, null, CProgram.gQ2Game.gEffect); 153 | spriteBatch.Draw(texture, new Rectangle(0, 0, Width, Height), Color.White); 154 | spriteBatch.End(); 155 | } 156 | 157 | /// 158 | /// SetBlurEffectParameters 159 | /// ----------------------- 160 | /// Computes sample weightings and texture coordinate offsets 161 | /// for one pass of a separable gaussian blur filter 162 | /// 163 | private void SetBlurEffectParameters(float dx, float dy) 164 | { 165 | EffectParameter weightsParameter; 166 | EffectParameter offsetsParameter; 167 | int sampleCount; 168 | float[] sampleWeights; 169 | Vector2[] sampleOffsets; 170 | float totalWeights; 171 | 172 | // get the sample weight and offset effect parameters 173 | weightsParameter = CProgram.gQ2Game.gEffect.Parameters["SampleWeights"]; 174 | offsetsParameter = CProgram.gQ2Game.gEffect.Parameters["SampleOffsets"]; 175 | 176 | // get the amount of samples our gaussian blur effect supports 177 | sampleCount = weightsParameter.Elements.Count; 178 | 179 | // create temporary arrays for computing our filter settings 180 | sampleWeights = new float[sampleCount]; 181 | sampleOffsets = new Vector2[sampleCount]; 182 | 183 | // the first sample always has a zero offset 184 | sampleWeights[0] = ComputeGaussian(0, BlurAmount); 185 | sampleOffsets[0] = new Vector2(0); 186 | 187 | // maintain a sum of all the weighting values 188 | totalWeights = sampleWeights[0]; 189 | 190 | // add pairs of additional sample taps, positioned along a line in both directions from the center 191 | for (int i = 0; i < sampleCount / 2; i++) 192 | { 193 | float weight; 194 | float sampleOffset; 195 | Vector2 delta; 196 | 197 | // store weights for the positive and negative taps 198 | weight = ComputeGaussian(i + 1, BlurAmount); 199 | sampleWeights[i * 2 + 1] = weight; 200 | sampleWeights[i * 2 + 2] = weight; 201 | totalWeights += weight * 2; 202 | 203 | // To get the maximum amount of blurring from a limited number of pixel shader samples, 204 | // we take advantage of the bilinear filtering hardware inside the texture fetch unit. 205 | // If we position our texture coordinates exactly halfway between two texels, the filtering 206 | // unit will average them for us, giving two samples for the price of one. 207 | // This allows us to step in units of two texels per sample, rather than just one at a time. 208 | // The 1.5 offset kicks things off by positioning us nicely in between two texels. 209 | sampleOffset = i * 2 + 1.5f; 210 | 211 | delta = new Vector2(dx, dy) * sampleOffset; 212 | 213 | // store texture coordinate offsets for the positive and negative taps 214 | sampleOffsets[i * 2 + 1] = delta; 215 | sampleOffsets[i * 2 + 2] = -delta; 216 | } 217 | 218 | // normalize the list of sample weightings, so they will always sum to one 219 | for (int i = 0; i < sampleWeights.Length; i++) 220 | { 221 | sampleWeights[i] /= totalWeights; 222 | } 223 | 224 | // tell the effect about our new filter settings 225 | weightsParameter.SetValue(sampleWeights); 226 | offsetsParameter.SetValue(sampleOffsets); 227 | } 228 | 229 | /// 230 | /// Evaluates a single point on the gaussian falloff curve. 231 | /// Used for setting up the blur filter weightings. 232 | /// 233 | private float ComputeGaussian(float n, float theta) 234 | { 235 | return (float)((1.0d / Math.Sqrt(2 * Math.PI * theta)) * Math.Exp(-(n * n) / (2 * theta * theta))); 236 | } 237 | 238 | /// 239 | /// Release 240 | /// ------- 241 | /// De-allocate the render targets used by the bloom postprocess 242 | /// 243 | public void Release() 244 | { 245 | if (RenderTargetScene != null) 246 | RenderTargetScene.Dispose(); 247 | 248 | if (RenderTarget1 != null) 249 | RenderTarget1.Dispose(); 250 | 251 | if (RenderTarget2 != null) 252 | RenderTarget2.Dispose(); 253 | } 254 | 255 | 256 | public enum IntermediateBuffer 257 | { 258 | PreBloom, 259 | BlurredHorizontally, 260 | BlurredBothWays, 261 | FinalResult, 262 | } 263 | 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /Client.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using System.Text; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CClient 35 | { 36 | public const int CMD_BACKUP = 64; // allow a lot of command backups for very fast systems 37 | 38 | public static SClientState cl; 39 | 40 | 41 | // the SClientState structure is wiped completely at every server map change 42 | public struct SClientState 43 | { 44 | public int timeoutcount; 45 | 46 | public int timedemo_frames; 47 | public int timedemo_start; 48 | 49 | public bool refresh_prepped; // false if on new level or new ref dll 50 | public bool sound_prepped; // ambient sounds can start 51 | public bool force_refdef; // vid has changed, so we can't use a paused refdef 52 | 53 | public int parse_entities; // index (not anded off) into cl_parse_entities[] 54 | 55 | //usercmd_t cmd; 56 | //usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds 57 | public int[] cmd_time; // size: CMD_BACKUP (time sent, for calculating pings) 58 | public short[,] predicted_origins; // size: [CMD_BACKUP, 3] (for debug comparing against server) 59 | 60 | public float predicted_step; // for stair up smoothing 61 | public uint predicted_step_time; 62 | 63 | public Vector3 predicted_origin; // generated by CL_PredictMovement 64 | public Vector3 predicted_angles; 65 | public Vector3 prediction_error; 66 | 67 | //frame_t frame; // received from server 68 | public int surpressCount; // number of messages rate supressed 69 | //frame_t frames[UPDATE_BACKUP]; 70 | 71 | // the client maintains its own idea of view angles, which are sent to the server each frame. 72 | // It is cleared to 0 upon entering each level. The server sends a delta each frame which is added to the 73 | // locally tracked view angles to account for standing on rotating objects, and teleport direction changes 74 | public Vector3 viewangles; 75 | 76 | public int time; // this is the time value that the client is rendering at. Always <= cls.realtime 77 | public int lerpfrac; // between oldframe and frame 78 | 79 | public CLocal.SRefDef RefDef; 80 | 81 | // set when refdef.angles is set 82 | public Vector3 v_forward; 83 | public Vector3 v_right; 84 | public Vector3 v_up; 85 | 86 | // 87 | // transient data from server 88 | // 89 | public string layout; // size: 1024 (general 2D overlay) 90 | public int[] inventory; // size: MAX_ITEMS 91 | 92 | // 93 | // non-gameserver information 94 | // FIXME: move this cinematic stuff into the cin_t structure 95 | //FILE *cinematic_file; 96 | public int cinematictime; // cls.realtime for first cinematic frame 97 | public int cinematicframe; 98 | public byte[] cinematicpalette; // size: 768 99 | public bool cinematicpalette_active; 100 | 101 | 102 | // 103 | // server state information 104 | // 105 | public bool attractloop; // running the attract loop, any key will menu 106 | public int servercount; // server identification for prespawns 107 | public string gamedir; // size: MAX_QPATH 108 | public int playernum; 109 | public string[] configstrings; // size: [MAX_CONFIGSTRINGS,MAX_QPATH] 110 | 111 | 112 | // 113 | // locally derived information from server state 114 | // 115 | //struct model_s *model_draw[MAX_MODELS]; 116 | //struct cmodel_s *model_clip[MAX_MODELS]; 117 | 118 | //struct sfx_s *sound_precache[MAX_SOUNDS]; 119 | //struct image_s *image_precache[MAX_IMAGES]; 120 | 121 | //clientinfo_t clientinfo[MAX_CLIENTS]; 122 | //clientinfo_t baseclientinfo; 123 | } 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /ClientEffect.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CClientEffect 34 | { 35 | // ============================================================== 36 | // 37 | // LIGHT STYLE MANAGEMENT 38 | // 39 | // ============================================================== 40 | public SCLightStyle[] cl_lightstyle; 41 | public int lastofs; 42 | 43 | public CClientEffect() 44 | { 45 | cl_lightstyle = new SCLightStyle[CLocal.MAX_LIGHTSTYLES]; 46 | 47 | for (int i = 0; i < CLocal.MAX_LIGHTSTYLES; i++) 48 | { 49 | cl_lightstyle[i].length = 0; 50 | cl_lightstyle[i].value = new float[3]; 51 | cl_lightstyle[i].map = new float[CShared.MAX_QPATH]; 52 | } 53 | } 54 | 55 | public void CL_ClearLightStyles() 56 | { 57 | for (int i = 0; i < cl_lightstyle.Length; i++) 58 | { 59 | cl_lightstyle[i].length = 0; 60 | 61 | for (int j = 0; j < cl_lightstyle[i].value.Length; j++) 62 | { 63 | cl_lightstyle[i].value[j] = 0.0f; 64 | } 65 | 66 | for (int j = 0; j < cl_lightstyle[i].map.Length; j++) 67 | { 68 | cl_lightstyle[i].map[j] = 0.0f; 69 | } 70 | } 71 | 72 | lastofs = -1; 73 | } 74 | 75 | public void CL_RunLightStyles() 76 | { 77 | int ofs; 78 | 79 | ofs = (int)(CProgram.gQ2Game.gCMain.gTimeGame.TotalGameTime.TotalMilliseconds / 1000.0f); 80 | if (ofs == lastofs) 81 | return; 82 | 83 | lastofs = ofs; 84 | 85 | for (int i = 0; i < CLocal.MAX_LIGHTSTYLES; i++) 86 | { 87 | if (cl_lightstyle[i].length == 0) 88 | { 89 | cl_lightstyle[i].value[0] = cl_lightstyle[i].value[1] = cl_lightstyle[i].value[2] = 1.0f; 90 | continue; 91 | } 92 | 93 | if (cl_lightstyle[i].length == 1) 94 | cl_lightstyle[i].value[0] = cl_lightstyle[i].value[1] = cl_lightstyle[i].value[2] = cl_lightstyle[i].map[0]; 95 | else 96 | cl_lightstyle[i].value[0] = cl_lightstyle[i].value[1] = cl_lightstyle[i].value[2] = cl_lightstyle[i].map[ofs % cl_lightstyle[i].length]; 97 | } 98 | } 99 | 100 | public void CL_SetLightstyle(int i) 101 | { 102 | int len; 103 | string s; 104 | 105 | s = CClient.cl.configstrings[CShared.CS_LIGHTS + i]; 106 | len = s.Length; 107 | 108 | if (len >= CShared.MAX_QPATH) 109 | CMain.Error(CMain.EErrorParm.ERR_WARNING, "svc_lightstyle length=" + len.ToString()); 110 | 111 | cl_lightstyle[i].length = len; 112 | 113 | for (int j = 0; j < len; j++) 114 | { 115 | cl_lightstyle[i].map[j] = (float)(s[j] - 'a') / (float)('m' - 'a'); 116 | } 117 | } 118 | 119 | public void CL_AddLightStyles() 120 | { 121 | for (int i = 0; i < CLocal.MAX_LIGHTSTYLES; i++) 122 | { 123 | CProgram.gQ2Game.gCCommon.gCClientMain.gCClientView.V_AddLightStyle(i, cl_lightstyle[i].value[0], cl_lightstyle[i].value[1], cl_lightstyle[i].value[2]); 124 | } 125 | } 126 | 127 | public void CL_ClearEffects() 128 | { 129 | CL_ClearLightStyles(); 130 | } 131 | 132 | public struct SCLightStyle 133 | { 134 | public int length; 135 | public float[] value; // size: 3 136 | public float[] map; // size: MAX_QPATH 137 | } 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /ClientEntity.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CClientEntity 34 | { 35 | public void CL_AddEntities() 36 | { 37 | CProgram.gQ2Game.gCCommon.gCClientMain.gCClientEffect.CL_AddLightStyles(); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ClientMain.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CClientMain 34 | { 35 | public CClientParse gCClientParse; 36 | public CClientEffect gCClientEffect; 37 | public CClientView gCClientView; 38 | public CClientEntity gCClientEntity; 39 | 40 | public CClientMain() 41 | { 42 | gCClientParse = new CClientParse(); 43 | gCClientEffect = new CClientEffect(); 44 | gCClientView = new CClientView(); 45 | gCClientEntity = new CClientEntity(); 46 | 47 | 48 | 49 | // TEMPORARY! (SHOULD BE IN SP_WORLDSPAWN) 50 | if (CClient.cl.configstrings == null) 51 | CClient.cl.configstrings = new string[CShared.MAX_CONFIGSTRINGS]; 52 | 53 | // setup light animation tables. 'a' is total darkness, 'z' is doublebright. 54 | 55 | // 0 normal 56 | CClient.cl.configstrings[CShared.CS_LIGHTS + 0] = "m"; 57 | 58 | // 1 FLICKER (first variety) 59 | CClient.cl.configstrings[CShared.CS_LIGHTS + 1] = "mmnmmommommnonmmonqnmmo"; 60 | 61 | // 2 SLOW STRONG PULSE 62 | CClient.cl.configstrings[CShared.CS_LIGHTS + 2] = "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"; 63 | 64 | // 3 CANDLE (first variety) 65 | CClient.cl.configstrings[CShared.CS_LIGHTS + 3] = "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"; 66 | 67 | // 4 FAST STROBE 68 | CClient.cl.configstrings[CShared.CS_LIGHTS + 4] = "mamamamamama"; 69 | 70 | // 5 GENTLE PULSE 1 71 | CClient.cl.configstrings[CShared.CS_LIGHTS + 5] = "jklmnopqrstuvwxyzyxwvutsrqponmlkj"; 72 | 73 | // 6 FLICKER (second variety) 74 | CClient.cl.configstrings[CShared.CS_LIGHTS + 6] = "nmonqnmomnmomomno"; 75 | 76 | // 7 CANDLE (second variety) 77 | CClient.cl.configstrings[CShared.CS_LIGHTS + 7] = "mmmaaaabcdefgmmmmaaaammmaamm"; 78 | 79 | // 8 CANDLE (third variety) 80 | CClient.cl.configstrings[CShared.CS_LIGHTS + 8] = "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"; 81 | 82 | // 9 SLOW STROBE (fourth variety) 83 | CClient.cl.configstrings[CShared.CS_LIGHTS + 9] = "aaaaaaaazzzzzzzz"; 84 | 85 | // 10 FLUORESCENT FLICKER 86 | CClient.cl.configstrings[CShared.CS_LIGHTS + 10] = "mmamammmmammamamaaamammma"; 87 | 88 | // 11 SLOW PULSE NOT FADE TO BLACK 89 | CClient.cl.configstrings[CShared.CS_LIGHTS + 11] = "abcdefghijklmnopqrrqponmlkjihgfedcba"; 90 | 91 | // styles 32-62 are assigned by the light program for switchable lights 92 | 93 | // 63 testing 94 | CClient.cl.configstrings[CShared.CS_LIGHTS + 63] = "a"; 95 | } 96 | 97 | private void CL_ReadPackets() 98 | { 99 | gCClientParse.CL_ParseServerMessage(); 100 | } 101 | 102 | public void CL_Frame(int msec) 103 | { 104 | CL_ReadPackets(); 105 | 106 | gCClientEffect.CL_RunLightStyles(); 107 | } 108 | 109 | public void CL_ClearState() 110 | { 111 | gCClientEffect.CL_ClearEffects(); 112 | } 113 | 114 | public void CL_Disconnect() 115 | { 116 | CL_ClearState(); 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /ClientParse.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CClientParse 34 | { 35 | public string[] svc_strings = 36 | { 37 | "svc_bad", 38 | 39 | "svc_muzzleflash", 40 | "svc_muzzlflash2", 41 | "svc_temp_entity", 42 | "svc_layout", 43 | "svc_inventory", 44 | 45 | "svc_nop", 46 | "svc_disconnect", 47 | "svc_reconnect", 48 | "svc_sound", 49 | "svc_print", 50 | "svc_stufftext", 51 | "svc_serverdata", 52 | "svc_configstring", 53 | "svc_spawnbaseline", 54 | "svc_centerprint", 55 | "svc_download", 56 | "svc_playerinfo", 57 | "svc_packetentities", 58 | "svc_deltapacketentities", 59 | "svc_frame" 60 | }; 61 | 62 | 63 | public void CL_ParseServerData() 64 | { 65 | CProgram.gQ2Game.gCCommon.gCClientMain.CL_ClearState(); 66 | } 67 | 68 | private void CL_ParseConfigString() 69 | { 70 | int i; 71 | string s; 72 | 73 | //i = MSG_ReadShort(&net_message); 74 | //if (i < 0 || i >= MAX_CONFIGSTRINGS) 75 | // Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS"); 76 | //s = MSG_ReadString(&net_message); 77 | 78 | //strncpy(olds, cl.configstrings[i], sizeof(olds)); 79 | //olds[sizeof(olds) - 1] = 0; 80 | 81 | 82 | // jkrige - just temporary setting a fake network message 83 | i = CShared.CS_LIGHTS; 84 | s = "gjrbdwed"; 85 | //if (CClient.cl.configstrings == null) 86 | // CClient.cl.configstrings = new string[CShared.MAX_CONFIGSTRINGS]; 87 | // jkrige - just temporary setting a fake network message 88 | 89 | CClient.cl.configstrings[i] = s; 90 | 91 | // do something apropriate 92 | 93 | if (i >= CShared.CS_LIGHTS && i < CShared.CS_LIGHTS + CShared.MAX_LIGHTSTYLES) 94 | CProgram.gQ2Game.gCCommon.gCClientMain.gCClientEffect.CL_SetLightstyle(i - CShared.CS_LIGHTS); 95 | } 96 | 97 | public void CL_ParseServerMessage() 98 | { 99 | CL_ParseServerData(); 100 | 101 | CL_ParseConfigString(); 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ClientView.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CClientView 34 | { 35 | private CLocal.SLightStyle[] r_lightstyles; 36 | 37 | public CClientView() 38 | { 39 | r_lightstyles = new CLocal.SLightStyle[CLocal.MAX_LIGHTSTYLES]; 40 | 41 | for (int i = 0; i < CLocal.MAX_LIGHTSTYLES; i++) 42 | { 43 | r_lightstyles[i].white = 0; 44 | r_lightstyles[i].rgb = new float[3]; 45 | } 46 | } 47 | 48 | public void V_AddLightStyle(int style, float r, float g, float b) 49 | { 50 | if (style < 0 || style > CShared.MAX_LIGHTSTYLES) 51 | CMain.Error(CMain.EErrorParm.ERR_WARNING, "Bad light style " + style.ToString()); 52 | 53 | r_lightstyles[style].white = r + g + b; 54 | r_lightstyles[style].rgb[0] = r; 55 | r_lightstyles[style].rgb[1] = g; 56 | r_lightstyles[style].rgb[2] = b; 57 | } 58 | 59 | public void V_RenderView() 60 | { 61 | CProgram.gQ2Game.gCCommon.gCClientMain.gCClientEntity.CL_AddEntities(); 62 | 63 | CClient.cl.RefDef.lightstyles = r_lightstyles; 64 | } 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Common.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CCommon 34 | { 35 | public CClientMain gCClientMain; 36 | 37 | // IMPORTANT NOTE: #1 38 | // main.cs will probably be desolved eventually as common.cs will likely be the main entry point 39 | // either that or main.cs will be used via xna draws while common.cs will be used via xna updates 40 | // ...something like that 41 | 42 | // IMPORTANT NOTE: #2 43 | // all the client source code from the common.cs class downwards is not referenced at this time. 44 | // its a guideline for continued development. 45 | 46 | public CCommon() 47 | { 48 | gCClientMain = new CClientMain(); 49 | } 50 | 51 | public void Qcommon_Frame(int msec) 52 | { 53 | //if (host_speeds->value) 54 | // time_before = Sys_Milliseconds(); 55 | 56 | //SV_Frame(msec); 57 | 58 | //if (host_speeds->value) 59 | // time_between = Sys_Milliseconds(); 60 | 61 | gCClientMain.CL_Frame(msec); 62 | 63 | gCClientMain.gCClientView.V_RenderView(); 64 | } 65 | 66 | 67 | public struct SSizeBuf 68 | { 69 | public bool allowoverflow; // if false, do a Com_Error 70 | public bool overflowed; // set to true if the buffer size failed 71 | public byte[] data; 72 | public int maxsize; 73 | public int cursize; 74 | public int readcount; 75 | } 76 | 77 | 78 | // ============================================================== 79 | // 80 | // PROTOCOL 81 | // 82 | // ============================================================== 83 | public const int PROTOCOL_VERSION = 34; 84 | 85 | public const int PORT_MASTER = 27900; 86 | public const int PORT_CLIENT = 27901; 87 | public const int PORT_SERVER = 27910; 88 | 89 | public const int UPDATE_BACKUP = 16; // copies of entity_state_t to keep buffered, must be power of two 90 | public const int UPDATE_MASK = UPDATE_BACKUP - 1; 91 | 92 | // the svc_strings[] array in ClientParse.cs should mirror this. 93 | 94 | // server to client 95 | public enum ESVC_Ops 96 | { 97 | svc_bad, 98 | 99 | // these ops are known to the game dll 100 | svc_muzzleflash, 101 | svc_muzzleflash2, 102 | svc_temp_entity, 103 | svc_layout, 104 | svc_inventory, 105 | 106 | // the rest are private to the client and server 107 | svc_nop, 108 | svc_disconnect, 109 | svc_reconnect, 110 | svc_sound, // 111 | svc_print, // [byte] id [string] null terminated string 112 | svc_stufftext, // [string] stuffed into client's console buffer, should be \n terminated 113 | svc_serverdata, // [long] protocol ... 114 | svc_configstring, // [short] [string] 115 | svc_spawnbaseline, 116 | svc_centerprint, // [string] to put in center of the screen 117 | svc_download, // [short] size [size bytes] 118 | svc_playerinfo, // variable 119 | svc_packetentities, // [...] 120 | svc_deltapacketentities, // [...] 121 | svc_frame 122 | } 123 | 124 | // client to server 125 | public enum ECLC_Ops 126 | { 127 | clc_bad, 128 | clc_nop, 129 | clc_move, // [[usercmd_t] 130 | clc_userinfo, // [[userinfo string] 131 | clc_stringcmd // [string] message 132 | }; 133 | 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Config.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Configuration; 30 | using System.Text; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CConfig 35 | { 36 | /// 37 | /// Gets the value of a configuration setting key and attempts to return its value as a boolean 38 | /// 39 | /// The configuration setting key 40 | /// Returns configuration setting key value as a boolean 41 | public static bool GetConfigBOOL(string KeyName) 42 | { 43 | bool KeyValue; 44 | 45 | try 46 | { 47 | KeyValue = Convert.ToBoolean(ConfigurationManager.AppSettings[KeyName].ToString()); 48 | } 49 | catch 50 | { 51 | KeyValue = false; 52 | } 53 | 54 | return KeyValue; 55 | } 56 | 57 | /// 58 | /// Gets the value of a configuration setting key and attempts to return its value as a string 59 | /// 60 | /// The configuration setting key 61 | /// Returns configuration setting key value as a string 62 | public static string GetConfigSTRING(string KeyName) 63 | { 64 | string KeyValue; 65 | 66 | try 67 | { 68 | KeyValue = ConfigurationManager.AppSettings[KeyName].ToString(); 69 | } 70 | catch 71 | { 72 | KeyValue = null; 73 | } 74 | 75 | return KeyValue; 76 | } 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Content/Q2BSPContent.contentproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {29204DFD-5723-48DB-AC99-A8208752E4F1} 5 | {96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | x86 8 | Library 9 | Properties 10 | v4.0 11 | v4.0 12 | x86 13 | bin\$(Platform)\$(Configuration) 14 | Content 15 | http://localhost/Q2BSPContent/ 16 | true 17 | Web 18 | true 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | true 28 | false 29 | true 30 | 31 | 32 | Windows 33 | AllRules.ruleset 34 | 35 | 36 | Windows 37 | AllRules.ruleset 38 | 39 | 40 | 41 | False 42 | 43 | 44 | False 45 | 46 | 47 | False 48 | 49 | 50 | False 51 | 52 | 53 | False 54 | 55 | 56 | False 57 | 58 | 59 | 60 | 61 | SpriteFont1 62 | FontDescriptionImporter 63 | FontDescriptionProcessor 64 | 65 | 66 | 67 | 68 | effects20 69 | EffectImporter 70 | EffectProcessor 71 | 72 | 73 | effects30 74 | EffectImporter 75 | EffectProcessor 76 | 77 | 78 | bloom 79 | EffectImporter 80 | EffectProcessor 81 | 82 | 83 | blur 84 | EffectImporter 85 | EffectProcessor 86 | 87 | 88 | generic 89 | EffectImporter 90 | EffectProcessor 91 | 92 | 93 | skins 94 | EffectImporter 95 | EffectProcessor 96 | 97 | 98 | textures 99 | EffectImporter 100 | EffectProcessor 101 | 102 | 103 | 104 | 105 | False 106 | Microsoft .NET Framework 4 %28x86 and x64%29 107 | true 108 | 109 | 110 | False 111 | .NET Framework 3.5 SP1 Client Profile 112 | false 113 | 114 | 115 | False 116 | .NET Framework 3.5 SP1 117 | false 118 | 119 | 120 | False 121 | Windows Installer 3.1 122 | true 123 | 124 | 125 | 126 | 133 | -------------------------------------------------------------------------------- /Content/SpriteFont1.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | Verdana 15 | 16 | 20 | 10 21 | 22 | 26 | 1 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | 45 | 46 | 53 | 54 | 55 | 56 | ~ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Content/bloom.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | 28 | // The initial phase of implementing bloom postprocess is to extract the brighter areas of a given image 29 | float4 BloomExtractPS(float2 texCoord : TEXCOORD0) : COLOR0 30 | { 31 | // get the original texture pixel color 32 | float4 Color = tex2D(TextureSampler, texCoord); 33 | 34 | // only retain the values that are brighter than the specified threshold 35 | return saturate((Color - xBloomThreshold) / (1 - xBloomThreshold)); 36 | } 37 | 38 | 39 | // The final phase of implementing bloom postprocess is to combine the bloom image with the original scene 40 | sampler BaseSampler : register(s1); 41 | sampler BloomSampler : register(s0); 42 | 43 | float4 AdjustSaturation(float4 Color, float Saturation) 44 | { 45 | // the constants 0.3, 0.59 and 0.11 are chosen because the human eye 46 | // is more sensitive to green light and less to blue light. 47 | float Gray = dot(Color, float3(0.3, 0.59, 0.11)); 48 | 49 | return lerp(Gray, Color, Saturation); 50 | } 51 | 52 | float4 BloomCombinePS(float2 texCoord : TEXCOORD0) : COLOR0 53 | { 54 | // get the original base texture pixel color as well as the bloom pixel color 55 | float4 base = tex2D(BaseSampler, texCoord); 56 | float4 bloom = tex2D(BloomSampler, texCoord); 57 | 58 | // adjust pixel color saturation and intensity 59 | base = AdjustSaturation(base, xBaseSaturation) * xBaseIntensity; 60 | bloom = AdjustSaturation(bloom, xBloomSaturation) * xBloomIntensity; 61 | 62 | // darken the base image in areas where there is a lot of bloom 63 | // to prevent things looking excessively burned-out. 64 | base *= (1 - saturate(bloom)); 65 | 66 | return base + bloom; 67 | } 68 | -------------------------------------------------------------------------------- /Content/blur.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | 28 | // Applies a one dimensional gaussian blur filter 29 | #define SAMPLE_COUNT 15 30 | 31 | float2 SampleOffsets[SAMPLE_COUNT]; 32 | float SampleWeights[SAMPLE_COUNT]; 33 | 34 | float4 GaussianBlurPS(float2 texCoord : TEXCOORD0) : COLOR0 35 | { 36 | float4 Color = float4(0.0, 0.0, 0.0, 0.0); 37 | 38 | // combine a number of weighted image filter taps 39 | for (int i = 0; i < SAMPLE_COUNT; i++) 40 | { 41 | Color += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i]; 42 | } 43 | 44 | return Color; 45 | } 46 | -------------------------------------------------------------------------------- /Content/effects20.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | #define LIGHT_COUNT 2 28 | 29 | #include "generic.fx" 30 | #include "skins.fx" 31 | #include "textures.fx" 32 | #include "bloom.fx" 33 | #include "blur.fx" 34 | 35 | 36 | // SKINS.FX 37 | technique TexturedSkin 38 | { 39 | pass Pass0 40 | { 41 | VertexShader = compile vs_2_0 TexturedSkinVS(); 42 | PixelShader = compile ps_2_0 TexturedSkinPS(); 43 | } 44 | } 45 | 46 | 47 | // TEXTURES.FX 48 | technique Textured 49 | { 50 | pass Pass0 51 | { 52 | VertexShader = compile vs_2_0 TexturedVS(); 53 | PixelShader = compile ps_2_0 TexturedPS(); 54 | } 55 | } 56 | 57 | technique TexturedLightmap 58 | { 59 | pass Pass0 60 | { 61 | VertexShader = compile vs_2_0 TexturedVS(); 62 | PixelShader = compile ps_2_0 TexturedLightmapPS(); 63 | } 64 | } 65 | 66 | technique TexturedWarped 67 | { 68 | pass Pass0 69 | { 70 | VertexShader = compile vs_2_0 TexturedWarpedVS(); 71 | PixelShader = compile ps_2_0 TexturedPS(); 72 | } 73 | } 74 | 75 | technique TexturedTranslucent 76 | { 77 | pass Pass0 78 | { 79 | AlphaBlendEnable = true; 80 | SrcBlend = SrcAlpha; 81 | DestBlend = InvSrcAlpha; 82 | VertexShader = compile vs_2_0 TexturedVS(); 83 | PixelShader = compile ps_2_0 TexturedTranslucentPS(); 84 | } 85 | } 86 | 87 | technique TexturedWarpedTranslucent 88 | { 89 | pass Pass0 90 | { 91 | AlphaBlendEnable = true; 92 | SrcBlend = SrcAlpha; 93 | DestBlend = InvSrcAlpha; 94 | VertexShader = compile vs_2_0 TexturedWarpedVS(); 95 | PixelShader = compile ps_2_0 TexturedTranslucentPS(); 96 | } 97 | } 98 | 99 | technique TexturedSkybox 100 | { 101 | pass Pass0 102 | { 103 | VertexShader = compile vs_2_0 TexturedSkyboxVS(); 104 | PixelShader = compile ps_2_0 TexturedSkyboxPS(); 105 | } 106 | } 107 | 108 | technique TexturedLight 109 | { 110 | pass Pass0 111 | { 112 | VertexShader = compile vs_2_0 TexturedLightVS(); 113 | PixelShader = compile ps_2_0 TexturedLightPS(); 114 | } 115 | } 116 | 117 | 118 | // BLOOM.FX 119 | technique BloomExtract 120 | { 121 | pass Pass0 122 | { 123 | PixelShader = compile ps_2_0 BloomExtractPS(); 124 | } 125 | } 126 | 127 | technique BloomCombine 128 | { 129 | pass Pass0 130 | { 131 | PixelShader = compile ps_2_0 BloomCombinePS(); 132 | } 133 | } 134 | 135 | 136 | // BLUR.FX (this is used twice by the bloom postprocess, blurring horizontally, then vertically) 137 | technique GaussianBlur 138 | { 139 | pass Pass0 140 | { 141 | PixelShader = compile ps_2_0 GaussianBlurPS(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Content/effects30.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | #define LIGHT_COUNT 8 28 | 29 | #include "generic.fx" 30 | #include "skins.fx" 31 | #include "textures.fx" 32 | #include "bloom.fx" 33 | #include "blur.fx" 34 | 35 | 36 | // SKINS.FX 37 | technique TexturedSkin 38 | { 39 | pass Pass0 40 | { 41 | VertexShader = compile vs_3_0 TexturedSkinVS(); 42 | PixelShader = compile ps_3_0 TexturedSkinPS(); 43 | } 44 | } 45 | 46 | 47 | // TEXTURES.FX 48 | technique Textured 49 | { 50 | pass Pass0 51 | { 52 | VertexShader = compile vs_3_0 TexturedVS(); 53 | PixelShader = compile ps_3_0 TexturedPS(); 54 | } 55 | } 56 | 57 | technique TexturedLightmap 58 | { 59 | pass Pass0 60 | { 61 | VertexShader = compile vs_3_0 TexturedVS(); 62 | PixelShader = compile ps_3_0 TexturedLightmapPS(); 63 | } 64 | } 65 | 66 | technique TexturedWarped 67 | { 68 | pass Pass0 69 | { 70 | VertexShader = compile vs_3_0 TexturedWarpedVS(); 71 | PixelShader = compile ps_3_0 TexturedPS(); 72 | } 73 | } 74 | 75 | technique TexturedTranslucent 76 | { 77 | pass Pass0 78 | { 79 | AlphaBlendEnable = true; 80 | SrcBlend = SrcAlpha; 81 | DestBlend = InvSrcAlpha; 82 | VertexShader = compile vs_3_0 TexturedVS(); 83 | PixelShader = compile ps_3_0 TexturedTranslucentPS(); 84 | } 85 | } 86 | 87 | technique TexturedWarpedTranslucent 88 | { 89 | pass Pass0 90 | { 91 | AlphaBlendEnable = true; 92 | SrcBlend = SrcAlpha; 93 | DestBlend = InvSrcAlpha; 94 | VertexShader = compile vs_3_0 TexturedWarpedVS(); 95 | PixelShader = compile ps_3_0 TexturedTranslucentPS(); 96 | } 97 | } 98 | 99 | technique TexturedSkybox 100 | { 101 | pass Pass0 102 | { 103 | VertexShader = compile vs_3_0 TexturedSkyboxVS(); 104 | PixelShader = compile ps_3_0 TexturedSkyboxPS(); 105 | } 106 | } 107 | 108 | technique TexturedLight 109 | { 110 | pass Pass0 111 | { 112 | VertexShader = compile vs_3_0 TexturedLightVS(); 113 | PixelShader = compile ps_3_0 TexturedLightPS(); 114 | } 115 | } 116 | 117 | 118 | // BLOOM.FX 119 | technique BloomExtract 120 | { 121 | pass Pass0 122 | { 123 | PixelShader = compile ps_3_0 BloomExtractPS(); 124 | } 125 | } 126 | 127 | technique BloomCombine 128 | { 129 | pass Pass0 130 | { 131 | PixelShader = compile ps_3_0 BloomCombinePS(); 132 | } 133 | } 134 | 135 | 136 | // BLUR.FX (this is used twice by the bloom postprocess, blurring horizontally, then vertically) 137 | technique GaussianBlur 138 | { 139 | pass Pass0 140 | { 141 | PixelShader = compile ps_3_0 GaussianBlurPS(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Content/generic.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | struct Light 28 | { 29 | float4 color; 30 | float4 position; 31 | float falloff; 32 | float range; 33 | }; 34 | 35 | struct VertexShaderOutput 36 | { 37 | float4 Position : POSITION; 38 | float2 TextureCoords : TEXCOORD0; 39 | float2 LightmapCoords : TEXCOORD1; 40 | float3 WorldNormal : TEXCOORD2; 41 | float3 WorldPosition : TEXCOORD3; 42 | float4 ambientLightColor : COLOR0; 43 | }; 44 | 45 | struct PixelShaderInput 46 | { 47 | float2 TextureCoords : TEXCOORD0; 48 | float2 LightmapCoords : TEXCOORD1; 49 | float3 WorldNormal : TEXCOORD2; 50 | float3 WorldPosition : TEXCOORD3; 51 | float4 ambientLightColor : COLOR0; 52 | }; 53 | 54 | 55 | struct VertexShaderSkinOutput 56 | { 57 | float4 Position : POSITION; 58 | float2 TextureCoords : TEXCOORD0; 59 | float3 WorldNormal : TEXCOORD2; 60 | float3 WorldPosition : TEXCOORD3; 61 | float4 ambientLightColor : COLOR0; 62 | }; 63 | 64 | struct PixelShaderSkinInput 65 | { 66 | float2 TextureCoords : TEXCOORD0; 67 | float3 WorldNormal : TEXCOORD2; 68 | float3 WorldPosition : TEXCOORD3; 69 | float4 ambientLightColor : COLOR0; 70 | }; 71 | 72 | 73 | struct VertexShaderOutput_Skybox 74 | { 75 | float4 Position : POSITION; 76 | float2 TextureCoords : TEXCOORD0; 77 | float3 WorldPosition : TEXCOORD1; 78 | }; 79 | 80 | struct PixelShaderInput_Skybox 81 | { 82 | float2 TextureCoords : TEXCOORD0; 83 | float3 WorldPosition : TEXCOORD1; 84 | }; 85 | 86 | 87 | // -------- XNA to HLSL variables -------- 88 | float4x4 xView; 89 | float4x4 xProjection; 90 | float4x4 xWorld; 91 | float4 xLightModel; 92 | float4 xLightAmbient; 93 | float xLightPower; 94 | float xTextureAlpha; 95 | float xGamma; 96 | float xRealTime; 97 | float xBloomThreshold; 98 | float xBaseIntensity; 99 | float xBloomIntensity; 100 | float xBaseSaturation; 101 | float xBloomSaturation; 102 | bool xPointLights; 103 | bool xFlow; 104 | 105 | 106 | // 7: GaussianQuad - A 4-sample Gaussian filter used as a texture magnification or minification filter. 107 | // 6: PyramidalQuad - A 4-sample tent filter used as a texture magnification or minification filter. 108 | // 3: Anisotropic - Anisotropic texture filtering used as a texture magnification or minification filter. This type of filtering compensates for distortion caused by the difference in angle between the texture polygon and the plane of the screen. 109 | // 2: Linear - Bilinear interpolation filtering used as a texture magnification or minification filter. A weighted average of a 2x2 area of texels surrounding the desired pixel is used. The texture filter used between mipmap levels is trilinear mipmap interpolation, in which the rasterizer performs linear interpolation on pixel color, using the texels of the two nearest mipmap textures. 110 | // 1: Point - Point filtering used as a texture magnification or minification filter. The texel with coordinates nearest to the desired pixel value is used. The texture filter used between mipmap levels is based on the nearest point; that is, the rasterizer uses the color from the texel of the nearest mipmap texture. 111 | // 0: None - Mipmapping disabled. The rasterizer uses the magnification filter instead. 112 | 113 | 114 | // -------- Texture Samplers -------- 115 | Texture xTextureDiffuse; 116 | sampler TextureSamplerDiffuse = sampler_state { 117 | texture = ; 118 | MagFilter = Anisotropic; 119 | MinFilter = Anisotropic; 120 | MipFilter = Linear; 121 | MaxAnisotropy = 8; 122 | AddressU = Wrap; 123 | AddressV = Wrap; 124 | }; 125 | 126 | Texture xTextureLightmap; 127 | sampler TextureSamplerLightmap = sampler_state { 128 | texture = ; 129 | MagFilter = Anisotropic; 130 | MinFilter = Anisotropic; 131 | MipFilter = LINEAR; 132 | MaxAnisotropy = 8; 133 | AddressU = Wrap; 134 | AddressV = Wrap; 135 | }; 136 | 137 | Texture xTextureSkin; 138 | sampler TextureSamplerSkin = sampler_state { 139 | texture = ; 140 | MagFilter = Anisotropic; 141 | MinFilter = Anisotropic; 142 | MipFilter = Linear; 143 | MaxAnisotropy = 8; 144 | AddressU = Clamp; 145 | AddressV = Clamp; 146 | }; 147 | 148 | sampler TextureSampler : register(s0); 149 | 150 | 151 | float4 CalculateSingleLightmap(Light light, float3 worldPosition, float3 worldNormal, float4 LightmapColor) 152 | { 153 | float3 lightVector = light.position - worldPosition; 154 | float lightDist = length(lightVector); 155 | float3 directionToLight = normalize(lightVector); 156 | 157 | // calculate the intensity of the light with exponential falloff 158 | float baseIntensity = pow(saturate((light.range - lightDist) / light.range), light.falloff); 159 | float diffuseIntensity = saturate(dot(directionToLight, worldNormal)); 160 | diffuseIntensity *= xLightPower; 161 | 162 | // modify the lightmap pixels 163 | float4 diffuse = diffuseIntensity * light.color; 164 | float blendfactor = min(1, lightDist / light.range); 165 | float4 lightmapPixel = (1 - blendfactor) * diffuse + blendfactor * LightmapColor; 166 | 167 | 168 | return lightmapPixel * baseIntensity; 169 | } 170 | 171 | float4 CalculateSingleLight(Light light, float3 worldPosition, float3 worldNormal, float2 TextureCoords, float4 diffuseColor, float4 specularColor) 172 | { 173 | float3 lightVector = light.position - worldPosition; 174 | float lightDist = length(lightVector); 175 | float3 directionToLight = normalize(lightVector); 176 | 177 | //calculate the intensity of the light with exponential falloff 178 | float baseIntensity = pow(saturate((light.range - lightDist) / light.range), light.falloff); 179 | float diffuseIntensity = saturate(dot(directionToLight, worldNormal)); 180 | diffuseIntensity *= xLightPower; 181 | 182 | float4 diffuse = diffuseIntensity * light.color * diffuseColor; 183 | 184 | //calculate phong components per-pixel 185 | //float3 reflectionVector = normalize(reflect(directionToLight, worldNormal)); 186 | //float3 directionToCamera = normalize(cameraPosition - worldPosition); 187 | 188 | //calculate specular component 189 | //float4 specular = saturate(light.color * specularColor * specularIntensity * pow(saturate(dot(reflectionVector, directionToCamera)), specularPower)); 190 | //return (diffuse + specular) * baseIntensity; 191 | 192 | return diffuse * baseIntensity; 193 | } 194 | 195 | float4 CalculateGamma(float4 color) 196 | { 197 | return log(1 + color) * xGamma; 198 | } 199 | 200 | float2 CalculateWarp(float2 TexCoords) 201 | { 202 | float2 TC; 203 | float TurbScale = (256.0f / (2 * 3.141592)); 204 | float Flowing = 0.0f; 205 | 206 | if (xFlow == true) 207 | Flowing = -64.0f * ((xRealTime * 0.5f) - (int)(xRealTime * 0.5f)); 208 | 209 | // muliplying the result by 3.0 to make the warping more dramatic 210 | TC.x = TexCoords.x + sin(radians((TexCoords.y * 0.125f + xRealTime) * TurbScale)) * 3.0f; 211 | TC.x += Flowing; 212 | TC.x *= (1.0f / 64.0f); 213 | TC.y = TexCoords.y + sin(radians((TexCoords.x * 0.125f + xRealTime) * TurbScale)) * 3.0f; 214 | TC.y *= (1.0f / 64.0f); 215 | 216 | return TC; 217 | } 218 | -------------------------------------------------------------------------------- /Content/skins.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | //-------- Technique: TexturedSkin -------- 28 | VertexShaderSkinOutput TexturedSkinVS(float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0) 29 | { 30 | VertexShaderSkinOutput Output = (VertexShaderSkinOutput)0; 31 | 32 | // generate the viewprojection and worldviewprojection 33 | float4x4 preViewProjection = mul(xView, xProjection); 34 | float4x4 preWorldViewProjection = mul(xWorld, preViewProjection); 35 | 36 | // transform the input position to the output 37 | Output.Position = mul(inPos, preWorldViewProjection); 38 | 39 | Output.WorldNormal = normalize(mul(inNormal, (float3x3)xWorld)); 40 | Output.WorldPosition = mul(inPos, xWorld); 41 | 42 | // copy the tex coords to the interpolator 43 | Output.TextureCoords = inTexCoords; 44 | 45 | // copy the ambient lighting 46 | Output.ambientLightColor = float4(1.0, 1.0, 1.0, 1.0); 47 | 48 | return Output; 49 | } 50 | 51 | float4 TexturedSkinPS(PixelShaderSkinInput Input) : COLOR 52 | { 53 | float4 diffuseColor = tex2D(TextureSamplerSkin, Input.TextureCoords); 54 | 55 | // gamma correction 56 | diffuseColor = CalculateGamma(diffuseColor * xLightModel); 57 | diffuseColor.a = 1.0; 58 | 59 | return diffuseColor; 60 | } 61 | -------------------------------------------------------------------------------- /Content/textures.fx: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | float numLights = LIGHT_COUNT; 28 | shared Light lights[LIGHT_COUNT]; 29 | 30 | 31 | //-------- Technique: Textured -------- 32 | VertexShaderOutput TexturedVS(float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0, float2 inLightCoords: TEXCOORD1) 33 | { 34 | VertexShaderOutput Output = (VertexShaderOutput)0; 35 | 36 | // generate the viewprojection and worldviewprojection 37 | float4x4 preViewProjection = mul(xView, xProjection); 38 | float4x4 preWorldViewProjection = mul(xWorld, preViewProjection); 39 | 40 | // transform the input position to the output 41 | Output.Position = mul(inPos, preWorldViewProjection); 42 | 43 | Output.WorldNormal = normalize(mul(inNormal, (float3x3)xWorld)); 44 | Output.WorldPosition = mul(inPos, xWorld); 45 | 46 | // copy the tex coords to the interpolator 47 | Output.TextureCoords = inTexCoords; 48 | 49 | // copy the lightmap coords to the interpolator 50 | Output.LightmapCoords = inLightCoords; 51 | 52 | // copy the ambient lighting 53 | Output.ambientLightColor = float4(1.0, 1.0, 1.0, 1.0); 54 | 55 | return Output; 56 | } 57 | 58 | float4 TexturedPS(PixelShaderInput Input) : COLOR 59 | { 60 | float4 diffuseColor = tex2D(TextureSamplerDiffuse, Input.TextureCoords); 61 | 62 | // gamma correction 63 | diffuseColor = CalculateGamma(diffuseColor); 64 | diffuseColor.a = 1.0; 65 | 66 | return diffuseColor; 67 | } 68 | 69 | 70 | //-------- Technique: TexturedWarped -------- 71 | VertexShaderOutput TexturedWarpedVS(float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0, float2 inLightCoords: TEXCOORD1) 72 | { 73 | VertexShaderOutput Output = (VertexShaderOutput)0; 74 | 75 | // generate the viewprojection and worldviewprojection 76 | float4x4 preViewProjection = mul(xView, xProjection); 77 | float4x4 preWorldViewProjection = mul(xWorld, preViewProjection); 78 | 79 | // transform the input position to the output 80 | Output.Position = mul(inPos, preWorldViewProjection); 81 | 82 | Output.WorldNormal = normalize(mul(inNormal, (float3x3)xWorld)); 83 | Output.WorldPosition = mul(inPos, xWorld); 84 | 85 | // copy the tex coords to the interpolator 86 | Output.TextureCoords = CalculateWarp(inTexCoords); 87 | 88 | // copy the lightmap coords to the interpolator 89 | Output.LightmapCoords = inLightCoords; 90 | 91 | // copy the ambient lighting 92 | Output.ambientLightColor = float4(1.0, 1.0, 1.0, 1.0); 93 | 94 | return Output; 95 | } 96 | 97 | 98 | //-------- Technique: TexturedLightmap -------- 99 | float4 TexturedLightmapPS(PixelShaderInput Input) : COLOR 100 | { 101 | float4 Color; 102 | float4 TextureColor = tex2D(TextureSamplerDiffuse, Input.TextureCoords); 103 | float4 LightmapColor = tex2D(TextureSamplerLightmap, Input.LightmapCoords); 104 | 105 | //all color components are summed in the pixel shader 106 | if(xPointLights == true) 107 | { 108 | for(int i = 0; i < LIGHT_COUNT; i++) 109 | { 110 | LightmapColor += CalculateSingleLightmap(lights[i], Input.WorldPosition, Input.WorldNormal, LightmapColor); // * (i < numLights); 111 | } 112 | } 113 | 114 | // gamma correction 115 | Color = CalculateGamma(TextureColor * LightmapColor); 116 | Color.a = 1.0; 117 | 118 | return Color; 119 | } 120 | 121 | 122 | //-------- Technique: TexturedTranslucent -------- 123 | float4 TexturedTranslucentPS(PixelShaderInput Input) : COLOR 124 | { 125 | float4 diffuseColor = tex2D(TextureSamplerDiffuse, Input.TextureCoords); 126 | 127 | // gamma correction 128 | diffuseColor = CalculateGamma(diffuseColor); 129 | diffuseColor.a = xTextureAlpha; 130 | 131 | return diffuseColor; 132 | } 133 | 134 | 135 | //-------- Technique: TexturedSkybox -------- 136 | VertexShaderOutput_Skybox TexturedSkyboxVS(float4 inPos : POSITION, float2 inTexCoords: TEXCOORD0) 137 | { 138 | VertexShaderOutput_Skybox Output = (VertexShaderOutput_Skybox)0; 139 | 140 | // generate the viewprojection and worldviewprojection 141 | float4x4 preViewProjection = mul(xView, xProjection); 142 | float4x4 preWorldViewProjection = mul(xWorld, preViewProjection); 143 | 144 | // transform the input position to the output 145 | Output.Position = mul(inPos, preWorldViewProjection); 146 | Output.WorldPosition = mul(inPos, xWorld); 147 | 148 | // copy the tex coords to the interpolator 149 | Output.TextureCoords = inTexCoords; 150 | 151 | return Output; 152 | } 153 | 154 | float4 TexturedSkyboxPS(PixelShaderInput_Skybox Input) : COLOR 155 | { 156 | float4 diffuseColor = tex2D(TextureSamplerDiffuse, Input.TextureCoords); 157 | 158 | // gamma correction 159 | diffuseColor = CalculateGamma(diffuseColor); 160 | diffuseColor.a = 1.0; 161 | 162 | return diffuseColor; 163 | } 164 | 165 | 166 | //-------- Technique: TexturedLight -------- 167 | VertexShaderOutput TexturedLightVS(float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0) 168 | { 169 | VertexShaderOutput Output = (VertexShaderOutput)0; 170 | 171 | // generate the viewprojection and worldviewprojection 172 | float4x4 preViewProjection = mul(xView, xProjection); 173 | float4x4 preWorldViewProjection = mul(xWorld, preViewProjection); 174 | 175 | // transform the input position to the output 176 | Output.Position = mul(inPos, preWorldViewProjection); 177 | 178 | Output.WorldNormal = normalize(mul(inNormal, (float3x3)xWorld)); 179 | Output.WorldPosition = mul(inPos, xWorld); 180 | 181 | // copy the tex coords to the interpolator 182 | Output.TextureCoords = inTexCoords; 183 | 184 | // copy the ambient lighting 185 | Output.ambientLightColor = xLightAmbient; 186 | 187 | return Output; 188 | } 189 | 190 | float4 TexturedLightPS(PixelShaderInput Input) : COLOR 191 | { 192 | float4 diffuseColor = tex2D(TextureSamplerDiffuse, Input.TextureCoords); 193 | float4 specularColor = float4(0.15, 0.15, 0.15, 0.15); 194 | float4 Color = Input.ambientLightColor * diffuseColor; 195 | 196 | //all color components are summed in the pixel shader 197 | if(xPointLights == true) 198 | { 199 | for(int i = 0; i < LIGHT_COUNT; i++) 200 | { 201 | Color += CalculateSingleLight(lights[i], Input.WorldPosition, Input.WorldNormal, Input.TextureCoords, diffuseColor, specularColor); // * (i < numLights); 202 | } 203 | } 204 | 205 | // gamma correction 206 | Color = CalculateGamma(Color); 207 | Color.a = 1.0; 208 | 209 | return Color; 210 | } 211 | -------------------------------------------------------------------------------- /Files.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.IO; 30 | using System.Text; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CFiles 35 | { 36 | // ======================================================================== 37 | // PAK FILE LOADING 38 | // 39 | // The .pak files are just a linear collapse of a directory tree 40 | // ======================================================================== 41 | public const int IDPAKHEADER = (('K' << 24) + ('C' << 16) + ('A' << 8) + 'P'); 42 | public const int PACK_MAX_FILES = 8192; // bumped from 4096 to support loading Heretic2 43 | public const int PACK_MAX_FILENAME_LENGTH = 56; 44 | 45 | // total number of files inside pak 46 | private int fs_packFiles; 47 | 48 | // the loaded pack information 49 | private SPack? qPack; 50 | 51 | public void FS_LoadPak(string PakFile, string BaseName) 52 | { 53 | if (CProgram.gQ2Game.gCMain.r_usepak == false) 54 | return; 55 | 56 | qPack = FS_LoadPakFile(PakFile, BaseName); 57 | } 58 | 59 | public void FS_ClosePak() 60 | { 61 | if (CProgram.gQ2Game.gCMain.r_usepak == false) 62 | return; 63 | 64 | if (qPack.HasValue == false) 65 | return; 66 | 67 | qPack.Value.handle.Close(); 68 | qPack = null; 69 | } 70 | 71 | /// 72 | /// FS_ReadFile 73 | /// ----------- 74 | /// filename are relative to the quake search path 75 | /// 76 | public void FS_ReadFile(string qpath, out byte[] qdata) 77 | { 78 | qdata = FS_ReadFile2(qpath); 79 | } 80 | 81 | public void FS_ReadFile(string qpath, out MemoryStream qdata) 82 | { 83 | byte[] data = FS_ReadFile2(qpath); 84 | 85 | if (data != null) 86 | qdata = new MemoryStream(data); 87 | else 88 | qdata = null; 89 | } 90 | 91 | private byte[] FS_ReadFile2(string qpath) 92 | { 93 | int i; 94 | bool found = false; 95 | 96 | if (qPack.HasValue == false) 97 | return null; 98 | 99 | for (i = 0; i < qPack.Value.buildBuffer.Count; i++) 100 | { 101 | if (qpath == qPack.Value.buildBuffer[i].Name) 102 | { 103 | found = true; 104 | break; 105 | } 106 | 107 | } 108 | 109 | if (found == true) 110 | { 111 | BinaryReader r = new BinaryReader(qPack.Value.handle); 112 | 113 | r.BaseStream.Seek(qPack.Value.buildBuffer[i].Position, System.IO.SeekOrigin.Begin); 114 | return r.ReadBytes(qPack.Value.buildBuffer[i].Size); 115 | } 116 | 117 | return null; 118 | } 119 | 120 | private SPack? FS_LoadPakFile(string PakFile, string BaseName) 121 | { 122 | SPack Pack; 123 | BinaryReader r; 124 | 125 | PakFile = CProgram.gQ2Game.Content.RootDirectory + "\\" + PakFile; 126 | 127 | if (File.Exists(PakFile) == false) 128 | { 129 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "PAK file not found."); 130 | return null; 131 | } 132 | 133 | Pack.handle = File.OpenRead(PakFile); 134 | 135 | if (Pack.handle == null) 136 | return null; 137 | 138 | r = new BinaryReader(Pack.handle); 139 | PakFile = PakFile.ToLower(); 140 | BaseName = BaseName.ToLower(); 141 | 142 | if (r.ReadInt32() != IDPAKHEADER) 143 | { 144 | Pack.handle.Close(); 145 | Pack.handle = null; 146 | 147 | CMain.Error(CMain.EErrorParm.ERR_FATAL, PakFile + " is not a packfile"); 148 | return null; 149 | } 150 | 151 | Pack.packDirOffset = r.ReadInt32(); 152 | Pack.packDirLength = r.ReadInt32(); 153 | 154 | // if the directory offset is beyond the EOF then we assume its htic2-0.pak 155 | // Raven Software probably did this so unaware PAK readers fails to read the Heretic2 content 156 | if (CProgram.gQ2Game.gCMain.r_htic2 == true) 157 | { 158 | if (Pack.packDirOffset > r.BaseStream.Length) 159 | { 160 | Pack.packDirOffset = 215695973; // 0x0cdb4265 (215 695 973 bytes) 161 | Pack.packDirLength = 264256; // EOF - Pack.packDirOffset (EOF: 0x0cdf4aa5 | 215 960 229 bytes) 162 | } 163 | } 164 | 165 | // PACK_MAX_FILENAME_LENGTH + FilePosition + FileLength 166 | Pack.numfiles = Pack.packDirLength / (PACK_MAX_FILENAME_LENGTH + sizeof(int) + sizeof(int)); 167 | 168 | if (Pack.numfiles > PACK_MAX_FILES) 169 | CMain.Error(CMain.EErrorParm.ERR_FATAL, PakFile + " has " + Pack.numfiles + " files"); 170 | 171 | Pack.buildBuffer = new List(); 172 | 173 | fs_packFiles += Pack.numfiles; 174 | Pack.pakFilename = PakFile; 175 | Pack.pakBasename = BaseName.Replace(".pak", ""); 176 | 177 | r.BaseStream.Seek(Pack.packDirOffset, SeekOrigin.Begin); 178 | 179 | for (int i = 0; i < Pack.numfiles; i++) 180 | { 181 | SFileInPack _FileInPack; 182 | 183 | _FileInPack.Name = CShared.Com_ToString(r.ReadChars(PACK_MAX_FILENAME_LENGTH)).ToLower(); 184 | _FileInPack.Position = r.ReadInt32(); 185 | _FileInPack.Size = r.ReadInt32(); 186 | 187 | Pack.buildBuffer.Add(_FileInPack); 188 | } 189 | 190 | //for (int i = 0; i < Pack.buildBuffer.Count; i++) 191 | //{ 192 | // r.BaseStream.Seek(Pack.buildBuffer[i].Position, System.IO.SeekOrigin.Begin); 193 | // fs_headerLongs[fs_numHeaderLongs++] = CCrc32.GetMemoryCRC32(r.ReadBytes(Pack.buildBuffer[i].Size)); 194 | //} 195 | 196 | //Pack.checksum = CProgram.vCCommon.Com_BlockChecksum(fs_headerLongs); 197 | //Pack.pure_checksum = CProgram.vCCommon.Com_BlockChecksumKey(fs_headerLongs, fs_checksumFeed); 198 | 199 | // As of yet unassigned 200 | //Pack.hashSize = 0; 201 | Pack.pakGamename = null; 202 | 203 | return Pack; 204 | } 205 | 206 | 207 | public struct SPack 208 | { 209 | public string pakFilename; // c:\quake2\baseq2\pak0.pak 210 | public string pakBasename; // pak0 211 | public string pakGamename; // baseq2 212 | public FileStream handle; // handle to pack file 213 | //public long checksum; // regular checksum 214 | //public long pure_checksum; // checksum for pure 215 | public int numfiles; // number of files in pak 216 | public List buildBuffer; // file entry 217 | 218 | public int packDirOffset; 219 | public int packDirLength; 220 | } 221 | 222 | public struct SFileInPack 223 | { 224 | public string Name; // name of the file 225 | public long Position; // file info position in pak 226 | public int Size; // file info size in pak 227 | } 228 | 229 | 230 | // ======================================================================== 231 | // PCX FILE LOADING 232 | // 233 | // Used for as many images as possible 234 | // ======================================================================== 235 | public struct SPCX 236 | { 237 | public byte manufacturer; 238 | public byte version; 239 | public byte encoding; 240 | public byte bits_per_pixel; 241 | public ushort xmin; 242 | public ushort ymin; 243 | public ushort xmax; 244 | public ushort ymax; 245 | public ushort hres; 246 | public ushort vres; 247 | public byte[] palette; // size: 48 (unsigned char ??) 248 | public byte reserved; 249 | public byte color_planes; 250 | public ushort bytes_per_line; 251 | public ushort palette_type; 252 | public byte[] filler; // size: 58 253 | public byte data; // unsigned char ?? 254 | } 255 | 256 | /*typedef struct 257 | { 258 | char manufacturer; 259 | char version; 260 | char encoding; 261 | char bits_per_pixel; 262 | unsigned short xmin,ymin,xmax,ymax; 263 | unsigned short hres,vres; 264 | unsigned char palette[48]; 265 | char reserved; 266 | char color_planes; 267 | unsigned short bytes_per_line; 268 | unsigned short palette_type; 269 | char filler[58]; 270 | unsigned char data; // unbounded 271 | } pcx_t;*/ 272 | 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /Game.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacqueskrige/quake2-csharp-xna/8d92b97d5cac4a4ed94fb90776157cc6c582c707/Game.ico -------------------------------------------------------------------------------- /GameThumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacqueskrige/quake2-csharp-xna/8d92b97d5cac4a4ed94fb90776157cc6c582c707/GameThumbnail.png -------------------------------------------------------------------------------- /Gamma.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework.Graphics; 30 | using System.Text; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CGamma 35 | { 36 | private float GammaValue; 37 | 38 | public CGamma() 39 | { 40 | GammaValue = 2.1f; 41 | 42 | CProgram.gQ2Game.gCMain.gSGlobal.HLSL.xGamma = GammaValue; 43 | } 44 | 45 | public void GammaLighten() 46 | { 47 | if (GammaValue > 5.0f) 48 | GammaValue = 5.0f; 49 | 50 | if (GammaValue == 5.0f) 51 | return; 52 | 53 | GammaValue += 0.02f; 54 | GammaValue = (float)Math.Round(GammaValue, 2); 55 | 56 | CProgram.gQ2Game.gCMain.gSGlobal.HLSL.xGamma = GammaValue; 57 | 58 | //SetGamma(GammaValue, GammaValue, GammaValue); 59 | } 60 | 61 | public void GammaDarken() 62 | { 63 | if (GammaValue < 1.0f) 64 | GammaValue = 1.0f; 65 | 66 | if (GammaValue <= 1.0f) 67 | return; 68 | 69 | GammaValue -= 0.02f; 70 | GammaValue = (float)Math.Round(GammaValue, 2); 71 | 72 | CProgram.gQ2Game.gCMain.gSGlobal.HLSL.xGamma = GammaValue; 73 | 74 | //SetGamma(GammaValue, GammaValue, GammaValue); 75 | } 76 | 77 | /*private void SetGamma(float Red, float Green, float Blue) 78 | { 79 | // map the float values (0.0 min, 1.0 max) to byte values (0 min, 255 max) 80 | //byte redOffset = (byte)(Red * 255); 81 | //byte greenOffset = (byte)(Green * 255); 82 | //byte blueOffset = (byte)(Blue * 255); 83 | short redOffset = (short)(Red * 255); 84 | short greenOffset = (short)(Green * 255); 85 | short blueOffset = (short)(Blue * 255); 86 | 87 | // get the gamma ramp 88 | GammaRamp ramp = CProgram.gQ2Game.gGraphicsDevice.GetGammaRamp(); 89 | short[] r = ramp.GetRed(); 90 | short[] g = ramp.GetGreen(); 91 | short[] b = ramp.GetBlue(); 92 | 93 | // set the gamma values 94 | // they are stored as shorts, but are treated as ushorts by the hardware 95 | // if the value is over short.MaxValue, subtract ushort.MaxValue from it 96 | for (short i = 0; i < 256; i++) 97 | { 98 | r[i] *= redOffset; 99 | if (r[i] > short.MaxValue) 100 | { 101 | r[i] -= (short)(r[i] - ushort.MaxValue * 2); 102 | System.Diagnostics.Debug.WriteLine("over red"); 103 | } 104 | //if (r[i] > 2550) 105 | // r[i] = 2550; 106 | 107 | g[i] *= greenOffset; 108 | if (g[i] > short.MaxValue) 109 | { 110 | g[i] -= (short)(g[i] - ushort.MaxValue * 2); 111 | System.Diagnostics.Debug.WriteLine("over green"); 112 | } 113 | //if (g[i] > 2550) 114 | // g[i] = 2550; 115 | 116 | b[i] *= blueOffset; 117 | if (b[i] > short.MaxValue) 118 | { 119 | b[i] -= (short)(b[i] - ushort.MaxValue * 2); 120 | System.Diagnostics.Debug.WriteLine("over blue"); 121 | } 122 | //if (b[i] > 2550) 123 | // b[i] = 2550; 124 | } 125 | 126 | // set the gamma values 127 | ramp.SetRed(r); 128 | ramp.SetGreen(g); 129 | ramp.SetBlue(b); 130 | CProgram.gQ2Game.gGraphicsDevice.SetGammaRamp(true, ramp); 131 | }*/ 132 | 133 | public float Gamma 134 | { 135 | get 136 | { 137 | return GammaValue; 138 | } 139 | } 140 | 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /Input.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Input; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CInput 35 | { 36 | KeyboardState KeyboardStateLast; 37 | KeyboardState KeyboardStateCurrent; 38 | 39 | MouseState MouseStateOriginal; 40 | MouseState MouseStateCurrent; 41 | 42 | public CInput() 43 | { 44 | Mouse.SetPosition(CProgram.gQ2Game.gGraphicsDevice.Viewport.Width / 2, CProgram.gQ2Game.gGraphicsDevice.Viewport.Height / 2); 45 | MouseStateOriginal = Mouse.GetState(); 46 | } 47 | 48 | public void ProcessMouse() 49 | { 50 | float RotationPitch = 0.0f; 51 | float RotationYaw = 0.0f; 52 | Quaternion RotationAdd; 53 | 54 | MouseStateCurrent = Mouse.GetState(); 55 | 56 | if (MouseStateCurrent != MouseStateOriginal) 57 | { 58 | float xDifference = MouseStateCurrent.X - MouseStateOriginal.X; 59 | float yDifference = MouseStateCurrent.Y - MouseStateOriginal.Y; 60 | 61 | // the magic number 16 is used because its the number of milliseconds that passes when vsync is turned on 62 | // this ensures the mouse response remains constant whether vsync is turned on/off 63 | xDifference *= (16 / CProgram.gQ2Game.TargetElapsedTime.Milliseconds); 64 | yDifference *= (16 / CProgram.gQ2Game.TargetElapsedTime.Milliseconds); 65 | 66 | RotationYaw += CProgram.gQ2Game.gCMain.SpeedMouse * xDifference; 67 | RotationPitch -= CProgram.gQ2Game.gCMain.SpeedMouse * yDifference; 68 | 69 | Mouse.SetPosition(CProgram.gQ2Game.gGraphicsDevice.Viewport.Width / 2, CProgram.gQ2Game.gGraphicsDevice.Viewport.Height / 2); 70 | } 71 | 72 | 73 | // update camera pitch & yaw 74 | CClient.cl.RefDef.ViewAngles.X += Microsoft.Xna.Framework.MathHelper.ToDegrees(RotationPitch); 75 | CClient.cl.RefDef.ViewAngles.Z += Microsoft.Xna.Framework.MathHelper.ToDegrees(RotationYaw); 76 | 77 | if (CClient.cl.RefDef.ViewAngles.X < 0.0f) 78 | CClient.cl.RefDef.ViewAngles.X += 360.0f; 79 | else if (CClient.cl.RefDef.ViewAngles.X > 360.0f) 80 | CClient.cl.RefDef.ViewAngles.X -= 360.0f; 81 | 82 | if (CClient.cl.RefDef.ViewAngles.Z < 0.0f) 83 | CClient.cl.RefDef.ViewAngles.Z += 360.0f; 84 | else if (CClient.cl.RefDef.ViewAngles.Z > 360.0f) 85 | CClient.cl.RefDef.ViewAngles.Z -= 360.0f; 86 | 87 | // rotation 88 | RotationAdd = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), -RotationPitch) * Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), -RotationYaw); 89 | CClient.cl.RefDef.TargetAngles *= RotationAdd; 90 | } 91 | 92 | public void ProcessKeyboard() 93 | { 94 | float RotationRoll = 0.0f; 95 | Quaternion RotationAdd; 96 | Vector3 OriginAdd; 97 | 98 | KeyboardStateLast = KeyboardStateCurrent; 99 | KeyboardStateCurrent = Keyboard.GetState(); 100 | 101 | 102 | // update camera roll 103 | if (KeyboardStateCurrent.IsKeyDown(Keys.Left) == true || KeyboardStateCurrent.IsKeyDown(Keys.Right) == true) 104 | { 105 | if (KeyboardStateCurrent.IsKeyDown(Keys.Left) == true) 106 | RotationRoll -= CProgram.gQ2Game.gCMain.SpeedRotation; 107 | 108 | if (KeyboardStateCurrent.IsKeyDown(Keys.Right) == true) 109 | RotationRoll += CProgram.gQ2Game.gCMain.SpeedRotation; 110 | } 111 | 112 | CClient.cl.RefDef.ViewAngles.Y += Microsoft.Xna.Framework.MathHelper.ToDegrees(RotationRoll); 113 | 114 | if (CClient.cl.RefDef.ViewAngles.Y < 0.0f) 115 | CClient.cl.RefDef.ViewAngles.Y += 360.0f; 116 | else if (CClient.cl.RefDef.ViewAngles.Y > 360.0f) 117 | CClient.cl.RefDef.ViewAngles.Y -= 360.0f; 118 | 119 | 120 | // movement for camera forward/backward 121 | if (KeyboardStateCurrent.IsKeyDown(Keys.Up) == true || KeyboardStateCurrent.IsKeyDown(Keys.Down) == true) 122 | { 123 | if (KeyboardStateCurrent.IsKeyDown(Keys.Up) == true) 124 | CProgram.gQ2Game.gCMain.MoveForward = -1; 125 | 126 | if (KeyboardStateCurrent.IsKeyDown(Keys.Down) == true) 127 | CProgram.gQ2Game.gCMain.MoveForward = 1; 128 | } 129 | else 130 | { 131 | CProgram.gQ2Game.gCMain.MoveForward = 0; 132 | } 133 | 134 | // movement for camera left/right (strafe) 135 | if (KeyboardStateCurrent.IsKeyDown(Keys.Z) == true || KeyboardStateCurrent.IsKeyDown(Keys.X) == true) 136 | { 137 | if (KeyboardStateCurrent.IsKeyDown(Keys.Z) == true) 138 | CProgram.gQ2Game.gCMain.MoveSide = 1; 139 | 140 | if (KeyboardStateCurrent.IsKeyDown(Keys.X) == true) 141 | CProgram.gQ2Game.gCMain.MoveSide = -1; 142 | } 143 | else 144 | { 145 | CProgram.gQ2Game.gCMain.MoveSide = 0; 146 | } 147 | 148 | // movement for camera up/down 149 | if (KeyboardStateCurrent.IsKeyDown(Keys.Q) == true || KeyboardStateCurrent.IsKeyDown(Keys.A) == true) 150 | { 151 | if (KeyboardStateCurrent.IsKeyDown(Keys.Q) == true) 152 | CProgram.gQ2Game.gCMain.MoveUp = 1; 153 | 154 | if (KeyboardStateCurrent.IsKeyDown(Keys.A) == true) 155 | CProgram.gQ2Game.gCMain.MoveUp = -1; 156 | } 157 | else 158 | { 159 | CProgram.gQ2Game.gCMain.MoveUp = 0; 160 | } 161 | 162 | // quit 163 | if (KeyboardStateCurrent.IsKeyDown(Keys.Escape) == true) 164 | { 165 | CProgram.gQ2Game.Exit(); 166 | } 167 | 168 | // switch between wireframe and solid rendering modes 169 | if (KeyboardStateCurrent.IsKeyDown(Keys.O) == true && KeyboardStateLast.IsKeyUp(Keys.O) == true) 170 | { 171 | CProgram.gQ2Game.gCMain.r_wireframe = !CProgram.gQ2Game.gCMain.r_wireframe; 172 | } 173 | 174 | // switch entity on and off 175 | if (KeyboardStateCurrent.IsKeyDown(Keys.E) == true && KeyboardStateLast.IsKeyUp(Keys.E) == true) 176 | { 177 | CProgram.gQ2Game.gCMain.r_drawentities = !CProgram.gQ2Game.gCMain.r_drawentities; 178 | } 179 | 180 | // set the gamma intensity 181 | if (KeyboardStateCurrent.IsKeyDown(Keys.Subtract) == true) 182 | { 183 | CProgram.gQ2Game.gCGamma.GammaDarken(); 184 | } 185 | if (KeyboardStateCurrent.IsKeyDown(Keys.Add) == true) 186 | { 187 | CProgram.gQ2Game.gCGamma.GammaLighten(); 188 | } 189 | 190 | // switch hardware pointlight on and off 191 | if (KeyboardStateCurrent.IsKeyDown(Keys.P) == true && KeyboardStateLast.IsKeyUp(Keys.P) == true) 192 | { 193 | CProgram.gQ2Game.gCMain.gSGlobal.HLSL.xPointLights = !CProgram.gQ2Game.gCMain.gSGlobal.HLSL.xPointLights; 194 | } 195 | 196 | // switch between hardware per-pixel lighting and classic lightmaps 197 | if (KeyboardStateCurrent.IsKeyDown(Keys.H) == true && KeyboardStateLast.IsKeyUp(Keys.H) == true) 198 | { 199 | CProgram.gQ2Game.gCMain.r_hardwarelight = !CProgram.gQ2Game.gCMain.r_hardwarelight; 200 | } 201 | 202 | // switch pvs lock on and off 203 | if (KeyboardStateCurrent.IsKeyDown(Keys.L) == true && KeyboardStateLast.IsKeyUp(Keys.L) == true) 204 | { 205 | CProgram.gQ2Game.gCMain.r_lockpvs = !CProgram.gQ2Game.gCMain.r_lockpvs; 206 | } 207 | 208 | // switch bloom on and off 209 | if (KeyboardStateCurrent.IsKeyDown(Keys.B) == true && KeyboardStateLast.IsKeyUp(Keys.B) == true) 210 | { 211 | CProgram.gQ2Game.gCMain.r_bloom = !CProgram.gQ2Game.gCMain.r_bloom; 212 | } 213 | 214 | if (KeyboardStateCurrent.IsKeyDown(Keys.Space) == true && KeyboardStateLast.IsKeyUp(Keys.Space) == true) 215 | { 216 | CProgram.gQ2Game.gCMain.r_controls = !CProgram.gQ2Game.gCMain.r_controls; 217 | } 218 | 219 | 220 | // rotation 221 | RotationAdd = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), -RotationRoll); 222 | CClient.cl.RefDef.TargetAngles *= RotationAdd; 223 | 224 | // move left/right 225 | OriginAdd = Vector3.Transform(new Vector3(1, 0, 0), CClient.cl.RefDef.TargetAngles); 226 | CClient.cl.RefDef.TargetOrigin += OriginAdd * CProgram.gQ2Game.gCMain.SpeedSide; 227 | 228 | // move forward/backward 229 | OriginAdd = Vector3.Transform(new Vector3(0, 1, 0), CClient.cl.RefDef.TargetAngles); 230 | CClient.cl.RefDef.TargetOrigin += OriginAdd * CProgram.gQ2Game.gCMain.SpeedForward; 231 | 232 | // move up/down 233 | OriginAdd = Vector3.Transform(new Vector3(0, 0, 1), CClient.cl.RefDef.TargetAngles); 234 | CClient.cl.RefDef.TargetOrigin += OriginAdd * CProgram.gQ2Game.gCMain.SpeedUp; 235 | 236 | // update ViewOrigin 237 | CClient.cl.RefDef.ViewOrigin = CClient.cl.RefDef.TargetOrigin; 238 | } 239 | 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /Library/Command.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.IO; 30 | using System.Text; 31 | 32 | namespace Q2BSP.Library 33 | { 34 | public class CCommand 35 | { 36 | public const string TextReturn = "\r\n"; 37 | 38 | public static bool WriteFile(string FilePath, string FileData) 39 | { 40 | FileStream FS; 41 | BinaryWriter BW; 42 | 43 | if (string.IsNullOrEmpty(FilePath) == true) 44 | return false; 45 | 46 | if (string.IsNullOrEmpty(FileData) == true) 47 | return false; 48 | 49 | FS = System.IO.File.Open(FilePath, FileMode.Create, FileAccess.Write); 50 | 51 | if (FS == null) 52 | return false; 53 | 54 | BW = new BinaryWriter(FS); 55 | for (int i = 0; i < FileData.Length; i++) 56 | { 57 | BW.Write(FileData[i]); 58 | } 59 | 60 | BW.Close(); 61 | BW = null; 62 | 63 | FS.Close(); 64 | FS.Dispose(); 65 | FS = null; 66 | 67 | return true; 68 | } 69 | 70 | public static string LoadFile(string FileName) 71 | { 72 | string MapData; 73 | char[] ch; 74 | FileStream FS; 75 | BinaryReader BR; 76 | StringBuilder SB; 77 | 78 | if (string.IsNullOrEmpty(FileName) == true) 79 | return null; 80 | 81 | FS = System.IO.File.OpenRead(FileName); 82 | 83 | if (FS == null) 84 | return null; 85 | 86 | BR = new BinaryReader(FS); 87 | ch = BR.ReadChars((int)FS.Length); 88 | 89 | BR.Close(); 90 | BR = null; 91 | 92 | FS.Close(); 93 | FS.Dispose(); 94 | FS = null; 95 | 96 | SB = new StringBuilder(ch.Length); 97 | SB.Append(ch); 98 | 99 | MapData = SB.ToString(); 100 | 101 | if (string.IsNullOrEmpty(MapData) == true) 102 | return null; 103 | 104 | // fix line ends 105 | MapData = MapData.Replace("\r", "").Replace("\n", "\r\n"); 106 | 107 | return MapData; 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Library/Script.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP.Library 32 | { 33 | public class CScript 34 | { 35 | private const int MAX_INCLUDES = 8; 36 | private const int MAX_TOKEN = 1024; 37 | 38 | //private cCommand vCommand; 39 | 40 | //private string InputData; 41 | //private SScript[] ScriptStack; 42 | private List Script; 43 | public int ScriptLine; 44 | 45 | public string Token; 46 | //private bool ScriptEnd; 47 | private bool TokenReady; // only qtrue if UnGetToken was just called 48 | 49 | public CScript(/*string Input*/) 50 | { 51 | //if (string.IsNullOrEmpty(Input) == true) 52 | // InputData = null; 53 | //else 54 | // InputData = Input.Trim(); 55 | 56 | //vCommand = new cCommand(); 57 | 58 | //ScriptStack = new SScript[MAX_INCLUDES]; 59 | Script = new List(); 60 | } 61 | 62 | /*public bool BufferAvailable() 63 | { 64 | if (string.IsNullOrEmpty(Script[Script.Count - 1].Buffer) == true) 65 | return false; 66 | else 67 | return true; 68 | }*/ 69 | 70 | // ================ 71 | // AddScriptToStack 72 | // ================ 73 | private void AddScriptToStack(string FileName) 74 | { 75 | SScript _Script; 76 | 77 | if (Script.Count == MAX_INCLUDES - 1) 78 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Script file exceeded MAX_INCLUDES"); 79 | 80 | _Script.FileName = FileName; 81 | _Script.Buffer = CCommand.LoadFile(_Script.FileName); 82 | 83 | CMain.Printf("entering " + _Script.FileName + "\n"); 84 | 85 | _Script.Line = 1; 86 | 87 | // jkrige - todo 88 | _Script.StartPosition = 0; 89 | _Script.EndPosition = _Script.Buffer.Length - 1; 90 | //script->script_p = script->buffer; 91 | //script->end_p = script->buffer + size; 92 | // jkrige - todo 93 | 94 | Script.Add(_Script); 95 | } 96 | 97 | // ================ 98 | // LoadScriptFile 99 | // ================ 100 | public string LoadScriptFile(string FileName) 101 | { 102 | AddScriptToStack(FileName); 103 | 104 | //ScriptEnd = false; 105 | TokenReady = false; 106 | 107 | return Script[Script.Count - 1].Buffer; 108 | } 109 | 110 | // ================ 111 | // ParseFromMemory 112 | // ================ 113 | public void ParseFromMemory(string buffer) 114 | { 115 | SScript _Script; 116 | 117 | if (Script.Count == MAX_INCLUDES) 118 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Script file exceeded MAX_INCLUDES"); 119 | 120 | _Script.FileName = "memory buffer"; 121 | _Script.Buffer = buffer; 122 | 123 | _Script.Line = 1; 124 | 125 | // jkrige - todo 126 | _Script.StartPosition = 0; 127 | _Script.EndPosition = _Script.Buffer.Length - 1; 128 | //script->script_p = script->buffer; 129 | //script->end_p = script->buffer + size; 130 | // jkrige - todo 131 | 132 | Script.Add(_Script); 133 | 134 | //ScriptEnd = false; 135 | TokenReady = false; 136 | } 137 | 138 | // ================ 139 | // UnGetToken 140 | // 141 | // Signals that the current token was not used, and should be reported for the next GetToken. 142 | // Note that 143 | // 144 | // GetToken(qtrue); 145 | // UnGetToken(); 146 | // GetToken (qfalse); 147 | // 148 | // could cross a line boundary. 149 | // ================ 150 | public void UnGetToken() 151 | { 152 | TokenReady = true; 153 | } 154 | 155 | public bool EndOfScript(bool CrossLine) 156 | { 157 | SScript _Script; 158 | 159 | if (CrossLine == false) 160 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Line " + ScriptLine + " is incomplete."); 161 | 162 | if (Script[Script.Count - 1].FileName == "memory buffer") 163 | { 164 | //ScriptEnd = true; 165 | return false; 166 | } 167 | 168 | _Script = Script[Script.Count - 1]; 169 | _Script.Buffer = ""; 170 | Script[Script.Count - 1] = _Script; 171 | 172 | // jkrige - check : this IF statement 173 | //if (Script.Count == MAX_INCLUDES) 174 | // return false; 175 | 176 | if (Script.Count == 1) 177 | { 178 | return false; 179 | } 180 | // jkrige - check : this IF statement 181 | 182 | Script.RemoveAt(Script.Count - 1); 183 | ScriptLine = Script[Script.Count - 1].Line; 184 | CMain.Printf("returning to " + Script[Script.Count - 1].FileName + "\n"); 185 | 186 | return GetToken(CrossLine); 187 | } 188 | 189 | // ================ 190 | // GetToken 191 | // ================ 192 | public bool GetToken(bool CrossLine) 193 | { 194 | string token_p; 195 | SScript _Script; 196 | 197 | // is a token already waiting? 198 | if (TokenReady == true) 199 | { 200 | TokenReady = false; 201 | return true; 202 | } 203 | 204 | //token_p = ""; 205 | _Script = Script[Script.Count - 1]; 206 | 207 | if (_Script.StartPosition >= _Script.EndPosition) 208 | return EndOfScript(CrossLine); 209 | 210 | 211 | // 212 | // skip space 213 | // 214 | 215 | skipspace: 216 | while (_Script.Buffer[_Script.StartPosition] <= 32) 217 | { 218 | if (_Script.StartPosition >= _Script.EndPosition) 219 | { 220 | Script[Script.Count - 1] = _Script; 221 | return EndOfScript(CrossLine); 222 | } 223 | 224 | if (_Script.Buffer[_Script.StartPosition++] == '\n') 225 | { 226 | if(CrossLine == false) 227 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Line " + ScriptLine + " is incomplete."); 228 | 229 | ScriptLine = _Script.Line++; 230 | } 231 | } 232 | 233 | if (_Script.StartPosition >= _Script.EndPosition) 234 | { 235 | Script[Script.Count - 1] = _Script; 236 | return EndOfScript(CrossLine); 237 | } 238 | 239 | // ; # // comments 240 | if ( 241 | _Script.Buffer[_Script.StartPosition] == ';' 242 | || _Script.Buffer[_Script.StartPosition] == '#' 243 | || (_Script.Buffer[_Script.StartPosition] == '/' && _Script.Buffer[_Script.StartPosition + 1] == '/') 244 | ) 245 | { 246 | if (CrossLine == false) 247 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Line " + ScriptLine + " is incomplete."); 248 | 249 | while (_Script.Buffer[_Script.StartPosition++] != '\n') 250 | { 251 | if (_Script.StartPosition >= _Script.EndPosition) 252 | { 253 | Script[Script.Count - 1] = _Script; 254 | return EndOfScript(CrossLine); 255 | } 256 | } 257 | 258 | ScriptLine = _Script.Line++; 259 | Script[Script.Count - 1] = _Script; 260 | goto skipspace; 261 | } 262 | 263 | // /* */ comments 264 | if (_Script.Buffer[_Script.StartPosition] == '/' && _Script.Buffer[_Script.StartPosition + 1] == '*') 265 | { 266 | if (CrossLine == false) 267 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Line " + ScriptLine + " is incomplete."); 268 | 269 | _Script.StartPosition += 2; 270 | 271 | while (_Script.Buffer[_Script.StartPosition] != '*' && _Script.Buffer[_Script.StartPosition + 1] != '/') 272 | { 273 | if (_Script.Buffer[_Script.StartPosition] == '\n') 274 | ScriptLine = _Script.Line++; 275 | 276 | _Script.StartPosition++; 277 | 278 | if (_Script.StartPosition >= _Script.EndPosition) 279 | { 280 | Script[Script.Count - 1] = _Script; 281 | return EndOfScript(CrossLine); 282 | } 283 | } 284 | 285 | _Script.StartPosition += 2; 286 | Script[Script.Count - 1] = _Script; 287 | goto skipspace; 288 | } 289 | 290 | 291 | // 292 | // copy token 293 | // 294 | 295 | token_p = ""; 296 | //token_p = Token; 297 | //int test = _Script.Position; 298 | 299 | if (_Script.Buffer[_Script.StartPosition] == '"') 300 | { 301 | // quoted token 302 | _Script.StartPosition++; 303 | 304 | while (_Script.Buffer[_Script.StartPosition] != '"') 305 | { 306 | token_p = token_p + _Script.Buffer[_Script.StartPosition++]; 307 | 308 | if (_Script.StartPosition == _Script.EndPosition) 309 | break; 310 | 311 | if (token_p.Length >= MAX_TOKEN) 312 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Token too large on line " + ScriptLine + "."); 313 | } 314 | _Script.StartPosition++; 315 | } 316 | else 317 | { 318 | // regular token 319 | while (_Script.Buffer[_Script.StartPosition] > 32 && _Script.Buffer[_Script.StartPosition] != ';') 320 | { 321 | token_p = token_p + _Script.Buffer[_Script.StartPosition++]; 322 | 323 | if (_Script.StartPosition == _Script.EndPosition) 324 | break; 325 | 326 | if (token_p.Length >= MAX_TOKEN) 327 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "Token too large on line " + ScriptLine + "."); 328 | } 329 | } 330 | 331 | Token = token_p; 332 | Script[Script.Count - 1] = _Script; 333 | 334 | if (Token == "$include") 335 | { 336 | GetToken(false); 337 | AddScriptToStack(Token); 338 | 339 | return GetToken(CrossLine); 340 | } 341 | 342 | return true; 343 | } 344 | 345 | // ================ 346 | // TokenAvailable 347 | // 348 | // Returns qtrue if there is another token on the line 349 | // ================ 350 | public bool TokenAvailable() 351 | { 352 | int oldLine; 353 | bool r; 354 | 355 | oldLine = Script[Script.Count - 1].Line; 356 | r = GetToken(true); 357 | 358 | if (r == false) 359 | return false; 360 | 361 | UnGetToken(); 362 | 363 | if (oldLine == Script[Script.Count - 1].Line) 364 | return true; 365 | 366 | return false; 367 | } 368 | 369 | 370 | // ===================================================================== 371 | 372 | public void MatchToken(string Match) 373 | { 374 | GetToken(true); 375 | 376 | if (Token != Match) 377 | CMain.Error(CMain.EErrorParm.ERR_FATAL, "MatchToken( \"" + Match + "\" ) failed at line " + ScriptLine + "."); 378 | } 379 | 380 | /*public void Parse1DMatrix(int x, ref cMath.Vec[] v, int vPosition) 381 | { 382 | MatchToken("("); 383 | 384 | if (v != null) 385 | { 386 | for (int i = 0; i < x; i++) 387 | { 388 | GetToken(false); 389 | v[vPosition + i].Value = Convert.ToSingle(Token); 390 | } 391 | } 392 | 393 | MatchToken(")"); 394 | }*/ 395 | 396 | /*public void Parse2DMatrix(int y, int x, ref cMath.Vec[] v, int vPosition) 397 | { 398 | MatchToken("("); 399 | 400 | if (v != null) 401 | { 402 | for (int i = 0; i < y; i++) 403 | { 404 | Parse1DMatrix(x, ref v, vPosition + i * x); 405 | } 406 | } 407 | 408 | MatchToken(")"); 409 | }*/ 410 | 411 | /*public void Parse3DMatrix(int z, int y, int x, ref cMath.Vec[] v, int vPosition) 412 | { 413 | MatchToken("("); 414 | 415 | if (v != null) 416 | { 417 | for (int i = 0; i < z; i++) 418 | { 419 | Parse2DMatrix(y, x, ref v, vPosition + i * x * y); 420 | } 421 | } 422 | 423 | MatchToken(")"); 424 | }*/ 425 | 426 | /*public void Write1DMatrix(System.IO.FileStream FS, int x, ref cMath.Vec[] v, int vPosition) 427 | { 428 | System.IO.BinaryWriter BW = new System.IO.BinaryWriter(FS); 429 | 430 | BW.Write("( "); 431 | 432 | if (v != null) 433 | { 434 | for (int i = 0; i < x; i++) 435 | { 436 | if (v[vPosition + i].Value == System.Math.Round(v[vPosition + i].Value)) 437 | { 438 | BW.Write(System.Math.Round(v[vPosition + i].Value).ToString() + " "); 439 | } 440 | else 441 | { 442 | BW.Write(v[vPosition + i].Value.ToString() + " "); 443 | } 444 | } 445 | } 446 | 447 | BW.Write(")"); 448 | }*/ 449 | 450 | /*public void Write2DMatrix(System.IO.FileStream FS, int y, int x, ref cMath.Vec[] v, int vPosition) 451 | { 452 | System.IO.BinaryWriter BW = new System.IO.BinaryWriter(FS); 453 | 454 | BW.Write("( "); 455 | 456 | if (v != null) 457 | { 458 | for (int i = 0; i < y; i++) 459 | { 460 | Write1DMatrix(FS, x, ref v, vPosition + i * x); 461 | BW.Write(" "); 462 | } 463 | } 464 | 465 | BW.Write(")\n"); 466 | }*/ 467 | 468 | /*public void Write3DMatrix(System.IO.FileStream FS, int z, int y, int x, ref cMath.Vec[] v, int vPosition) 469 | { 470 | System.IO.BinaryWriter BW = new System.IO.BinaryWriter(FS); 471 | 472 | BW.Write("(\n"); 473 | 474 | if (v != null) 475 | { 476 | for (int i = 0; i < z; i++) 477 | { 478 | Write2DMatrix(FS, y, x, ref v, vPosition + i * x * y); 479 | } 480 | } 481 | 482 | BW.Write(")\n"); 483 | }*/ 484 | 485 | private struct SScript 486 | { 487 | public string FileName; 488 | public string Buffer; 489 | public int StartPosition; 490 | public int EndPosition; 491 | public int Line; 492 | } 493 | 494 | } 495 | } 496 | -------------------------------------------------------------------------------- /Local.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Graphics; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CLocal 35 | { 36 | public const int MAX_LIGHTSTYLES = 256; 37 | public const int TEXNUM_LIGHTMAPS = 1024; 38 | public const int MAX_LBM_HEIGHT = 480; 39 | 40 | public const float gl_modulate = 1.0f; 41 | 42 | public static BoundingBox ClearBounds() 43 | { 44 | BoundingBox bounds; 45 | 46 | bounds.Min.X = bounds.Min.Y = bounds.Min.Z = 99999; 47 | bounds.Max.X = bounds.Max.Y = bounds.Max.Z = -99999; 48 | 49 | return bounds; 50 | } 51 | 52 | public static void AddPointToBounds(Vector3 v, ref BoundingBox bounds) 53 | { 54 | if (v.X < bounds.Min.X) 55 | bounds.Min.X = v.X; 56 | 57 | if (v.X > bounds.Max.X) 58 | bounds.Max.X = v.X; 59 | 60 | 61 | if (v.Y < bounds.Min.Y) 62 | bounds.Min.Y = v.Y; 63 | 64 | if (v.Y > bounds.Max.Y) 65 | bounds.Max.Y = v.Y; 66 | 67 | 68 | if (v.Z < bounds.Min.Z) 69 | bounds.Min.Z = v.Z; 70 | 71 | if (v.Z > bounds.Max.Z) 72 | bounds.Max.Z = v.Z; 73 | } 74 | 75 | 76 | 77 | public struct SLightStyle 78 | { 79 | public float[] rgb; // size: 3 (0.0 - 2.0) 80 | public float white; // highest of rgb 81 | } 82 | 83 | public struct SRefDef 84 | { 85 | public Vector3 ViewOrigin; 86 | public Vector3 ViewAngles; 87 | public Vector3 ViewUp; 88 | 89 | public Vector3 TargetOrigin; 90 | public Quaternion TargetAngles; 91 | 92 | public BoundingFrustum FrustumBounds; 93 | 94 | public int EntityIndex; 95 | 96 | public string MapName; 97 | 98 | public SLightStyle[] lightstyles; // size: MAX_LIGHTSTYLES 99 | } 100 | 101 | public struct SHLSL 102 | { 103 | public Matrix xViewMatrix; 104 | public Matrix xProjectionMatrix; 105 | public Matrix xWorld; 106 | public Color xLightModel; 107 | public Color xLightAmbient; 108 | public float xLightPower; 109 | public float xTextureAlpha; 110 | public float xGamma; 111 | public float xRealTime; 112 | public float xBloomThreshold; 113 | public float xBaseIntensity; 114 | public float xBloomIntensity; 115 | public float xBaseSaturation; 116 | public float xBloomSaturation; 117 | public bool xPointLights; 118 | public bool xFlow; 119 | } 120 | 121 | public struct SGlobal 122 | { 123 | public SHLSL HLSL; 124 | public SHLSL OldHLSL; 125 | } 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /PointLight.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Graphics; 31 | using System.Text; 32 | 33 | namespace Q2BSP 34 | { 35 | public class CPointLight 36 | { 37 | ////////////////////////////////////////////////////////////// 38 | // The only parameter that will be changing for every light // 39 | // each frame is the postion parameter. For the sake of // 40 | // reducing string look-ups, the position parameter is // 41 | // stored as a parameter instance. The other parameters // 42 | // are updated much less frequently, so a tradeoff has been // 43 | // made for clarity. // 44 | ////////////////////////////////////////////////////////////// 45 | 46 | private EffectParameter positionParameter; 47 | private EffectParameter instanceParameter; 48 | 49 | private float LightRange = 300.0f; 50 | private float LightFalloff = 1.1f; 51 | private Vector4 LightPosition; 52 | private Color LightColor = Color.White; 53 | 54 | public CPointLight(Vector4 initialPosition) 55 | { 56 | gPosition = initialPosition; 57 | } 58 | 59 | public CPointLight(Vector4 initialPosition, float initialRange) 60 | { 61 | gPosition = initialPosition; 62 | gRange = initialRange; 63 | } 64 | 65 | public CPointLight(Vector4 initialPosition, float initialRange, float Red, float Green, float Blue) 66 | { 67 | gPosition = initialPosition; 68 | gRange = initialRange; 69 | LightColor.R = (byte)(255 * Red); 70 | LightColor.G = (byte)(255 * Green); 71 | LightColor.B = (byte)(255 * Blue); 72 | LightColor.A = (byte)255; 73 | gColor = LightColor; 74 | } 75 | 76 | public CPointLight(Vector4 initialPosition, EffectParameter lightParameter) 77 | { 78 | ////////////////////////////////////////////////////////////// 79 | // An instance of a light is bound to an instance of a // 80 | // Light structure defined in the effect. The // 81 | // "StructureMembers" property of a parameter is used to // 82 | // access the individual fields of a structure. // 83 | ////////////////////////////////////////////////////////////// 84 | instanceParameter = lightParameter; 85 | positionParameter = instanceParameter.StructureMembers["position"]; 86 | gPosition = initialPosition; 87 | instanceParameter.StructureMembers["range"].SetValue(LightRange); 88 | instanceParameter.StructureMembers["falloff"].SetValue(LightFalloff); 89 | instanceParameter.StructureMembers["color"].SetValue(LightColor.ToVector4()); 90 | } 91 | 92 | public void SetLight(EffectParameter lightParameter) 93 | { 94 | instanceParameter = lightParameter; 95 | 96 | //if (CProgram.gQ2Game.gCMain.r_hardwarelight == false) 97 | // return; 98 | 99 | instanceParameter.StructureMembers["position"].SetValue(LightPosition); 100 | instanceParameter.StructureMembers["range"].SetValue(LightRange); 101 | instanceParameter.StructureMembers["falloff"].SetValue(LightFalloff); 102 | instanceParameter.StructureMembers["color"].SetValue(LightColor.ToVector4()); 103 | 104 | // generic.fx 105 | //struct Light 106 | //{ 107 | // float4 color; // 0 108 | // float4 position; // 1 109 | // float falloff; // 2 110 | // float range; // 3 111 | //}; 112 | //instanceParameter.StructureMembers[0].SetValue(LightColor.ToVector4()); // "color" 113 | //instanceParameter.StructureMembers[1].SetValue(LightPosition); // "position" 114 | //instanceParameter.StructureMembers[2].SetValue(LightFalloff); // "falloff" 115 | //instanceParameter.StructureMembers[3].SetValue(LightRange); // "range" 116 | } 117 | 118 | #region Light Properties 119 | public Vector4 gPosition 120 | { 121 | set 122 | { 123 | LightPosition = value; 124 | 125 | if (positionParameter != null) 126 | positionParameter.SetValue(LightPosition); 127 | } 128 | get 129 | { 130 | return LightPosition; 131 | } 132 | } 133 | 134 | 135 | public Color gColor 136 | { 137 | set 138 | { 139 | LightColor = value; 140 | 141 | if (instanceParameter != null) 142 | instanceParameter.StructureMembers["color"].SetValue(LightColor.ToVector4()); 143 | } 144 | get 145 | { 146 | return LightColor; 147 | } 148 | } 149 | 150 | public float gRange 151 | { 152 | set 153 | { 154 | LightRange = value; 155 | 156 | if (instanceParameter != null) 157 | instanceParameter.StructureMembers["range"].SetValue(LightRange); 158 | } 159 | get 160 | { 161 | return LightRange; 162 | } 163 | } 164 | 165 | 166 | public float gFalloff 167 | { 168 | set 169 | { 170 | LightFalloff = value; 171 | 172 | if (instanceParameter != null) 173 | instanceParameter.StructureMembers["falloff"].SetValue(LightFalloff); 174 | } 175 | get 176 | { 177 | return LightFalloff; 178 | } 179 | } 180 | #endregion 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | 29 | namespace Q2BSP 30 | { 31 | public static class CProgram 32 | { 33 | public static CQ2Game gQ2Game; 34 | 35 | /// 36 | /// Main 37 | /// ---- 38 | /// The main entry point for the application. 39 | /// 40 | static void Main(string[] args) 41 | { 42 | using (gQ2Game = new CQ2Game()) 43 | { 44 | gQ2Game.Run(); 45 | } 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Q2BSP")] 9 | [assembly: AssemblyProduct("Q2BSP")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyCompany("Korvin Korax")] 12 | 13 | [assembly: AssemblyCopyright("Copyright © Korvin Korax 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c505cbf7-5ceb-41e7-8119-5a179c33bf3e")] 24 | 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /Q2BSP.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {16A93DDD-6C32-43A3-B219-E5BD5A27AF39} 5 | {6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | x86 8 | WinExe 9 | Properties 10 | Q2BSP 11 | Q2BSP 12 | v4.0 13 | v4.0 14 | Windows 15 | e6fb21a1-52c0-49f5-83fa-6a793ad6ba24 16 | Game.ico 17 | GameThumbnail.png 18 | true 19 | 20 | 21 | Game 22 | HiDef 23 | Client 24 | 25 | 26 | 3.5 27 | 28 | http://localhost/Q2BSP/ 29 | true 30 | Web 31 | true 32 | Foreground 33 | 7 34 | Days 35 | false 36 | false 37 | true 38 | 0 39 | 1.0.0.%2a 40 | false 41 | true 42 | 43 | 44 | true 45 | full 46 | false 47 | bin\x86\Debug 48 | DEBUG;TRACE;WINDOWS 49 | prompt 50 | 4 51 | true 52 | false 53 | x86 54 | false 55 | AllRules.ruleset 56 | 57 | 58 | pdbonly 59 | true 60 | bin\x86\Release 61 | TRACE;WINDOWS 62 | prompt 63 | 4 64 | true 65 | false 66 | x86 67 | True 68 | AllRules.ruleset 69 | 70 | 71 | 72 | False 73 | 74 | 75 | False 76 | 77 | 78 | False 79 | 80 | 81 | False 82 | 83 | 84 | False 85 | 86 | 87 | False 88 | 89 | 90 | False 91 | 92 | 93 | False 94 | 95 | 96 | False 97 | 98 | 99 | False 100 | 101 | 102 | False 103 | 104 | 105 | False 106 | 107 | 108 | 109 | 110 | 111 | False 112 | 113 | 114 | False 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 29204dfd-5723-48db-ac99-a8208752e4f1 159 | False 160 | 161 | 162 | 163 | 164 | False 165 | .NET Framework 3.5 SP1 Client Profile 166 | false 167 | 168 | 169 | False 170 | .NET Framework 2.0 %28x86%29 171 | false 172 | 173 | 174 | False 175 | .NET Framework 3.0 %28x86%29 176 | false 177 | 178 | 179 | False 180 | .NET Framework 3.5 181 | false 182 | 183 | 184 | False 185 | .NET Framework 3.5 SP1 186 | true 187 | 188 | 189 | False 190 | Windows Installer 3.1 191 | true 192 | 193 | 194 | False 195 | Microsoft XNA Framework Redistributable 3.0 196 | true 197 | 198 | 199 | False 200 | Microsoft XNA Framework Redistributable 4.0 201 | true 202 | 203 | 204 | 205 | 206 | {29204DFD-5723-48DB-AC99-A8208752E4F1} 207 | Q2BSPContent %28Content%29 208 | Content 209 | 210 | 211 | 212 | 213 | Designer 214 | 215 | 216 | 217 | 218 | 225 | -------------------------------------------------------------------------------- /Q2BSP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Q2BSP", "Q2BSP.csproj", "{16A93DDD-6C32-43A3-B219-E5BD5A27AF39}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Q2BSPContent", "Content\Q2BSPContent.contentproj", "{29204DFD-5723-48DB-AC99-A8208752E4F1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {16A93DDD-6C32-43A3-B219-E5BD5A27AF39}.Debug|x86.ActiveCfg = Debug|x86 15 | {16A93DDD-6C32-43A3-B219-E5BD5A27AF39}.Debug|x86.Build.0 = Debug|x86 16 | {16A93DDD-6C32-43A3-B219-E5BD5A27AF39}.Release|x86.ActiveCfg = Release|x86 17 | {16A93DDD-6C32-43A3-B219-E5BD5A27AF39}.Release|x86.Build.0 = Release|x86 18 | {29204DFD-5723-48DB-AC99-A8208752E4F1}.Debug|x86.ActiveCfg = Debug|x86 19 | {29204DFD-5723-48DB-AC99-A8208752E4F1}.Release|x86.ActiveCfg = Release|x86 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /Q2Game.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Audio; 31 | using Microsoft.Xna.Framework.Content; 32 | using Microsoft.Xna.Framework.GamerServices; 33 | using Microsoft.Xna.Framework.Graphics; 34 | using Microsoft.Xna.Framework.Input; 35 | using Microsoft.Xna.Framework.Media; 36 | using Microsoft.Xna.Framework.Net; 37 | using Microsoft.Xna.Framework.Storage; 38 | 39 | namespace Q2BSP 40 | { 41 | /// 42 | /// This is the main type for your game 43 | /// 44 | public class CQ2Game : Microsoft.Xna.Framework.Game 45 | { 46 | public GraphicsDeviceManager gGraphicsDeviceManager; 47 | public GraphicsDevice gGraphicsDevice; 48 | public Effect gEffect; 49 | public SpriteBatch spriteBatch; 50 | 51 | public CMain gCMain; 52 | public CCommon gCCommon; 53 | public CGamma gCGamma; 54 | 55 | // temporary text drawing 56 | SpriteFont Font1; 57 | Vector2 FontPos; 58 | 59 | /// 60 | /// CQ2Game 61 | /// ---------- 62 | /// The game constructor 63 | /// 64 | public CQ2Game() 65 | { 66 | gGraphicsDeviceManager = new GraphicsDeviceManager(this); 67 | 68 | Content.RootDirectory = "Content"; 69 | } 70 | 71 | private void DrawOverlayText(Vector2 Origin, string Text, Color TextColor) 72 | { 73 | spriteBatch.Begin(); 74 | 75 | Origin.X -= 1; 76 | Origin.Y -= 1; 77 | spriteBatch.DrawString(Font1, Text, FontPos, Color.Black, 0, Origin, 1.0f, SpriteEffects.None, 0.5f); 78 | 79 | Origin.X += 1; 80 | Origin.Y += 1; 81 | spriteBatch.DrawString(Font1, Text, FontPos, TextColor, 0, Origin, 1.0f, SpriteEffects.None, 0.5f); 82 | 83 | spriteBatch.End(); 84 | } 85 | 86 | 87 | // ===================================================================== 88 | // 89 | // XNA SPECIFIC FUNCTIONS 90 | // 91 | // ===================================================================== 92 | 93 | /// 94 | /// Initialize 95 | /// ---------- 96 | /// Allows the game to perform any initialization it needs to before starting to run. 97 | /// This is where it can query for any required services and load any non-graphic 98 | /// related content. Calling base.Initialize will enumerate through any components 99 | /// and initialize them as well. 100 | /// 101 | protected override void Initialize() 102 | { 103 | Window.Title = CMain.GameTitle; 104 | gGraphicsDeviceManager.PreferMultiSampling = true; 105 | gGraphicsDeviceManager.IsFullScreen = CConfig.GetConfigBOOL("Fullscreen"); 106 | 107 | if (gGraphicsDeviceManager.IsFullScreen == true) 108 | { 109 | int Width; 110 | int Height; 111 | 112 | try 113 | { 114 | Width = Convert.ToInt32(CConfig.GetConfigSTRING("Width")); 115 | Height = Convert.ToInt32(CConfig.GetConfigSTRING("Height")); 116 | } 117 | catch 118 | { 119 | Width = 1024; 120 | Height = 768; 121 | } 122 | 123 | gGraphicsDeviceManager.PreferredBackBufferWidth = Width; 124 | gGraphicsDeviceManager.PreferredBackBufferHeight = Height; 125 | } 126 | else 127 | { 128 | gGraphicsDeviceManager.PreferredBackBufferWidth = 1024; 129 | gGraphicsDeviceManager.PreferredBackBufferHeight = 768; 130 | } 131 | 132 | if (CConfig.GetConfigBOOL("Vertical Sync") == true) 133 | { 134 | gGraphicsDeviceManager.SynchronizeWithVerticalRetrace = true; 135 | gGraphicsDeviceManager.GraphicsDevice.PresentationParameters.PresentationInterval = PresentInterval.Default; 136 | } 137 | else 138 | { 139 | gGraphicsDeviceManager.SynchronizeWithVerticalRetrace = false; 140 | gGraphicsDeviceManager.GraphicsDevice.PresentationParameters.PresentationInterval = PresentInterval.Immediate; 141 | 142 | TargetElapsedTime = TimeSpan.FromMilliseconds(1); 143 | } 144 | IsFixedTimeStep = true; 145 | 146 | gGraphicsDeviceManager.ApplyChanges(); 147 | gGraphicsDevice = gGraphicsDeviceManager.GraphicsDevice; 148 | 149 | gCMain = new CMain(); 150 | gCCommon = new CCommon(); 151 | gCGamma = new CGamma(); 152 | 153 | base.Initialize(); 154 | } 155 | 156 | /// 157 | /// LoadContent 158 | /// ----------- 159 | /// Will be called once per game and is the place to load 160 | /// all of your content. 161 | /// 162 | protected override void LoadContent() 163 | { 164 | // Create a new SpriteBatch, which can be used to draw textures. 165 | spriteBatch = new SpriteBatch(GraphicsDevice); 166 | 167 | if (CProgram.gQ2Game.gGraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef) 168 | { 169 | //gCMain.r_maxLights = 8; 170 | //gEffect = Content.Load("effects30"); 171 | 172 | // "Cannot mix shader model 3.0 with earlier shader models. If either the vertex shader or pixel shader is compiled as 3.0, they must both be." 173 | // FIXME: Not sure how to get tis fixed... using SM2 instead 174 | gCMain.r_maxLights = 2; 175 | gEffect = Content.Load("effects20"); 176 | } 177 | else 178 | { 179 | gCMain.r_maxLights = 2; 180 | gEffect = Content.Load("effects20"); 181 | } 182 | 183 | Font1 = Content.Load("SpriteFont1"); 184 | FontPos = new Vector2(5, 5); 185 | 186 | gCMain.gCBloom.Setup(); 187 | 188 | gCMain.BuildWorldModel(CConfig.GetConfigSTRING("Map Name")); 189 | gCMain.WorldViewInit(); 190 | } 191 | 192 | /// 193 | /// UnloadContent 194 | /// ------------- 195 | /// Will be called once per game and is the place to unload 196 | /// all content. 197 | /// 198 | protected override void UnloadContent() 199 | { 200 | gCMain.gCBloom.Release(); 201 | } 202 | 203 | /// 204 | /// Update 205 | /// ------ 206 | /// Allows the game to run logic such as updating the world, 207 | /// checking for collisions, gathering input, and playing audio. 208 | /// 209 | /// Provides a snapshot of timing values. 210 | protected override void Update(GameTime gameTime) 211 | { 212 | gCMain.gTimeGame = gameTime; 213 | 214 | gCMain.FrameUpdate(); 215 | gCCommon.Qcommon_Frame(1); 216 | 217 | base.Update(gameTime); 218 | } 219 | 220 | /// 221 | /// Draw 222 | /// ---- 223 | /// This is called when the game should draw itself. 224 | /// 225 | /// Provides a snapshot of timing values. 226 | protected override void Draw(GameTime gameTime) 227 | { 228 | Vector2 FontOrigin; 229 | gCMain.gTimeGame = gameTime; 230 | 231 | gCMain.gCBloom.DrawBloom(); 232 | 233 | gGraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0); 234 | 235 | 236 | // reset and set the rasterizer states 237 | CProgram.gQ2Game.gCMain.gRasterizerState = new RasterizerState(); 238 | CProgram.gQ2Game.gCMain.gRasterizerState.CullMode = CullMode.CullCounterClockwiseFace; 239 | 240 | if (CProgram.gQ2Game.gCMain.r_wireframe == false) 241 | CProgram.gQ2Game.gCMain.gRasterizerState.FillMode = FillMode.Solid; 242 | else 243 | CProgram.gQ2Game.gCMain.gRasterizerState.FillMode = FillMode.WireFrame; 244 | 245 | gGraphicsDevice.RasterizerState = CProgram.gQ2Game.gCMain.gRasterizerState; 246 | 247 | 248 | // reset the blend and depth states 249 | gGraphicsDevice.BlendState = BlendState.Opaque; 250 | 251 | 252 | // reset and set the depthstencil states 253 | CProgram.gQ2Game.gCMain.gDepthStencilState = new DepthStencilState(); 254 | CProgram.gQ2Game.gCMain.gDepthStencilState.DepthBufferEnable = true; 255 | gGraphicsDevice.DepthStencilState = CProgram.gQ2Game.gCMain.gDepthStencilState; 256 | 257 | 258 | gCMain.FrameRenderView(); 259 | gCMain.gCBloom.Draw(); 260 | 261 | 262 | // we are drawing the overlay text here, because we don't want it to be affected by postprocessing 263 | 264 | // reset and set the rasterizer states 265 | CProgram.gQ2Game.gCMain.gRasterizerState = new RasterizerState(); 266 | CProgram.gQ2Game.gCMain.gRasterizerState.FillMode = FillMode.Solid; 267 | gGraphicsDevice.RasterizerState = CProgram.gQ2Game.gCMain.gRasterizerState; 268 | 269 | 270 | FontOrigin.X = 0; 271 | FontOrigin.Y = 0; 272 | DrawOverlayText(FontOrigin, CClient.cl.RefDef.MapName, Color.White); 273 | 274 | FontOrigin.X = 0; 275 | FontOrigin.Y = -40; 276 | DrawOverlayText(FontOrigin, "FPS Rate: " + gCMain.FrameRate.FrameRate.ToString(), Color.Silver); 277 | 278 | FontOrigin.X = 0; 279 | FontOrigin.Y = -60; 280 | DrawOverlayText(FontOrigin, "PVS Cluster: " + CMain.r_viewcluster.ToString(), Color.Silver); 281 | 282 | FontOrigin.X = 0; 283 | FontOrigin.Y = -80; 284 | DrawOverlayText(FontOrigin, "PVS Locked: " + gCMain.r_lockpvs.ToString(), Color.Silver); 285 | 286 | FontOrigin.X = 0; 287 | FontOrigin.Y = -100; 288 | DrawOverlayText(FontOrigin, "Bloom: " + gCMain.r_bloom.ToString(), Color.Silver); 289 | 290 | FontOrigin.X = 0; 291 | FontOrigin.Y = -120; 292 | DrawOverlayText(FontOrigin, "Primitives: " + CMain.c_brush_polys.ToString(), Color.Silver); 293 | 294 | FontOrigin.X = 0; 295 | FontOrigin.Y = -140; 296 | DrawOverlayText(FontOrigin, "Origin: (XYZ) " + Convert.ToInt64(CClient.cl.RefDef.ViewOrigin.X).ToString() + ", " + Convert.ToInt64(CClient.cl.RefDef.ViewOrigin.Y).ToString() + ", " + Convert.ToInt64(CClient.cl.RefDef.ViewOrigin.Z).ToString(), Color.Silver); 297 | 298 | FontOrigin.X = 0; 299 | FontOrigin.Y = -160; 300 | DrawOverlayText(FontOrigin, "View: (XYZ) " + Convert.ToInt64(CClient.cl.RefDef.ViewAngles.X).ToString() + ", " + Convert.ToInt64(CClient.cl.RefDef.ViewAngles.Y).ToString() + ", " + Convert.ToInt64(CClient.cl.RefDef.ViewAngles.Z).ToString(), Color.Silver); 301 | 302 | FontOrigin.X = 0; 303 | FontOrigin.Y = -180; 304 | DrawOverlayText(FontOrigin, "Gamma: " + gCMain.gSGlobal.HLSL.xGamma.ToString(), Color.Silver); 305 | 306 | FontOrigin.X = 0; 307 | FontOrigin.Y = -220; 308 | DrawOverlayText(FontOrigin, "[SPACE] show/hide controls", Color.Gray); 309 | 310 | if (CProgram.gQ2Game.gCMain.r_controls == true) 311 | { 312 | FontOrigin.X = 0; 313 | FontOrigin.Y = -240; 314 | DrawOverlayText(FontOrigin, "[ARROWS] forward/back, roll", Color.Gray); 315 | 316 | FontOrigin.X = 0; 317 | FontOrigin.Y = -260; 318 | DrawOverlayText(FontOrigin, "[Q]/[A] up/down", Color.Gray); 319 | 320 | FontOrigin.X = 0; 321 | FontOrigin.Y = -280; 322 | DrawOverlayText(FontOrigin, "[Z]/[X] left/right", Color.Gray); 323 | 324 | FontOrigin.X = 0; 325 | FontOrigin.Y = -300; 326 | DrawOverlayText(FontOrigin, "[MOUSE] pitch/yaw", Color.Gray); 327 | 328 | FontOrigin.X = 0; 329 | FontOrigin.Y = -320; 330 | DrawOverlayText(FontOrigin, "[O] fill mode", Color.Gray); 331 | 332 | FontOrigin.X = 0; 333 | FontOrigin.Y = -340; 334 | DrawOverlayText(FontOrigin, "[+]/[-] gamma", Color.Gray); 335 | 336 | FontOrigin.X = 0; 337 | FontOrigin.Y = -360; 338 | DrawOverlayText(FontOrigin, "[P] pointlights on/off", Color.Gray); 339 | 340 | FontOrigin.X = 0; 341 | FontOrigin.Y = -380; 342 | DrawOverlayText(FontOrigin, "[H] lightmaps on/off", Color.Gray); 343 | 344 | FontOrigin.X = 0; 345 | FontOrigin.Y = -400; 346 | DrawOverlayText(FontOrigin, "[L] pvs lock on/off", Color.Gray); 347 | 348 | FontOrigin.X = 0; 349 | FontOrigin.Y = -420; 350 | DrawOverlayText(FontOrigin, "[B] bloom on/off", Color.Gray); 351 | 352 | FontOrigin.X = 0; 353 | FontOrigin.Y = -440; 354 | DrawOverlayText(FontOrigin, "[E] entities on/off", Color.Gray); 355 | } 356 | 357 | base.Draw(gameTime); 358 | } 359 | 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /Q2MD2.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.IO; 30 | using Microsoft.Xna.Framework; 31 | using Microsoft.Xna.Framework.Graphics; 32 | using System.Text; 33 | 34 | namespace Q2BSP 35 | { 36 | public class CQ2MD2 37 | { 38 | private void BuildAliasModelBuffer(ref CModel.SModelMD2 _SModelMD2) 39 | { 40 | List vertbuffer; 41 | 42 | if (_SModelMD2.vbModel != null) 43 | return; 44 | 45 | CProgram.gQ2Game.gCMain.ModelVertexDeclaration = new VertexDeclaration(CModel.ModelVertexFormat.VertexElements); 46 | 47 | _SModelMD2.vbModel = new VertexBuffer[_SModelMD2.md2.num_frames]; 48 | 49 | // builds a vertexbuffer for each animation frame 50 | for (int i = 0; i < _SModelMD2.md2.num_frames; i++) 51 | { 52 | vertbuffer = new List(); 53 | 54 | for (int j = 0; j < _SModelMD2.md2.num_tris; j++) 55 | { 56 | for (int k = 0; k < 3; k++) 57 | { 58 | CModel.ModelVertexFormat _vert; 59 | 60 | _vert.Position.X = ((float)_SModelMD2.aliasframes[i].verts[_SModelMD2.triangles[j].index_xyz[k]].v[0]) * _SModelMD2.aliasframes[i].scale[0]; 61 | _vert.Position.Y = ((float)_SModelMD2.aliasframes[i].verts[_SModelMD2.triangles[j].index_xyz[k]].v[1]) * _SModelMD2.aliasframes[i].scale[1]; 62 | _vert.Position.Z = ((float)_SModelMD2.aliasframes[i].verts[_SModelMD2.triangles[j].index_xyz[k]].v[2]) * _SModelMD2.aliasframes[i].scale[2]; 63 | _vert.Position.X += _SModelMD2.aliasframes[i].translate[0]; 64 | _vert.Position.Y += _SModelMD2.aliasframes[i].translate[1]; 65 | _vert.Position.Z += _SModelMD2.aliasframes[i].translate[2]; 66 | 67 | _vert.TextureCoordinate.X = (float)(((double)_SModelMD2.st[_SModelMD2.triangles[j].index_st[k]].s + 0.5) / (double)_SModelMD2.md2.skinwidth); 68 | _vert.TextureCoordinate.Y = (float)(((double)_SModelMD2.st[_SModelMD2.triangles[j].index_st[k]].t + 0.5) / (double)_SModelMD2.md2.skinheight); 69 | 70 | _vert.Normal.X = 0.0f; 71 | _vert.Normal.Y = 0.0f; 72 | _vert.Normal.Z = 0.0f; 73 | 74 | vertbuffer.Add(_vert); 75 | } 76 | } 77 | 78 | // set up model frame vertex buffer 79 | _SModelMD2.vbModel[i] = new VertexBuffer(CProgram.gQ2Game.gGraphicsDevice, CProgram.gQ2Game.gCMain.ModelVertexDeclaration, vertbuffer.Count, BufferUsage.WriteOnly); 80 | _SModelMD2.vbModel[i].SetData(vertbuffer.ToArray()); 81 | 82 | vertbuffer.Clear(); 83 | vertbuffer = null; 84 | } 85 | } 86 | 87 | public void Mod_LoadAliasModel(ref CModel.SModel _SModel, MemoryStream ms) 88 | { 89 | BinaryReader br; 90 | List skinnames; 91 | List st; 92 | List triangles; 93 | List aliasframes; 94 | 95 | // HACK - prevent model loading if in Heretic II mode 96 | if (CProgram.gQ2Game.gCMain.r_htic2 == true) 97 | return; 98 | 99 | ms.Seek(0, System.IO.SeekOrigin.Begin); 100 | br = new BinaryReader(ms); 101 | 102 | 103 | // identity (header) 104 | _SModel.ModelMD2.md2.identification = br.ReadBytes(4); 105 | if (_SModel.ModelMD2.md2.identification[0] != 'I' 106 | || _SModel.ModelMD2.md2.identification[1] != 'D' 107 | || _SModel.ModelMD2.md2.identification[2] != 'P' 108 | || _SModel.ModelMD2.md2.identification[3] != '2') 109 | { 110 | System.Diagnostics.Debug.WriteLine("MDL file " + _SModel.name + " doesn't have IDP2 id"); 111 | 112 | br.Close(); 113 | return; 114 | } 115 | 116 | 117 | // model version 118 | _SModel.ModelMD2.md2.version = br.ReadInt32(); 119 | if (_SModel.ModelMD2.md2.version != ALIAS_VERSION) 120 | { 121 | System.Diagnostics.Debug.WriteLine(_SModel.name + " has wrong version number (" + _SModel.ModelMD2.md2.version + " should be " + ALIAS_VERSION + ")"); 122 | 123 | br.Close(); 124 | return; 125 | } 126 | 127 | 128 | // skin size 129 | _SModel.ModelMD2.md2.skinwidth = br.ReadInt32(); 130 | _SModel.ModelMD2.md2.skinheight = br.ReadInt32(); 131 | if (_SModel.ModelMD2.md2.skinheight > CLocal.MAX_LBM_HEIGHT) 132 | { 133 | System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has a skin taller than " + CLocal.MAX_LBM_HEIGHT + "."); 134 | 135 | br.Close(); 136 | return; 137 | } 138 | 139 | 140 | // frame size 141 | _SModel.ModelMD2.md2.framesize = br.ReadInt32(); 142 | 143 | 144 | // number of skins 145 | _SModel.ModelMD2.md2.num_skins = br.ReadInt32(); 146 | 147 | 148 | // number of vertices 149 | _SModel.ModelMD2.md2.num_xyz = br.ReadInt32(); 150 | if (_SModel.ModelMD2.md2.num_xyz > MAX_VERTS) 151 | { 152 | System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has too many vertices"); 153 | 154 | br.Close(); 155 | return; 156 | } 157 | 158 | 159 | // number of st vertices 160 | _SModel.ModelMD2.md2.num_st = br.ReadInt32(); 161 | if (_SModel.ModelMD2.md2.num_st <= 0) 162 | { 163 | System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no st vertices"); 164 | 165 | br.Close(); 166 | return; 167 | } 168 | 169 | 170 | // number of triangles 171 | _SModel.ModelMD2.md2.num_tris = br.ReadInt32(); 172 | if (_SModel.ModelMD2.md2.num_tris <= 0) 173 | { 174 | System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no triangles"); 175 | 176 | br.Close(); 177 | return; 178 | } 179 | 180 | 181 | // number of gl commands 182 | _SModel.ModelMD2.md2.num_glcmds = br.ReadInt32(); 183 | 184 | 185 | // number of frames 186 | _SModel.ModelMD2.md2.num_frames = br.ReadInt32(); 187 | if (_SModel.ModelMD2.md2.num_frames <= 0) 188 | { 189 | System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no frames"); 190 | 191 | br.Close(); 192 | return; 193 | } 194 | 195 | 196 | // load offsets 197 | _SModel.ModelMD2.md2.ofs_skins = br.ReadInt32(); // each skin is a MAX_SKINNAME string 198 | _SModel.ModelMD2.md2.ofs_st = br.ReadInt32(); // byte offset from start for stverts 199 | _SModel.ModelMD2.md2.ofs_tris = br.ReadInt32(); // offset for dtriangles 200 | _SModel.ModelMD2.md2.ofs_frames = br.ReadInt32(); // offset for first frame 201 | _SModel.ModelMD2.md2.ofs_glcmds = br.ReadInt32(); // offset for strip/fan command list 202 | _SModel.ModelMD2.md2.ofs_end = br.ReadInt32(); // end of file 203 | 204 | 205 | // 206 | // load the skin names 207 | // 208 | skinnames = new List(); 209 | for (int i = 0; i < _SModel.ModelMD2.md2.num_skins; i++) 210 | { 211 | skinnames.Add(CShared.Com_ToString(br.ReadChars(MAX_SKINNAME))); 212 | } 213 | 214 | if (skinnames.Count != 0) 215 | { 216 | _SModel.ModelMD2.skinnames = skinnames.ToArray(); 217 | skinnames.Clear(); 218 | skinnames = null; 219 | } 220 | 221 | 222 | // 223 | // load base s and t vertices (not used in gl version) 224 | // 225 | st = new List(); 226 | for (int i = 0; i < _SModel.ModelMD2.md2.num_st; i++) 227 | { 228 | SSTVert _SSTVert; 229 | 230 | _SSTVert.s = br.ReadInt16(); 231 | _SSTVert.t = br.ReadInt16(); 232 | 233 | st.Add(_SSTVert); 234 | } 235 | 236 | if (st.Count != 0) 237 | { 238 | _SModel.ModelMD2.st = st.ToArray(); 239 | st.Clear(); 240 | st = null; 241 | } 242 | 243 | 244 | // 245 | // load the triangles 246 | // 247 | triangles = new List(); 248 | for (int i = 0; i < _SModel.ModelMD2.md2.num_tris; i++) 249 | { 250 | SDTriangle _SDTriangle; 251 | 252 | _SDTriangle.index_xyz = new short[3]; 253 | _SDTriangle.index_xyz[0] = br.ReadInt16(); 254 | _SDTriangle.index_xyz[1] = br.ReadInt16(); 255 | _SDTriangle.index_xyz[2] = br.ReadInt16(); 256 | 257 | _SDTriangle.index_st = new short[3]; 258 | _SDTriangle.index_st[0] = br.ReadInt16(); 259 | _SDTriangle.index_st[1] = br.ReadInt16(); 260 | _SDTriangle.index_st[2] = br.ReadInt16(); 261 | 262 | triangles.Add(_SDTriangle); 263 | } 264 | 265 | if (triangles.Count != 0) 266 | { 267 | _SModel.ModelMD2.triangles = triangles.ToArray(); 268 | triangles.Clear(); 269 | triangles = null; 270 | } 271 | 272 | 273 | // 274 | // load the frames 275 | // 276 | aliasframes = new List(); 277 | for (int i = 0; i < _SModel.ModelMD2.md2.num_frames; i++) 278 | { 279 | SAliasFrameDesc _SAliasFrameDesc; 280 | 281 | _SAliasFrameDesc.scale = new float[3]; 282 | _SAliasFrameDesc.scale[0] = br.ReadSingle(); 283 | _SAliasFrameDesc.scale[1] = br.ReadSingle(); 284 | _SAliasFrameDesc.scale[2] = br.ReadSingle(); 285 | 286 | _SAliasFrameDesc.translate = new float[3]; 287 | _SAliasFrameDesc.translate[0] = br.ReadSingle(); 288 | _SAliasFrameDesc.translate[1] = br.ReadSingle(); 289 | _SAliasFrameDesc.translate[2] = br.ReadSingle(); 290 | 291 | _SAliasFrameDesc.name = br.ReadChars(16); 292 | 293 | _SAliasFrameDesc.verts = new STrivertx[_SModel.ModelMD2.md2.num_xyz]; 294 | for (int j = 0; j < _SModel.ModelMD2.md2.num_xyz; j++) 295 | { 296 | _SAliasFrameDesc.verts[j].v = new byte[3]; 297 | _SAliasFrameDesc.verts[j].v[0] = br.ReadByte(); 298 | _SAliasFrameDesc.verts[j].v[1] = br.ReadByte(); 299 | _SAliasFrameDesc.verts[j].v[2] = br.ReadByte(); 300 | 301 | _SAliasFrameDesc.verts[j].lightnormalindex = br.ReadByte(); 302 | } 303 | 304 | aliasframes.Add(_SAliasFrameDesc); 305 | } 306 | 307 | if (aliasframes.Count != 0) 308 | { 309 | _SModel.ModelMD2.aliasframes = aliasframes.ToArray(); 310 | aliasframes.Clear(); 311 | aliasframes = null; 312 | } 313 | 314 | 315 | // 316 | // load the gl commands 317 | // 318 | _SModel.ModelMD2.glcmds = br.ReadBytes(_SModel.ModelMD2.md2.num_glcmds * sizeof(int)); 319 | 320 | 321 | 322 | // set the model type 323 | _SModel.ModType = CModel.EModType.MOD_ALIAS; 324 | 325 | 326 | // register all skins 327 | _SModel.ModelMD2.skins = new Microsoft.Xna.Framework.Graphics.Texture2D[_SModel.ModelMD2.md2.num_skins]; 328 | for (int i = 0; i < _SModel.ModelMD2.md2.num_skins; i++) 329 | { 330 | _SModel.ModelMD2.skins[i] = CProgram.gQ2Game.gCMain.gCImage.LoadSkin(_SModel.ModelMD2.skinnames[i]); 331 | } 332 | 333 | // set default mins/maxs 334 | _SModel.mins.X = -32; 335 | _SModel.mins.Y = -32; 336 | _SModel.mins.Z = -32; 337 | _SModel.maxs.X = 32; 338 | _SModel.maxs.Y = 32; 339 | _SModel.maxs.Z = 32; 340 | 341 | // close the binary reader 342 | br.Close(); 343 | br = null; 344 | 345 | // close the memory stream 346 | ms.Close(); 347 | ms = null; 348 | 349 | BuildAliasModelBuffer(ref _SModel.ModelMD2); 350 | } 351 | 352 | public void R_DrawAliasModel(CModel.SEntities _CurrentEntity) 353 | { 354 | Matrix wMatrix; 355 | Color shadelight; 356 | 357 | if (_CurrentEntity.Model.ModelMD2.vbModel == null) 358 | return; 359 | 360 | // set vertex buffer 361 | CProgram.gQ2Game.gGraphicsDevice.SetVertexBuffer(_CurrentEntity.Model.ModelMD2.vbModel[_CurrentEntity.ModelFrameSeqStart + _CurrentEntity.ModelFrameCurrent]); 362 | 363 | // create model rotation and translation matrix 364 | wMatrix = Matrix.CreateFromYawPitchRoll(_CurrentEntity.Angles.Y, _CurrentEntity.Angles.X, _CurrentEntity.Angles.Z); 365 | wMatrix *= Matrix.CreateTranslation(_CurrentEntity.Origin); 366 | 367 | // calculate the model light color 368 | shadelight = new Color(); 369 | CProgram.gQ2Game.gCMain.gCLight.R_LightPoint(_CurrentEntity.Origin, ref shadelight); 370 | 371 | // update HLSL variables 372 | CProgram.gQ2Game.gEffect.Parameters["xWorld"].SetValue(wMatrix); 373 | CProgram.gQ2Game.gEffect.Parameters["xLightModel"].SetValue(shadelight.ToVector4()); 374 | 375 | 376 | CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques["TexturedSkin"]; 377 | 378 | 379 | // bind new texture 380 | CProgram.gQ2Game.gEffect.Parameters["xTextureSkin"].SetValue(_CurrentEntity.Model.ModelMD2.skins[_CurrentEntity.ModelCurrentSkin]); 381 | 382 | foreach (EffectPass pass in CProgram.gQ2Game.gEffect.CurrentTechnique.Passes) 383 | { 384 | pass.Apply(); 385 | CProgram.gQ2Game.gGraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _CurrentEntity.Model.ModelMD2.md2.num_tris); 386 | } 387 | 388 | CMain.c_brush_polys += _CurrentEntity.Model.ModelMD2.md2.num_tris; 389 | } 390 | 391 | 392 | 393 | // md2 model renderfx flags 394 | [Flags] 395 | public enum EModelFlags : int 396 | { 397 | RF_MINLIGHT = 1, // allways have some light (viewmodel) 398 | RF_VIEWERMODEL = 2, // don't draw through eyes, only mirrors 399 | RF_WEAPONMODEL = 4, // only draw through eyes 400 | RF_FULLBRIGHT = 8, // allways draw full intensity 401 | RF_DEPTHHACK = 16, // for view weapon Z crunching 402 | RF_TRANSLUCENT = 32, 403 | RF_FRAMELERP = 64, 404 | RF_BEAM = 128, 405 | RF_CUSTOMSKIN = 256, // skin is an index in image_precache 406 | RF_GLOW = 512, // pulse lighting for bonus items 407 | RF_SHELL_RED = 1024, 408 | RF_SHELL_GREEN = 2048, 409 | RF_SHELL_BLUE = 4096 410 | } 411 | 412 | 413 | // ================================================================ 414 | // 415 | // MD2 MODELS 416 | // 417 | // ================================================================ 418 | 419 | public const int IDALIASHEADER = (('2' << 24) + ('P' << 16) + ('D' << 8) + 'I'); 420 | private const int ALIAS_VERSION = 8; 421 | private const int MAX_TRIANGLES = 4096; 422 | private const int MAX_VERTS = 2048; 423 | private const int MAX_FRAMES = 512; 424 | private const int MAX_MD2SKINS = 32; 425 | private const int MAX_GLCMDS = 16384; 426 | 427 | private const int MAX_FRAMENAME = 16; 428 | private const int MAX_SKINNAME = 64; 429 | 430 | public struct SSTVert 431 | { 432 | public short s; 433 | public short t; 434 | } 435 | 436 | public struct SDTriangle 437 | { 438 | public short[] index_xyz; // size 3 439 | public short[] index_st; // size 3 440 | } 441 | 442 | public struct STrivertx 443 | { 444 | public byte[] v; // size 3 445 | public byte lightnormalindex; 446 | } 447 | 448 | public struct SAliasFrameDesc 449 | { 450 | public float[] scale; // size 3 (multiply byte verts by this) 451 | public float[] translate; // size 3 (then add this) 452 | public char[] name; // size 16 (frame name from grabbing) 453 | public STrivertx[] verts; 454 | } 455 | 456 | // the glcmd format: 457 | // a positive integer starts a tristrip command, followed by that many 458 | // vertex structures. 459 | // a negative integer starts a trifan command, followed by -x vertexes 460 | // a zero indicates the end of the command list. 461 | // a vertex consists of a floating point s, a floating point t, 462 | // and an integer vertex index. 463 | 464 | public struct SMd2 465 | { 466 | public byte[] identification; // size 4 (should be IDP2) 467 | public int version; // version: must be 8 468 | 469 | public int skinwidth; // texture width 470 | public int skinheight; // texture height 471 | 472 | public int framesize; // byte size of each frame 473 | 474 | public int num_skins; // number of skins 475 | public int num_xyz; // number of vertices 476 | public int num_st; // number of texture coordinates (greater than num_xyz for seams) 477 | public int num_tris; // number of triangles 478 | public int num_glcmds; // dwords in strip/fan command list 479 | public int num_frames; // number of frames 480 | 481 | public int ofs_skins; // each skin is a MAX_SKINNAME string 482 | public int ofs_st; // byte offset from start for stverts 483 | public int ofs_tris; // offset for dtriangles 484 | public int ofs_frames; // offset for first frame 485 | public int ofs_glcmds; // offset for strip/fan command list 486 | public int ofs_end; // end of file 487 | } 488 | 489 | } 490 | } 491 | -------------------------------------------------------------------------------- /Server.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | 31 | namespace Q2BSP 32 | { 33 | public class CServer 34 | { 35 | // max recipients for heartbeat packets 36 | public const int MAX_MASTERS = 8; 37 | 38 | //server_static_t svs; // persistant server info 39 | public static SServer sv; // local server 40 | 41 | 42 | public struct SServer 43 | { 44 | public EServerState state; // precache commands are only valid during load 45 | 46 | public bool attractloop; // running cinematics and demos for the local system only 47 | public bool loadgame; // client begins should reuse existing entity 48 | 49 | public uint time; // always sv.framenum * 100 msec 50 | public int framenum; 51 | 52 | public string name; // size: MAX_QPATH (map name, or cinematic name) 53 | //struct cmodel_s *models[MAX_MODELS]; 54 | 55 | public string[] configstrings; // size: [MAX_CONFIGSTRINGS, MAX_QPATH] 56 | public EClientState[] baselines; // size: MAX_EDICTS 57 | 58 | // the multicast buffer is used to send a message to a set of clients 59 | // it is only used to marshall data until SV_Multicast is called 60 | public CCommon.SSizeBuf multicast; 61 | public byte[] multicast_buf; // size: MAX_MSGLEN 62 | 63 | // demo server information 64 | //FILE *demofile; 65 | public bool timedemo; // don't time sync 66 | } 67 | 68 | 69 | 70 | 71 | /*typedef struct 72 | { 73 | server_state_t state; // precache commands are only valid during load 74 | 75 | qboolean attractloop; // running cinematics and demos for the local system only 76 | qboolean loadgame; // client begins should reuse existing entity 77 | 78 | unsigned time; // always sv.framenum * 100 msec 79 | int framenum; 80 | 81 | char name[MAX_QPATH]; // map name, or cinematic name 82 | struct cmodel_s *models[MAX_MODELS]; 83 | 84 | char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]; 85 | entity_state_t baselines[MAX_EDICTS]; 86 | 87 | // the multicast buffer is used to send a message to a set of clients 88 | // it is only used to marshall data until SV_Multicast is called 89 | sizebuf_t multicast; 90 | byte multicast_buf[MAX_MSGLEN]; 91 | 92 | // demo server information 93 | FILE *demofile; 94 | qboolean timedemo; // don't time sync 95 | } server_t;*/ 96 | 97 | 98 | 99 | 100 | 101 | public enum EServerState 102 | { 103 | ss_dead, // no map loaded 104 | ss_loading, // spawning level edicts 105 | ss_game, // actively running 106 | ss_cinematic, 107 | ss_demo, 108 | ss_pic 109 | } 110 | // some qc commands are only valid before the server has finished 111 | // initializing (precache commands, static sounds / objects, etc) 112 | 113 | public enum EClientState 114 | { 115 | cs_free, // can be reused for a new connection 116 | cs_zombie, // client has been disconnected, but don't reuse connection for a couple seconds 117 | cs_connected, // has been assigned to a client_t, but not in game yet 118 | cs_spawned // client is fully in game 119 | } 120 | 121 | 122 | 123 | 124 | 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Shared.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | using Microsoft.Xna.Framework; 31 | 32 | namespace Q2BSP 33 | { 34 | public class CShared 35 | { 36 | public const int MAX_QPATH = 64; 37 | public static Vector3 vec3_origin; 38 | 39 | public static string Com_ToString(char[] chr) 40 | { 41 | string str; 42 | 43 | if (chr == null) 44 | return null; 45 | 46 | if (chr.Length == 0) 47 | return ""; 48 | 49 | System.Text.StringBuilder SB = new System.Text.StringBuilder(); 50 | SB.Append(chr); 51 | 52 | str = SB.ToString().Trim(); 53 | SB = null; 54 | 55 | if (str.IndexOf('\0') != -1) 56 | str = str.Substring(0, str.IndexOf('\0')); 57 | 58 | return str; 59 | } 60 | 61 | public static char[] Com_ToChar(string str, bool nullTerminate) 62 | { 63 | int i; 64 | char[] chr; 65 | 66 | if (str == null) 67 | return null; 68 | 69 | if (nullTerminate == true) 70 | chr = new char[str.Length + 1]; 71 | else 72 | chr = new char[str.Length]; 73 | 74 | for (i = 0; i < str.Length; i++) 75 | { 76 | chr[i] = str[i]; 77 | } 78 | 79 | if (nullTerminate == true) 80 | chr[i] = '\0'; 81 | 82 | return chr; 83 | } 84 | 85 | public static void VectorScale(Vector3 vecIn, float scale, ref Vector3 vecOut) 86 | { 87 | vecOut.X = vecIn.X * scale; 88 | vecOut.Y = vecIn.Y * scale; 89 | vecOut.Z = vecIn.Z * scale; 90 | } 91 | 92 | public static void AngleVectors(Vector3 angles, ref Vector3 forward, ref Vector3 right, ref Vector3 up) 93 | { 94 | float angle; 95 | float sr, sp, sy, cr, cp, cy; 96 | 97 | angle = (float)(angles.Y * (Math.PI * 2 / 360)); 98 | sy = (float)Math.Sin(angle); 99 | cy = (float)Math.Cos(angle); 100 | 101 | angle = (float)(angles.X * (Math.PI * 2 / 360)); 102 | sp = (float)Math.Sin(angle); 103 | cp = (float)Math.Cos(angle); 104 | 105 | angle = (float)(angles.Z * (Math.PI * 2 / 360)); 106 | sr = (float)Math.Sin(angle); 107 | cr = (float)Math.Cos(angle); 108 | 109 | 110 | forward.X = cp * cy; 111 | forward.Y = cp * sy; 112 | forward.Z = -sp; 113 | 114 | right.X = (-1 * sr * sp * cy + -1 * cr * -sy); 115 | right.Y = (-1 * sr * sp * sy + -1 * cr * cy); 116 | right.Z = -1 * sr * cp; 117 | 118 | up.X = (cr * sp * cy + -sr * -sy); 119 | up.Y = (cr * sp * sy + -sr * cy); 120 | up.Z = cr * cp; 121 | } 122 | 123 | /*void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) 124 | { 125 | float angle; 126 | static float sr, sp, sy, cr, cp, cy; 127 | // static to help MS compiler fp bugs 128 | 129 | angle = angles[YAW] * (M_PI*2 / 360); 130 | sy = sin(angle); 131 | cy = cos(angle); 132 | angle = angles[PITCH] * (M_PI*2 / 360); 133 | sp = sin(angle); 134 | cp = cos(angle); 135 | angle = angles[ROLL] * (M_PI*2 / 360); 136 | sr = sin(angle); 137 | cr = cos(angle); 138 | 139 | if (forward) 140 | { 141 | forward[0] = cp*cy; 142 | forward[1] = cp*sy; 143 | forward[2] = -sp; 144 | } 145 | if (right) 146 | { 147 | right[0] = (-1*sr*sp*cy+-1*cr*-sy); 148 | right[1] = (-1*sr*sp*sy+-1*cr*cy); 149 | right[2] = -1*sr*cp; 150 | } 151 | if (up) 152 | { 153 | up[0] = (cr*sp*cy+-sr*-sy); 154 | up[1] = (cr*sp*sy+-sr*cy); 155 | up[2] = cr*cp; 156 | } 157 | }*/ 158 | 159 | 160 | 161 | public struct SCPlane 162 | { 163 | public Microsoft.Xna.Framework.Vector3 normal; 164 | public float dist; 165 | public byte type; // for fast side tests: 0,1,2 = axial, 3 = nonaxial 166 | public byte signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision 167 | 168 | // unused - alignment? 169 | public byte[] pad; // size: 2 170 | } 171 | 172 | 173 | 174 | // 175 | // per-level limits 176 | // 177 | public const int MAX_CLIENTS = 256; // absolute limit 178 | public const int MAX_EDICTS = 1024; // must change protocol to increase more 179 | public const int MAX_LIGHTSTYLES = 256; 180 | public const int MAX_MODELS = 256; // these are sent over the net as bytes 181 | public const int MAX_SOUNDS = 256; // so they cannot be blindly increased 182 | public const int MAX_IMAGES = 256; 183 | public const int MAX_ITEMS = 256; 184 | public const int MAX_GENERAL = (MAX_CLIENTS * 2); // general config strings 185 | 186 | 187 | // 188 | // Config strings are a general means of communication from the server to all connected clients. 189 | // Each config string can be at most MAX_QPATH characters. 190 | // 191 | public const int CS_NAME = 0; 192 | public const int CS_CDTRACK = 1; 193 | public const int CS_SKY = 2; 194 | public const int CS_SKYAXIS = 3; // %f %f %f format 195 | public const int CS_SKYROTATE = 4; 196 | public const int CS_STATUSBAR = 5; // display program string 197 | 198 | public const int CS_AIRACCEL = 29; // air acceleration control 199 | public const int CS_MAXCLIENTS = 30; 200 | public const int CS_MAPCHECKSUM = 31; // for catching cheater maps 201 | 202 | public const int CS_MODELS = 32; 203 | public const int CS_SOUNDS = (CS_MODELS + MAX_MODELS); 204 | public const int CS_IMAGES = (CS_SOUNDS + MAX_SOUNDS); 205 | public const int CS_LIGHTS = (CS_IMAGES + MAX_IMAGES); 206 | public const int CS_ITEMS = (CS_LIGHTS + MAX_LIGHTSTYLES); 207 | public const int CS_PLAYERSKINS = (CS_ITEMS + MAX_ITEMS); 208 | public const int CS_GENERAL = (CS_PLAYERSKINS + MAX_CLIENTS); 209 | public const int MAX_CONFIGSTRINGS = (CS_GENERAL + MAX_GENERAL); 210 | 211 | 212 | 213 | 214 | 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /Sky.cs: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 2000-2011 Korvin Korax 4 | Author: Jacques Krige 5 | http://www.sagamedev.com 6 | http://www.korvinkorax.com 7 | 8 | This file is part of Quake2 BSP XNA Renderer source code. 9 | Parts of the source code is copyright (C) Id Software, Inc. 10 | 11 | Quake2 BSP XNA Renderer source code is free software; you can redistribute it 12 | and/or modify it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation; either version 2 of the License, 14 | or (at your option) any later version. 15 | 16 | Quake2 BSP XNA Renderer source code is distributed in the hope that it will be 17 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with Foobar; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | =========================================================================== 25 | */ 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using Microsoft.Xna.Framework; 30 | using Microsoft.Xna.Framework.Graphics; 31 | using System.Text; 32 | 33 | namespace Q2BSP 34 | { 35 | public class CSky 36 | { 37 | private int[] skytexorder; 38 | private string[] suf; 39 | 40 | private string skyname; // size: MAX_QPATH 41 | private float skyrotate; 42 | private Vector3 skyaxis; 43 | 44 | private float[,] skymins; 45 | private float[,] skymaxs; 46 | 47 | Quaternion SkyboxRotation; 48 | 49 | private VertexDeclaration SkyboxVertexDeclaration; 50 | private int[,] st_to_vec; 51 | 52 | public CSky() 53 | { 54 | skytexorder = new int[] { 0, 2, 1, 3, 4, 5 }; 55 | suf = new string[] { "rt", "bk", "lf", "ft", "up", "dn" }; 56 | 57 | // 1 = s, 2 = t, 3 = 2048 58 | st_to_vec = new int[,] 59 | { 60 | { 3, -1, 2 }, 61 | { -3, 1, 2 }, 62 | { 1, 3, 2 }, 63 | { -1, -3, 2 }, 64 | { -2, -1, 3 }, // 0 degrees yaw, look straight up 65 | { 2, -1, -3 } // look straight down 66 | }; // [6, 3] 67 | 68 | skymins = new float[,] 69 | { 70 | { -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f }, 71 | { -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f } 72 | }; // [2, 6] 73 | 74 | skymaxs = new float[,] 75 | { 76 | { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, 77 | { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f } 78 | }; // [2, 6] 79 | 80 | SkyboxRotation = Quaternion.CreateFromYawPitchRoll(0.0f, 0.0f, 0.0f); 81 | } 82 | 83 | private SkyboxVertexFormat MakeSkyVec(int Width, float s, float t, int axis) 84 | { 85 | Vector3 v; 86 | SkyboxVertexFormat SVF; 87 | float[] v2 = new float[3]; 88 | float[] b = new float[] { s * Width, t * Width, Width }; 89 | float sky_min = 1.0f / Width; 90 | float sky_max = (Width - 1.0f) / Width; 91 | 92 | for (int i = 0; i < 3; i++) 93 | { 94 | int k = st_to_vec[axis, i]; 95 | 96 | if (k < 0) 97 | v2[i] = -b[-k - 1]; 98 | else 99 | v2[i] = b[k - 1]; 100 | } 101 | 102 | v.X = v2[0]; 103 | v.Y = v2[1]; 104 | v.Z = v2[2]; 105 | 106 | // avoid bilerp seam 107 | s = (s + 1) * 0.5f; 108 | t = (t + 1) * 0.5f; 109 | 110 | if (s < sky_min) 111 | s = sky_min; 112 | else if (s > sky_max) 113 | s = sky_max; 114 | 115 | if (t < sky_min) 116 | t = sky_min; 117 | else if (t > sky_max) 118 | t = sky_max; 119 | 120 | t = 1.0f - t; 121 | 122 | SVF.Position.X = v.X; 123 | SVF.Position.Y = v.Y; 124 | SVF.Position.Z = v.Z; 125 | SVF.TextureCoordinate.X = s; 126 | SVF.TextureCoordinate.Y = t; 127 | 128 | return SVF; 129 | } 130 | 131 | public void DrawSkyBox() 132 | { 133 | Matrix wMatrix; 134 | float RotationSpeed = ((float)CProgram.gQ2Game.gCMain.gTimeGame.ElapsedGameTime.TotalMilliseconds / 1000.0f) * skyrotate; 135 | 136 | // update skybox rotation 137 | SkyboxRotation *= Quaternion.CreateFromYawPitchRoll 138 | ( 139 | Microsoft.Xna.Framework.MathHelper.ToRadians(skyaxis.Y * RotationSpeed), 140 | Microsoft.Xna.Framework.MathHelper.ToRadians(skyaxis.X * RotationSpeed), 141 | Microsoft.Xna.Framework.MathHelper.ToRadians(skyaxis.Z * RotationSpeed) 142 | ); 143 | 144 | // update HLSL variables 145 | CProgram.gQ2Game.gCMain.UpdateHLSL(-1); 146 | 147 | // set vertex buffer 148 | CProgram.gQ2Game.gGraphicsDevice.SetVertexBuffer(CQ2BSP.SWorldData.vbSkybox); 149 | 150 | // create skybox rotation and translation matrix 151 | wMatrix = Matrix.CreateFromQuaternion(SkyboxRotation); 152 | wMatrix *= Matrix.CreateTranslation(CClient.cl.RefDef.ViewOrigin); 153 | 154 | // update HLSL variables 155 | CProgram.gQ2Game.gEffect.Parameters["xWorld"].SetValue(wMatrix); 156 | 157 | // set a rendering technique 158 | CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques["TexturedSkybox"]; 159 | 160 | // reset the depthstencil state and disable the depth buffer 161 | CProgram.gQ2Game.gCMain.gDepthStencilState = new DepthStencilState(); 162 | CProgram.gQ2Game.gCMain.gDepthStencilState.DepthBufferWriteEnable = false; 163 | CProgram.gQ2Game.gGraphicsDevice.DepthStencilState = CProgram.gQ2Game.gCMain.gDepthStencilState; 164 | 165 | for (int i = 0; i < 6; i++) 166 | { 167 | // bind the skybox side texture 168 | CProgram.gQ2Game.gEffect.Parameters["xTextureDiffuse"].SetValue(CQ2BSP.SWorldData.WorldSkies[skytexorder[i]]); 169 | 170 | // render the skybox side primitives 171 | foreach (EffectPass pass in CProgram.gQ2Game.gEffect.CurrentTechnique.Passes) 172 | { 173 | pass.Apply(); 174 | CProgram.gQ2Game.gGraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, i * 6, 2); 175 | } 176 | } 177 | 178 | // reset the depthstencil state and enable the depth buffer 179 | CProgram.gQ2Game.gCMain.gDepthStencilState = new DepthStencilState(); 180 | CProgram.gQ2Game.gCMain.gDepthStencilState.DepthBufferWriteEnable = true; 181 | CProgram.gQ2Game.gGraphicsDevice.DepthStencilState = CProgram.gQ2Game.gCMain.gDepthStencilState; 182 | } 183 | 184 | public void BuildSkybox() 185 | { 186 | List vertbuffer = new List(); 187 | SkyboxVertexDeclaration = new VertexDeclaration(SkyboxVertexFormat.VertexElements); 188 | 189 | // get skybox info from the worldspawn 190 | // "sky" : environment map name 191 | // "skyaxis" : vector axis for rotating sky 192 | // "skyrotate" : speed of rotation in degrees/second 193 | for (int i = 0; i < CQ2BSP.SWorldData.entities.Length; i++) 194 | { 195 | if (CProgram.gQ2Game.gCMain.gCModel.ValueForKey(CQ2BSP.SWorldData.entities[i], "classname") == "worldspawn") 196 | { 197 | string _skyrotate; 198 | string _skyaxis; 199 | 200 | skyname = CProgram.gQ2Game.gCMain.gCModel.ValueForKey(CQ2BSP.SWorldData.entities[i], "sky"); 201 | if (string.IsNullOrEmpty(skyname) == true) 202 | skyname = "unit1_"; 203 | 204 | _skyaxis = CProgram.gQ2Game.gCMain.gCModel.ValueForKey(CQ2BSP.SWorldData.entities[i], "skyaxis"); 205 | if (string.IsNullOrEmpty(_skyaxis) == true) 206 | { 207 | skyaxis.X = 0.0f; 208 | skyaxis.Y = 0.0f; 209 | skyaxis.Z = 0.0f; 210 | } 211 | else 212 | { 213 | string[] SkyAxisArgs; 214 | char[] delim = new char[1]; 215 | 216 | delim[0] = ' '; 217 | SkyAxisArgs = _skyaxis.Split(delim, StringSplitOptions.RemoveEmptyEntries); 218 | 219 | if (SkyAxisArgs.Length == 3) 220 | { 221 | skyaxis.X = Convert.ToSingle(SkyAxisArgs[0]); 222 | skyaxis.Y = Convert.ToSingle(SkyAxisArgs[1]); 223 | skyaxis.Z = Convert.ToSingle(SkyAxisArgs[2]); 224 | } 225 | } 226 | 227 | _skyrotate = CProgram.gQ2Game.gCMain.gCModel.ValueForKey(CQ2BSP.SWorldData.entities[i], "skyrotate"); 228 | if (string.IsNullOrEmpty(_skyrotate) == true) 229 | skyrotate = 0.0f; 230 | else 231 | skyrotate = Convert.ToSingle(_skyrotate); 232 | } 233 | } 234 | 235 | 236 | CProgram.gQ2Game.gCMain.gCImage.StartSky(ref CQ2BSP.SWorldData); 237 | 238 | for (int i = 0; i < 6; i++) 239 | { 240 | int Width; 241 | int Height; 242 | 243 | CProgram.gQ2Game.gCMain.gCImage.FindImage(skyname + suf[i], out Width, out Height, CImage.EImageType.IT_SKY); 244 | 245 | // triangle 1 (TriangleList) 246 | vertbuffer.Add(MakeSkyVec(Width, skymins[0, i], skymins[1, i], i)); 247 | vertbuffer.Add(MakeSkyVec(Width, skymins[0, i], skymaxs[1, i], i)); 248 | vertbuffer.Add(MakeSkyVec(Width, skymaxs[0, i], skymaxs[1, i], i)); 249 | 250 | // triangle 2 (TriangleList) 251 | vertbuffer.Add(MakeSkyVec(Width, skymins[0, i], skymins[1, i], i)); 252 | vertbuffer.Add(MakeSkyVec(Width, skymaxs[0, i], skymaxs[1, i], i)); 253 | vertbuffer.Add(MakeSkyVec(Width, skymaxs[0, i], skymins[1, i], i)); 254 | 255 | // TriangleFan 256 | //vertbuffer.Add(MakeSkyVec(Width, skymins[0, i], skymins[1, i], i)); 257 | //vertbuffer.Add(MakeSkyVec(Width, skymins[0, i], skymaxs[1, i], i)); 258 | //vertbuffer.Add(MakeSkyVec(Width, skymaxs[0, i], skymaxs[1, i], i)); 259 | //vertbuffer.Add(MakeSkyVec(Width, skymaxs[0, i], skymins[1, i], i)); 260 | } 261 | 262 | CQ2BSP.SWorldData.vbSkybox = new VertexBuffer(CProgram.gQ2Game.gGraphicsDevice, SkyboxVertexDeclaration, vertbuffer.Count, BufferUsage.WriteOnly); 263 | CQ2BSP.SWorldData.vbSkybox.SetData(vertbuffer.ToArray()); 264 | 265 | CProgram.gQ2Game.gCMain.gCImage.FinalizeSky(ref CQ2BSP.SWorldData); 266 | } 267 | 268 | 269 | // ================================================================ 270 | // 271 | // SKYBOX VERTEX FORMAT 272 | // 273 | // ================================================================ 274 | 275 | public struct SkyboxVertexFormat 276 | { 277 | public Vector3 Position; 278 | public Vector2 TextureCoordinate; 279 | 280 | public static VertexElement[] VertexElements = 281 | { 282 | new VertexElement(sizeof(float) * 0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), 283 | new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0), 284 | }; 285 | } 286 | 287 | } 288 | } 289 | --------------------------------------------------------------------------------