+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="Content-Style-Type" content="text/css">
- <title></title>
- <meta name="Generator" content="Cocoa HTML Writer">
- <meta name="CocoaVersion" content="1038.25">
- <style type="text/css">
- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
- </style>
-</head>
-<body>
-<p class="p1"><a href="http://dev.xonotic.org/projects/xonotic/wiki/Mapping">Xonotic Mapping Wiki</A></p>
-</body>
-</html>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
-<!-- /etc/fonts/fonts.conf file to configure system font access -->
-<fontconfig>
-
-<!--
- DO NOT EDIT THIS FILE.
- IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
- LOCAL CHANGES BELONG IN 'local.conf'.
-
- The intent of this standard configuration file is to be adequate for
- most environments. If you have a reasonably normal environment and
- have found problems with this configuration, they are probably
- things that others will also want fixed. Please submit any
- problems to the fontconfig bugzilla system located at fontconfig.org
-
- Note that the normal 'make install' procedure for fontconfig is to
- replace any existing fonts.conf file with the new version. Place
- any local customizations in local.conf which this file references.
-
- Keith Packard
--->
-
-<!-- Font directory list -->
-
- <dir>WINDOWSFONTDIR</dir>
-
- <dir>~/.fonts</dir>
-
-<!--
- Accept deprecated 'mono' alias, replacing it with 'monospace'
--->
- <match target="pattern">
- <test qual="any" name="family">
- <string>mono</string>
- </test>
- <edit name="family" mode="assign">
- <string>monospace</string>
- </edit>
- </match>
-
-<!--
- Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
--->
- <match target="pattern">
- <test qual="any" name="family">
- <string>sans serif</string>
- </test>
- <edit name="family" mode="assign">
- <string>sans-serif</string>
- </edit>
- </match>
-
-<!--
- Accept deprecated 'sans' alias, replacing it with 'sans-serif'
--->
- <match target="pattern">
- <test qual="any" name="family">
- <string>sans</string>
- </test>
- <edit name="family" mode="assign">
- <string>sans-serif</string>
- </edit>
- </match>
-
-<!--
- Load local system customization file
--->
- <include ignore_missing="yes">conf.d</include>
-
-<!-- Font cache directory list -->
-
- <cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir>
- <cachedir>~/.fontconfig</cachedir>
-
- <config>
-<!--
- These are the default Unicode chars that are expected to be blank
- in fonts. All other blank chars are assumed to be broken and
- won't appear in the resulting charsets
- -->
- <blank>
- <int>0x0020</int> <!-- SPACE -->
- <int>0x00A0</int> <!-- NO-BREAK SPACE -->
- <int>0x00AD</int> <!-- SOFT HYPHEN -->
- <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER -->
- <int>0x0600</int> <!-- ARABIC NUMBER SIGN -->
- <int>0x0601</int> <!-- ARABIC SIGN SANAH -->
- <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER -->
- <int>0x0603</int> <!-- ARABIC SIGN SAFHA -->
- <int>0x06DD</int> <!-- ARABIC END OF AYAH -->
- <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK -->
- <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER -->
- <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER -->
- <int>0x1680</int> <!-- OGHAM SPACE MARK -->
- <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ -->
- <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA -->
- <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR -->
- <int>0x2000</int> <!-- EN QUAD -->
- <int>0x2001</int> <!-- EM QUAD -->
- <int>0x2002</int> <!-- EN SPACE -->
- <int>0x2003</int> <!-- EM SPACE -->
- <int>0x2004</int> <!-- THREE-PER-EM SPACE -->
- <int>0x2005</int> <!-- FOUR-PER-EM SPACE -->
- <int>0x2006</int> <!-- SIX-PER-EM SPACE -->
- <int>0x2007</int> <!-- FIGURE SPACE -->
- <int>0x2008</int> <!-- PUNCTUATION SPACE -->
- <int>0x2009</int> <!-- THIN SPACE -->
- <int>0x200A</int> <!-- HAIR SPACE -->
- <int>0x200B</int> <!-- ZERO WIDTH SPACE -->
- <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER -->
- <int>0x200D</int> <!-- ZERO WIDTH JOINER -->
- <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK -->
- <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK -->
- <int>0x2028</int> <!-- LINE SEPARATOR -->
- <int>0x2029</int> <!-- PARAGRAPH SEPARATOR -->
- <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING -->
- <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING -->
- <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING -->
- <int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE -->
- <int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE -->
- <int>0x202F</int> <!-- NARROW NO-BREAK SPACE -->
- <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE -->
- <int>0x2060</int> <!-- WORD JOINER -->
- <int>0x2061</int> <!-- FUNCTION APPLICATION -->
- <int>0x2062</int> <!-- INVISIBLE TIMES -->
- <int>0x2063</int> <!-- INVISIBLE SEPARATOR -->
- <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING -->
- <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING -->
- <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING -->
- <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING -->
- <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES -->
- <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES -->
- <int>0x2800</int> <!-- BRAILLE PATTERN BLANK -->
- <int>0x3000</int> <!-- IDEOGRAPHIC SPACE -->
- <int>0x3164</int> <!-- HANGUL FILLER -->
- <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE -->
- <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER -->
- <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR -->
- <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR -->
- <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR -->
- </blank>
-<!--
- Rescan configuration every 30 seconds when FcFontSetList is called
- -->
- <rescan>
- <int>30</int>
- </rescan>
- </config>
-
-</fontconfig>
+++ /dev/null
-<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
-<!-- generated by Radiant setup, modify at your own risks -->
-<game
- type="voretournament"
- index="1"
- name="VoreTournament"
- enginepath_win32="C:/Program Files/VoreTournament/"
- enginepath_linux="/usr/share/games/voretournament/"
- enginepath_macos="/Applications/VoreTournament"
- engine_win32="voretournament-sdl.exe"
- engine_linux="voretournament-sdl"
- engine_macos="VoreTournament.app"
- prefix=".voretournament"
- basegame="data"
- basegamename="VoreTournament"
- unknowngamename="Custom VoreTournament modification"
- shaderpath="scripts"
- archivetypes="pk3"
- texturetypes="tga jpg png"
- modeltypes="md3 mdl md2 ase obj"
- maptypes="mapq3"
- shaders="quake3"
- entityclass="quake3"
- entityclasstype="def"
- entities="quake3"
- brushtypes="quake3"
- patchtypes="quake3"
-/>
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "AUTHORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-#include "utils.cg"
-
-struct cg_vertex2fragment
-{
- float4 position : TEXCOORD0;
- float4 tex_diffuse_bump : TEXCOORD1;
- float4 tex_specular : TEXCOORD2;
- float4 tex_atten_xy_z : TEXCOORD3;
-
- float3 tangent : TEXCOORD4;
- float3 binormal : TEXCOORD5;
- float3 normal : TEXCOORD6;
-};
-
-struct cg_fragment2final
-{
- float4 color : COLOR;
-};
-
-
-cg_fragment2final main(cg_vertex2fragment IN,
- uniform sampler2D diffusemap,
- uniform sampler2D bumpmap,
- uniform sampler2D specularmap,
- uniform sampler2D attenuationmap_xy,
- uniform sampler2D attenuationmap_z,
- uniform float3 view_origin,
- uniform float3 light_origin,
- uniform float3 light_color,
- uniform float bump_scale,
- uniform float specular_exponent)
-{
- cg_fragment2final OUT;
-
- // construct object-space-to-tangent-space 3x3 matrix
- float3x3 rotation = float3x3(IN.tangent, IN.binormal, IN.normal);
-
- // compute view direction in tangent space
- float3 V = normalize(mul(rotation, view_origin - IN.position.xyz));
-
- // compute light direction in tangent space
- float3 L = normalize(mul(rotation, (light_origin - IN.position.xyz)));
-
- // compute half angle in tangent space
- float3 H = normalize(L + V);
-
- // compute normal in tangent space from bumpmap
- float3 T = CG_Expand(tex2D(bumpmap, IN.tex_diffuse_bump.zw).xyz);
- T.z *= bump_scale;
- float3 N = normalize(T);
-
- // compute the diffuse term
- float4 diffuse = tex2D(diffusemap, IN.tex_diffuse_bump.xy);
- diffuse.rgb *= light_color * saturate(dot(N, L));
-
- // compute the specular term
- float3 specular = tex2D(specularmap, IN.tex_specular.xy).rgb * light_color * pow(saturate(dot(N, H)), specular_exponent);
-
- // compute attenuation
- float3 attenuation_xy = tex2Dproj(attenuationmap_xy, float3(IN.tex_atten_xy_z.x, IN.tex_atten_xy_z.y, IN.tex_atten_xy_z.w)).rgb;
- float3 attenuation_z = tex2D(attenuationmap_z, float2(IN.tex_atten_xy_z.z, 0)).rgb;
-
- // compute final color
- OUT.color.rgba = diffuse;
- OUT.color.rgb += specular;
- OUT.color.rgb *= attenuation_xy;
- OUT.color.rgb *= attenuation_z;
-
- return OUT;
-}
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "AUTHORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-
-struct cg_app2vertex
-{
- float4 position : POSITION;
- float4 tex0 : ATTR8;
-
- float3 tangent : ATTR9;
- float3 binormal : ATTR10;
- float3 normal : ATTR11;
-};
-
-struct cg_vertex2fragment
-{
- float4 hposition : POSITION;
-
- float4 position : TEXCOORD0;
- float4 tex_diffuse_bump : TEXCOORD1;
- float4 tex_specular : TEXCOORD2;
- float4 tex_atten_xy_z : TEXCOORD3;
-
- float3 tangent : TEXCOORD4;
- float3 binormal : TEXCOORD5;
- float3 normal : TEXCOORD6;
-};
-
-
-
-cg_vertex2fragment main(cg_app2vertex IN)
-{
- cg_vertex2fragment OUT;
-
- // transform vertex position into homogenous clip-space
- OUT.hposition = mul(glstate.matrix.mvp, IN.position);
-
- // assign position in object space
- OUT.position = IN.position;
-
- // transform texcoords
- OUT.tex_diffuse_bump.xy = mul(glstate.matrix.texture[0], IN.tex0).xy;
-
- // transform texcoords
- OUT.tex_diffuse_bump.zw = mul(glstate.matrix.texture[1], IN.tex0).xy;
-
- // transform texcoords
- OUT.tex_specular = mul(glstate.matrix.texture[2], IN.tex0);
-
- // transform vertex position into light space
- OUT.tex_atten_xy_z = mul(glstate.matrix.texture[3], IN.position);
-
- // assign tangent space vectors
- OUT.tangent = IN.tangent;
- OUT.binormal = IN.binormal;
- OUT.normal = IN.normal;
-
- return OUT;
-}
+++ /dev/null
-!!ARBfp1.0
-# cgc version 1.3.0001, build date Aug 4 2004 10:01:10
-# command line args: -profile arbfp1
-# source file: ..\..\setup\data\tools\gl\lighting_DBS_XY_Z_arbfp1.cg
-# source file: ..\..\setup\data\tools\gl/utils.cg
-#vendor NVIDIA Corporation
-#version 1.0.02
-#profile arbfp1
-#program main
-#semantic main.diffusemap
-#semantic main.bumpmap
-#semantic main.specularmap
-#semantic main.attenuationmap_xy
-#semantic main.attenuationmap_z
-#semantic main.view_origin
-#semantic main.light_origin
-#semantic main.light_color
-#semantic main.bump_scale
-#semantic main.specular_exponent
-#var float4 IN.position : $vin.TEX0 : TEX0 : 0 : 1
-#var float4 IN.tex_diffuse_bump : $vin.TEX1 : TEX1 : 0 : 1
-#var float4 IN.tex_specular : $vin.TEX2 : TEX2 : 0 : 1
-#var float4 IN.tex_atten_xy_z : $vin.TEX3 : TEX3 : 0 : 1
-#var float3 IN.tangent : $vin.TEX4 : TEX4 : 0 : 1
-#var float3 IN.binormal : $vin.TEX5 : TEX5 : 0 : 1
-#var float3 IN.normal : $vin.TEX6 : TEX6 : 0 : 1
-#var sampler2D diffusemap : : texunit 0 : 1 : 1
-#var sampler2D bumpmap : : texunit 1 : 2 : 1
-#var sampler2D specularmap : : texunit 2 : 3 : 1
-#var sampler2D attenuationmap_xy : : texunit 3 : 4 : 1
-#var sampler2D attenuationmap_z : : texunit 4 : 5 : 1
-#var float3 view_origin : : c[4] : 6 : 1
-#var float3 light_origin : : c[2] : 7 : 1
-#var float3 light_color : : c[3] : 8 : 1
-#var float bump_scale : : c[1] : 9 : 1
-#var float specular_exponent : : c[5] : 10 : 1
-#var float4 main.color : $vout.COL : COL : -1 : 1
-#const c[0] = 0.5 2 0
-PARAM c[6] = { { 0.5, 2, 0 },
- program.local[1..5] };
-TEMP R0;
-TEMP R1;
-TEMP R2;
-ADD R1.xyz, -fragment.texcoord[0], c[2];
-DP3 R0.z, fragment.texcoord[6], R1;
-DP3 R0.x, fragment.texcoord[4], R1;
-DP3 R0.y, fragment.texcoord[5], R1;
-ADD R1.xyz, -fragment.texcoord[0], c[4];
-DP3 R0.w, R0, R0;
-DP3 R2.z, fragment.texcoord[6], R1;
-DP3 R2.x, fragment.texcoord[4], R1;
-DP3 R2.y, fragment.texcoord[5], R1;
-RSQ R0.w, R0.w;
-MUL R1.xyz, R0.w, R0;
-DP3 R1.w, R2, R2;
-RSQ R0.w, R1.w;
-MUL R2.xyz, R0.w, R2;
-ADD R2.xyz, R1, R2;
-DP3 R0.w, R2, R2;
-RSQ R2.w, R0.w;
-TEX R0.xyz, fragment.texcoord[1].zwzw, texture[1], 2D;
-ADD R0.xyz, R0, -c[0].x;
-MUL R0.xyz, R0, c[0].y;
-MUL R0.z, R0, c[1].x;
-DP3 R1.w, R0, R0;
-RSQ R0.w, R1.w;
-MUL R0.xyz, R0.w, R0;
-MUL R2.xyz, R2.w, R2;
-DP3_SAT R0.w, R0, R2;
-DP3_SAT R0.x, R0, R1;
-TEX R2.xyz, fragment.texcoord[2], texture[2], 2D;
-MUL R1.xyz, R2, c[3];
-POW R0.w, R0.w, c[5].x;
-MUL R2.xyz, R1, R0.w;
-MUL R1.xyz, R0.x, c[3];
-TEX R0, fragment.texcoord[1], texture[0], 2D;
-MAD R2.xyz, R0, R1, R2;
-TXP R0.xyz, fragment.texcoord[3], texture[3], 2D;
-MOV R1.y, c[0].z;
-MOV R1.x, fragment.texcoord[3].z;
-TEX R1.xyz, R1, texture[4], 2D;
-MUL R0.xyz, R2, R0;
-MUL result.color.xyz, R0, R1;
-MOV result.color.w, R0;
-END
-# 41 instructions, 3 R-regs
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "CONTRIBUTORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-uniform sampler2D u_diffusemap;
-uniform sampler2D u_bumpmap;
-uniform sampler2D u_specularmap;
-uniform sampler2D u_attenuationmap_xy;
-uniform sampler2D u_attenuationmap_z;
-uniform vec3 u_view_origin;
-uniform vec3 u_light_origin;
-uniform vec3 u_light_color;
-uniform float u_bump_scale;
-uniform float u_specular_exponent;
-
-varying vec3 var_vertex;
-varying vec4 var_tex_diffuse_bump;
-varying vec2 var_tex_specular;
-varying vec4 var_tex_atten_xy_z;
-varying mat3 var_mat_os2ts;
-
-void main()
-{
- // compute view direction in tangent space
- vec3 V = normalize(var_mat_os2ts * (u_view_origin - var_vertex));
-
- // compute light direction in tangent space
- vec3 L = normalize(var_mat_os2ts * (u_light_origin - var_vertex));
-
- // compute half angle in tangent space
- vec3 H = normalize(L + V);
-
- // compute normal in tangent space from bumpmap
- vec3 N = 2.0 * (texture2D(u_bumpmap, var_tex_diffuse_bump.pq).xyz - 0.5);
- N.z *= u_bump_scale;
- N = normalize(N);
-
- // compute the diffuse term
- vec4 diffuse = texture2D(u_diffusemap, var_tex_diffuse_bump.st);
- diffuse.rgb *= u_light_color * clamp(dot(N, L), 0.0, 1.0);
-
- // compute the specular term
- vec3 specular = texture2D(u_specularmap, var_tex_specular).rgb * u_light_color * pow(clamp(dot(N, H), 0.0, 1.0), u_specular_exponent);
-
- // compute attenuation
- vec3 attenuation_xy = texture2DProj(u_attenuationmap_xy, vec3(var_tex_atten_xy_z.x, var_tex_atten_xy_z.y, var_tex_atten_xy_z.w)).rgb;
- vec3 attenuation_z = texture2D(u_attenuationmap_z, vec2(var_tex_atten_xy_z.z, 0)).rgb;
-
- // compute final color
- gl_FragColor.rgba = diffuse;
- gl_FragColor.rgb += specular;
- gl_FragColor.rgb *= attenuation_xy;
- gl_FragColor.rgb *= attenuation_z;
-}
-
+++ /dev/null
-!!ARBvp1.0
-# cgc version 1.3.0001, build date Aug 4 2004 10:01:10
-# command line args: -profile arbvp1
-# source file: ..\..\setup\data\tools\gl\lighting_DBS_XY_Z_arbvp1.cg
-#vendor NVIDIA Corporation
-#version 1.0.02
-#profile arbvp1
-#program main
-#semantic glstate : STATE
-#var float4 glstate.material.ambient : STATE.MATERIAL.AMBIENT : : -1 : 0
-#var float4 glstate.material.diffuse : STATE.MATERIAL.DIFFUSE : : -1 : 0
-#var float4 glstate.material.specular : STATE.MATERIAL.SPECULAR : : -1 : 0
-#var float4 glstate.material.emission : STATE.MATERIAL.EMISSION : : -1 : 0
-#var float4 glstate.material.shininess : STATE.MATERIAL.SHININESS : : -1 : 0
-#var float4 glstate.material.front.ambient : STATE.MATERIAL.FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.material.front.diffuse : STATE.MATERIAL.FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.material.front.specular : STATE.MATERIAL.FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.material.front.emission : STATE.MATERIAL.FRONT.EMISSION : : -1 : 0
-#var float4 glstate.material.front.shininess : STATE.MATERIAL.FRONT.SHININESS : : -1 : 0
-#var float4 glstate.material.back.ambient : STATE.MATERIAL.BACK.AMBIENT : : -1 : 0
-#var float4 glstate.material.back.diffuse : STATE.MATERIAL.BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.material.back.specular : STATE.MATERIAL.BACK.SPECULAR : : -1 : 0
-#var float4 glstate.material.back.emission : STATE.MATERIAL.BACK.EMISSION : : -1 : 0
-#var float4 glstate.material.back.shininess : STATE.MATERIAL.BACK.SHININESS : : -1 : 0
-#var float4 glstate.light[0].ambient : STATE.LIGHT[0].AMBIENT : : -1 : 0
-#var float4 glstate.light[0].diffuse : STATE.LIGHT[0].DIFFUSE : : -1 : 0
-#var float4 glstate.light[0].specular : STATE.LIGHT[0].SPECULAR : : -1 : 0
-#var float4 glstate.light[0].position : STATE.LIGHT[0].POSITION : : -1 : 0
-#var float4 glstate.light[0].attenuation : STATE.LIGHT[0].ATTENUATION : : -1 : 0
-#var float4 glstate.light[0].spot.direction : STATE.LIGHT[0].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[0].half : STATE.LIGHT[0].HALF : : -1 : 0
-#var float4 glstate.light[1].ambient : STATE.LIGHT[1].AMBIENT : : -1 : 0
-#var float4 glstate.light[1].diffuse : STATE.LIGHT[1].DIFFUSE : : -1 : 0
-#var float4 glstate.light[1].specular : STATE.LIGHT[1].SPECULAR : : -1 : 0
-#var float4 glstate.light[1].position : STATE.LIGHT[1].POSITION : : -1 : 0
-#var float4 glstate.light[1].attenuation : STATE.LIGHT[1].ATTENUATION : : -1 : 0
-#var float4 glstate.light[1].spot.direction : STATE.LIGHT[1].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[1].half : STATE.LIGHT[1].HALF : : -1 : 0
-#var float4 glstate.light[2].ambient : STATE.LIGHT[2].AMBIENT : : -1 : 0
-#var float4 glstate.light[2].diffuse : STATE.LIGHT[2].DIFFUSE : : -1 : 0
-#var float4 glstate.light[2].specular : STATE.LIGHT[2].SPECULAR : : -1 : 0
-#var float4 glstate.light[2].position : STATE.LIGHT[2].POSITION : : -1 : 0
-#var float4 glstate.light[2].attenuation : STATE.LIGHT[2].ATTENUATION : : -1 : 0
-#var float4 glstate.light[2].spot.direction : STATE.LIGHT[2].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[2].half : STATE.LIGHT[2].HALF : : -1 : 0
-#var float4 glstate.light[3].ambient : STATE.LIGHT[3].AMBIENT : : -1 : 0
-#var float4 glstate.light[3].diffuse : STATE.LIGHT[3].DIFFUSE : : -1 : 0
-#var float4 glstate.light[3].specular : STATE.LIGHT[3].SPECULAR : : -1 : 0
-#var float4 glstate.light[3].position : STATE.LIGHT[3].POSITION : : -1 : 0
-#var float4 glstate.light[3].attenuation : STATE.LIGHT[3].ATTENUATION : : -1 : 0
-#var float4 glstate.light[3].spot.direction : STATE.LIGHT[3].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[3].half : STATE.LIGHT[3].HALF : : -1 : 0
-#var float4 glstate.light[4].ambient : STATE.LIGHT[4].AMBIENT : : -1 : 0
-#var float4 glstate.light[4].diffuse : STATE.LIGHT[4].DIFFUSE : : -1 : 0
-#var float4 glstate.light[4].specular : STATE.LIGHT[4].SPECULAR : : -1 : 0
-#var float4 glstate.light[4].position : STATE.LIGHT[4].POSITION : : -1 : 0
-#var float4 glstate.light[4].attenuation : STATE.LIGHT[4].ATTENUATION : : -1 : 0
-#var float4 glstate.light[4].spot.direction : STATE.LIGHT[4].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[4].half : STATE.LIGHT[4].HALF : : -1 : 0
-#var float4 glstate.light[5].ambient : STATE.LIGHT[5].AMBIENT : : -1 : 0
-#var float4 glstate.light[5].diffuse : STATE.LIGHT[5].DIFFUSE : : -1 : 0
-#var float4 glstate.light[5].specular : STATE.LIGHT[5].SPECULAR : : -1 : 0
-#var float4 glstate.light[5].position : STATE.LIGHT[5].POSITION : : -1 : 0
-#var float4 glstate.light[5].attenuation : STATE.LIGHT[5].ATTENUATION : : -1 : 0
-#var float4 glstate.light[5].spot.direction : STATE.LIGHT[5].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[5].half : STATE.LIGHT[5].HALF : : -1 : 0
-#var float4 glstate.light[6].ambient : STATE.LIGHT[6].AMBIENT : : -1 : 0
-#var float4 glstate.light[6].diffuse : STATE.LIGHT[6].DIFFUSE : : -1 : 0
-#var float4 glstate.light[6].specular : STATE.LIGHT[6].SPECULAR : : -1 : 0
-#var float4 glstate.light[6].position : STATE.LIGHT[6].POSITION : : -1 : 0
-#var float4 glstate.light[6].attenuation : STATE.LIGHT[6].ATTENUATION : : -1 : 0
-#var float4 glstate.light[6].spot.direction : STATE.LIGHT[6].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[6].half : STATE.LIGHT[6].HALF : : -1 : 0
-#var float4 glstate.light[7].ambient : STATE.LIGHT[7].AMBIENT : : -1 : 0
-#var float4 glstate.light[7].diffuse : STATE.LIGHT[7].DIFFUSE : : -1 : 0
-#var float4 glstate.light[7].specular : STATE.LIGHT[7].SPECULAR : : -1 : 0
-#var float4 glstate.light[7].position : STATE.LIGHT[7].POSITION : : -1 : 0
-#var float4 glstate.light[7].attenuation : STATE.LIGHT[7].ATTENUATION : : -1 : 0
-#var float4 glstate.light[7].spot.direction : STATE.LIGHT[7].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[7].half : STATE.LIGHT[7].HALF : : -1 : 0
-#var float4 glstate.lightmodel.ambient : STATE.LIGHTMODEL.AMBIENT : : -1 : 0
-#var float4 glstate.lightmodel.scenecolor : STATE.LIGHTMODEL.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightmodel.front.scenecolor : STATE.LIGHTMODEL.FRONT.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightmodel.back.scenecolor : STATE.LIGHTMODEL.BACK.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightprod[0].ambient : STATE.LIGHTPROD[0].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].diffuse : STATE.LIGHTPROD[0].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].specular : STATE.LIGHTPROD[0].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[0].front.ambient : STATE.LIGHTPROD[0].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].front.diffuse : STATE.LIGHTPROD[0].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].front.specular : STATE.LIGHTPROD[0].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[0].back.ambient : STATE.LIGHTPROD[0].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].back.diffuse : STATE.LIGHTPROD[0].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].back.specular : STATE.LIGHTPROD[0].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].ambient : STATE.LIGHTPROD[1].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].diffuse : STATE.LIGHTPROD[1].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].specular : STATE.LIGHTPROD[1].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].front.ambient : STATE.LIGHTPROD[1].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].front.diffuse : STATE.LIGHTPROD[1].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].front.specular : STATE.LIGHTPROD[1].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].back.ambient : STATE.LIGHTPROD[1].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].back.diffuse : STATE.LIGHTPROD[1].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].back.specular : STATE.LIGHTPROD[1].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].ambient : STATE.LIGHTPROD[2].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].diffuse : STATE.LIGHTPROD[2].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].specular : STATE.LIGHTPROD[2].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].front.ambient : STATE.LIGHTPROD[2].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].front.diffuse : STATE.LIGHTPROD[2].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].front.specular : STATE.LIGHTPROD[2].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].back.ambient : STATE.LIGHTPROD[2].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].back.diffuse : STATE.LIGHTPROD[2].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].back.specular : STATE.LIGHTPROD[2].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].ambient : STATE.LIGHTPROD[3].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].diffuse : STATE.LIGHTPROD[3].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].specular : STATE.LIGHTPROD[3].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].front.ambient : STATE.LIGHTPROD[3].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].front.diffuse : STATE.LIGHTPROD[3].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].front.specular : STATE.LIGHTPROD[3].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].back.ambient : STATE.LIGHTPROD[3].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].back.diffuse : STATE.LIGHTPROD[3].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].back.specular : STATE.LIGHTPROD[3].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].ambient : STATE.LIGHTPROD[4].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].diffuse : STATE.LIGHTPROD[4].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].specular : STATE.LIGHTPROD[4].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].front.ambient : STATE.LIGHTPROD[4].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].front.diffuse : STATE.LIGHTPROD[4].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].front.specular : STATE.LIGHTPROD[4].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].back.ambient : STATE.LIGHTPROD[4].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].back.diffuse : STATE.LIGHTPROD[4].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].back.specular : STATE.LIGHTPROD[4].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].ambient : STATE.LIGHTPROD[5].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].diffuse : STATE.LIGHTPROD[5].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].specular : STATE.LIGHTPROD[5].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].front.ambient : STATE.LIGHTPROD[5].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].front.diffuse : STATE.LIGHTPROD[5].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].front.specular : STATE.LIGHTPROD[5].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].back.ambient : STATE.LIGHTPROD[5].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].back.diffuse : STATE.LIGHTPROD[5].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].back.specular : STATE.LIGHTPROD[5].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].ambient : STATE.LIGHTPROD[6].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].diffuse : STATE.LIGHTPROD[6].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].specular : STATE.LIGHTPROD[6].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].front.ambient : STATE.LIGHTPROD[6].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].front.diffuse : STATE.LIGHTPROD[6].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].front.specular : STATE.LIGHTPROD[6].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].back.ambient : STATE.LIGHTPROD[6].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].back.diffuse : STATE.LIGHTPROD[6].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].back.specular : STATE.LIGHTPROD[6].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].ambient : STATE.LIGHTPROD[7].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].diffuse : STATE.LIGHTPROD[7].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].specular : STATE.LIGHTPROD[7].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].front.ambient : STATE.LIGHTPROD[7].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].front.diffuse : STATE.LIGHTPROD[7].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].front.specular : STATE.LIGHTPROD[7].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].back.ambient : STATE.LIGHTPROD[7].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].back.diffuse : STATE.LIGHTPROD[7].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].back.specular : STATE.LIGHTPROD[7].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.texgen[0].eye.s : STATE.TEXGEN[0].EYE.S : : -1 : 0
-#var float4 glstate.texgen[0].eye.t : STATE.TEXGEN[0].EYE.T : : -1 : 0
-#var float4 glstate.texgen[0].eye.r : STATE.TEXGEN[0].EYE.R : : -1 : 0
-#var float4 glstate.texgen[0].eye.q : STATE.TEXGEN[0].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[0].object.s : STATE.TEXGEN[0].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[0].object.t : STATE.TEXGEN[0].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[0].object.r : STATE.TEXGEN[0].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[0].object.q : STATE.TEXGEN[0].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[1].eye.s : STATE.TEXGEN[1].EYE.S : : -1 : 0
-#var float4 glstate.texgen[1].eye.t : STATE.TEXGEN[1].EYE.T : : -1 : 0
-#var float4 glstate.texgen[1].eye.r : STATE.TEXGEN[1].EYE.R : : -1 : 0
-#var float4 glstate.texgen[1].eye.q : STATE.TEXGEN[1].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[1].object.s : STATE.TEXGEN[1].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[1].object.t : STATE.TEXGEN[1].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[1].object.r : STATE.TEXGEN[1].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[1].object.q : STATE.TEXGEN[1].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[2].eye.s : STATE.TEXGEN[2].EYE.S : : -1 : 0
-#var float4 glstate.texgen[2].eye.t : STATE.TEXGEN[2].EYE.T : : -1 : 0
-#var float4 glstate.texgen[2].eye.r : STATE.TEXGEN[2].EYE.R : : -1 : 0
-#var float4 glstate.texgen[2].eye.q : STATE.TEXGEN[2].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[2].object.s : STATE.TEXGEN[2].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[2].object.t : STATE.TEXGEN[2].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[2].object.r : STATE.TEXGEN[2].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[2].object.q : STATE.TEXGEN[2].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[3].eye.s : STATE.TEXGEN[3].EYE.S : : -1 : 0
-#var float4 glstate.texgen[3].eye.t : STATE.TEXGEN[3].EYE.T : : -1 : 0
-#var float4 glstate.texgen[3].eye.r : STATE.TEXGEN[3].EYE.R : : -1 : 0
-#var float4 glstate.texgen[3].eye.q : STATE.TEXGEN[3].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[3].object.s : STATE.TEXGEN[3].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[3].object.t : STATE.TEXGEN[3].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[3].object.r : STATE.TEXGEN[3].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[3].object.q : STATE.TEXGEN[3].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[4].eye.s : STATE.TEXGEN[4].EYE.S : : -1 : 0
-#var float4 glstate.texgen[4].eye.t : STATE.TEXGEN[4].EYE.T : : -1 : 0
-#var float4 glstate.texgen[4].eye.r : STATE.TEXGEN[4].EYE.R : : -1 : 0
-#var float4 glstate.texgen[4].eye.q : STATE.TEXGEN[4].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[4].object.s : STATE.TEXGEN[4].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[4].object.t : STATE.TEXGEN[4].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[4].object.r : STATE.TEXGEN[4].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[4].object.q : STATE.TEXGEN[4].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[5].eye.s : STATE.TEXGEN[5].EYE.S : : -1 : 0
-#var float4 glstate.texgen[5].eye.t : STATE.TEXGEN[5].EYE.T : : -1 : 0
-#var float4 glstate.texgen[5].eye.r : STATE.TEXGEN[5].EYE.R : : -1 : 0
-#var float4 glstate.texgen[5].eye.q : STATE.TEXGEN[5].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[5].object.s : STATE.TEXGEN[5].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[5].object.t : STATE.TEXGEN[5].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[5].object.r : STATE.TEXGEN[5].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[5].object.q : STATE.TEXGEN[5].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[6].eye.s : STATE.TEXGEN[6].EYE.S : : -1 : 0
-#var float4 glstate.texgen[6].eye.t : STATE.TEXGEN[6].EYE.T : : -1 : 0
-#var float4 glstate.texgen[6].eye.r : STATE.TEXGEN[6].EYE.R : : -1 : 0
-#var float4 glstate.texgen[6].eye.q : STATE.TEXGEN[6].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[6].object.s : STATE.TEXGEN[6].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[6].object.t : STATE.TEXGEN[6].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[6].object.r : STATE.TEXGEN[6].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[6].object.q : STATE.TEXGEN[6].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[7].eye.s : STATE.TEXGEN[7].EYE.S : : -1 : 0
-#var float4 glstate.texgen[7].eye.t : STATE.TEXGEN[7].EYE.T : : -1 : 0
-#var float4 glstate.texgen[7].eye.r : STATE.TEXGEN[7].EYE.R : : -1 : 0
-#var float4 glstate.texgen[7].eye.q : STATE.TEXGEN[7].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[7].object.s : STATE.TEXGEN[7].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[7].object.t : STATE.TEXGEN[7].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[7].object.r : STATE.TEXGEN[7].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[7].object.q : STATE.TEXGEN[7].OBJECT.Q : : -1 : 0
-#var float4 glstate.fog.color : STATE.FOG.COLOR : : -1 : 0
-#var float4 glstate.fog.params : STATE.FOG.PARAMS : : -1 : 0
-#var float4 glstate.clip[0].plane : STATE.CLIP[0].PLANE : : -1 : 0
-#var float4 glstate.clip[1].plane : STATE.CLIP[1].PLANE : : -1 : 0
-#var float4 glstate.clip[2].plane : STATE.CLIP[2].PLANE : : -1 : 0
-#var float4 glstate.clip[3].plane : STATE.CLIP[3].PLANE : : -1 : 0
-#var float4 glstate.clip[4].plane : STATE.CLIP[4].PLANE : : -1 : 0
-#var float4 glstate.clip[5].plane : STATE.CLIP[5].PLANE : : -1 : 0
-#var float4 glstate.clip[6].plane : STATE.CLIP[6].PLANE : : -1 : 0
-#var float4 glstate.clip[7].plane : STATE.CLIP[7].PLANE : : -1 : 0
-#var float glstate.point.size : STATE.POINT.SIZE : : -1 : 0
-#var float glstate.point.attenuation : STATE.POINT.ATTENUATION : : -1 : 0
-#var float4x4 glstate.matrix.modelview[0] : STATE.MATRIX.MODELVIEW[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[1] : STATE.MATRIX.MODELVIEW[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[2] : STATE.MATRIX.MODELVIEW[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[3] : STATE.MATRIX.MODELVIEW[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[4] : STATE.MATRIX.MODELVIEW[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[5] : STATE.MATRIX.MODELVIEW[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[6] : STATE.MATRIX.MODELVIEW[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[7] : STATE.MATRIX.MODELVIEW[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.projection : STATE.MATRIX.PROJECTION : , 4 : -1 : 0
-#var float4x4 glstate.matrix.mvp : STATE.MATRIX.MVP : c[0], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[0] : STATE.MATRIX.TEXTURE[0] : c[4], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[1] : STATE.MATRIX.TEXTURE[1] : c[8], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[2] : STATE.MATRIX.TEXTURE[2] : c[12], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[3] : STATE.MATRIX.TEXTURE[3] : c[16], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[4] : STATE.MATRIX.TEXTURE[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[5] : STATE.MATRIX.TEXTURE[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[6] : STATE.MATRIX.TEXTURE[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[7] : STATE.MATRIX.TEXTURE[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[0] : STATE.MATRIX.PALETTE[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[1] : STATE.MATRIX.PALETTE[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[2] : STATE.MATRIX.PALETTE[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[3] : STATE.MATRIX.PALETTE[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[4] : STATE.MATRIX.PALETTE[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[5] : STATE.MATRIX.PALETTE[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[6] : STATE.MATRIX.PALETTE[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[7] : STATE.MATRIX.PALETTE[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[0] : STATE.MATRIX.PROGRAM[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[1] : STATE.MATRIX.PROGRAM[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[2] : STATE.MATRIX.PROGRAM[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[3] : STATE.MATRIX.PROGRAM[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[4] : STATE.MATRIX.PROGRAM[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[5] : STATE.MATRIX.PROGRAM[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[6] : STATE.MATRIX.PROGRAM[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[7] : STATE.MATRIX.PROGRAM[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[0] : STATE.MATRIX.MODELVIEW[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[1] : STATE.MATRIX.MODELVIEW[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[2] : STATE.MATRIX.MODELVIEW[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[3] : STATE.MATRIX.MODELVIEW[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[4] : STATE.MATRIX.MODELVIEW[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[5] : STATE.MATRIX.MODELVIEW[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[6] : STATE.MATRIX.MODELVIEW[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[7] : STATE.MATRIX.MODELVIEW[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.projection : STATE.MATRIX.PROJECTION.INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.mvp : STATE.MATRIX.MVP.INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[0] : STATE.MATRIX.TEXTURE[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[1] : STATE.MATRIX.TEXTURE[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[2] : STATE.MATRIX.TEXTURE[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[3] : STATE.MATRIX.TEXTURE[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[4] : STATE.MATRIX.TEXTURE[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[5] : STATE.MATRIX.TEXTURE[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[6] : STATE.MATRIX.TEXTURE[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[7] : STATE.MATRIX.TEXTURE[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[0] : STATE.MATRIX.PALETTE[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[1] : STATE.MATRIX.PALETTE[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[2] : STATE.MATRIX.PALETTE[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[3] : STATE.MATRIX.PALETTE[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[4] : STATE.MATRIX.PALETTE[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[5] : STATE.MATRIX.PALETTE[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[6] : STATE.MATRIX.PALETTE[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[7] : STATE.MATRIX.PALETTE[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[0] : STATE.MATRIX.PROGRAM[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[1] : STATE.MATRIX.PROGRAM[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[2] : STATE.MATRIX.PROGRAM[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[3] : STATE.MATRIX.PROGRAM[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[4] : STATE.MATRIX.PROGRAM[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[5] : STATE.MATRIX.PROGRAM[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[6] : STATE.MATRIX.PROGRAM[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[7] : STATE.MATRIX.PROGRAM[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[0] : STATE.MATRIX.MODELVIEW[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[1] : STATE.MATRIX.MODELVIEW[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[2] : STATE.MATRIX.MODELVIEW[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[3] : STATE.MATRIX.MODELVIEW[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[4] : STATE.MATRIX.MODELVIEW[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[5] : STATE.MATRIX.MODELVIEW[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[6] : STATE.MATRIX.MODELVIEW[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[7] : STATE.MATRIX.MODELVIEW[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.projection : STATE.MATRIX.PROJECTION.TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.mvp : STATE.MATRIX.MVP.TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[0] : STATE.MATRIX.TEXTURE[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[1] : STATE.MATRIX.TEXTURE[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[2] : STATE.MATRIX.TEXTURE[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[3] : STATE.MATRIX.TEXTURE[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[4] : STATE.MATRIX.TEXTURE[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[5] : STATE.MATRIX.TEXTURE[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[6] : STATE.MATRIX.TEXTURE[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[7] : STATE.MATRIX.TEXTURE[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[0] : STATE.MATRIX.PALETTE[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[1] : STATE.MATRIX.PALETTE[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[2] : STATE.MATRIX.PALETTE[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[3] : STATE.MATRIX.PALETTE[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[4] : STATE.MATRIX.PALETTE[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[5] : STATE.MATRIX.PALETTE[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[6] : STATE.MATRIX.PALETTE[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[7] : STATE.MATRIX.PALETTE[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[0] : STATE.MATRIX.PROGRAM[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[1] : STATE.MATRIX.PROGRAM[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[2] : STATE.MATRIX.PROGRAM[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[3] : STATE.MATRIX.PROGRAM[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[4] : STATE.MATRIX.PROGRAM[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[5] : STATE.MATRIX.PROGRAM[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[6] : STATE.MATRIX.PROGRAM[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[7] : STATE.MATRIX.PROGRAM[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[0] : STATE.MATRIX.MODELVIEW[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[1] : STATE.MATRIX.MODELVIEW[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[2] : STATE.MATRIX.MODELVIEW[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[3] : STATE.MATRIX.MODELVIEW[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[4] : STATE.MATRIX.MODELVIEW[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[5] : STATE.MATRIX.MODELVIEW[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[6] : STATE.MATRIX.MODELVIEW[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[7] : STATE.MATRIX.MODELVIEW[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.projection : STATE.MATRIX.PROJECTION.INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.mvp : STATE.MATRIX.MVP.INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[0] : STATE.MATRIX.TEXTURE[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[1] : STATE.MATRIX.TEXTURE[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[2] : STATE.MATRIX.TEXTURE[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[3] : STATE.MATRIX.TEXTURE[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[4] : STATE.MATRIX.TEXTURE[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[5] : STATE.MATRIX.TEXTURE[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[6] : STATE.MATRIX.TEXTURE[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[7] : STATE.MATRIX.TEXTURE[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[0] : STATE.MATRIX.PALETTE[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[1] : STATE.MATRIX.PALETTE[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[2] : STATE.MATRIX.PALETTE[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[3] : STATE.MATRIX.PALETTE[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[4] : STATE.MATRIX.PALETTE[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[5] : STATE.MATRIX.PALETTE[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[6] : STATE.MATRIX.PALETTE[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[7] : STATE.MATRIX.PALETTE[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[0] : STATE.MATRIX.PROGRAM[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[1] : STATE.MATRIX.PROGRAM[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[2] : STATE.MATRIX.PROGRAM[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[3] : STATE.MATRIX.PROGRAM[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[4] : STATE.MATRIX.PROGRAM[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[5] : STATE.MATRIX.PROGRAM[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[6] : STATE.MATRIX.PROGRAM[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[7] : STATE.MATRIX.PROGRAM[7].INVTRANS : , 4 : -1 : 0
-#var float4 IN.position : $vin.POSITION : POSITION : 0 : 1
-#var float4 IN.tex0 : $vin.ATTR8 : ATTR8 : 0 : 1
-#var float3 IN.tangent : $vin.ATTR9 : ATTR9 : 0 : 1
-#var float3 IN.binormal : $vin.ATTR10 : ATTR10 : 0 : 1
-#var float3 IN.normal : $vin.ATTR11 : ATTR11 : 0 : 1
-#var float4 main.hposition : $vout.HPOS : HPOS : -1 : 1
-#var float4 main.position : $vout.TEX0 : TEX0 : -1 : 1
-#var float4 main.tex_diffuse_bump : $vout.TEX1 : TEX1 : -1 : 1
-#var float4 main.tex_specular : $vout.TEX2 : TEX2 : -1 : 1
-#var float4 main.tex_atten_xy_z : $vout.TEX3 : TEX3 : -1 : 1
-#var float3 main.tangent : $vout.TEX4 : TEX4 : -1 : 1
-#var float3 main.binormal : $vout.TEX5 : TEX5 : -1 : 1
-#var float3 main.normal : $vout.TEX6 : TEX6 : -1 : 1
-PARAM c[20] = { state.matrix.mvp,
- state.matrix.texture[0],
- state.matrix.texture[1],
- state.matrix.texture[2],
- state.matrix.texture[3] };
-TEMP R0;
-DP4 result.position.w, vertex.position, c[3];
-DP4 result.position.z, vertex.position, c[2];
-DP4 result.position.y, vertex.position, c[1];
-DP4 result.position.x, vertex.position, c[0];
-DP4 R0.y, vertex.attrib[8], c[9];
-DP4 R0.x, vertex.attrib[8], c[8];
-MOV result.texcoord[0], vertex.position;
-MOV result.texcoord[1].zw, R0.xyxy;
-DP4 result.texcoord[1].y, vertex.attrib[8], c[5];
-DP4 result.texcoord[1].x, vertex.attrib[8], c[4];
-DP4 result.texcoord[2].w, vertex.attrib[8], c[15];
-DP4 result.texcoord[2].z, vertex.attrib[8], c[14];
-DP4 result.texcoord[2].y, vertex.attrib[8], c[13];
-DP4 result.texcoord[2].x, vertex.attrib[8], c[12];
-DP4 result.texcoord[3].w, vertex.position, c[19];
-DP4 result.texcoord[3].z, vertex.position, c[18];
-DP4 result.texcoord[3].y, vertex.position, c[17];
-DP4 result.texcoord[3].x, vertex.position, c[16];
-MOV result.texcoord[4].xyz, vertex.attrib[9];
-MOV result.texcoord[5].xyz, vertex.attrib[10];
-MOV result.texcoord[6].xyz, vertex.attrib[11];
-END
-# 21 instructions, 1 R-regs
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "CONTRIBUTORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-attribute vec4 attr_TexCoord0;
-attribute vec3 attr_Tangent;
-attribute vec3 attr_Binormal;
-
-varying vec3 var_vertex;
-varying vec4 var_tex_diffuse_bump;
-varying vec2 var_tex_specular;
-varying vec4 var_tex_atten_xy_z;
-varying mat3 var_mat_os2ts;
-
-void main()
-{
- // transform vertex position into homogenous clip-space
- gl_Position = ftransform();
-
- // assign position in object space
- var_vertex = gl_Vertex.xyz;
-
- // transform texcoords into diffusemap texture space
- var_tex_diffuse_bump.st = (gl_TextureMatrix[0] * attr_TexCoord0).st;
-
- // transform texcoords into bumpmap texture space
- var_tex_diffuse_bump.pq = (gl_TextureMatrix[1] * attr_TexCoord0).st;
-
- // transform texcoords into specularmap texture space
- var_tex_specular = (gl_TextureMatrix[2] * attr_TexCoord0).st;
-
- // calc light xy,z attenuation in light space
- var_tex_atten_xy_z = gl_TextureMatrix[3] * gl_Vertex;
-
-
- // construct object-space-to-tangent-space 3x3 matrix
- var_mat_os2ts = mat3( attr_Tangent.x, attr_Binormal.x, gl_Normal.x,
- attr_Tangent.y, attr_Binormal.y, gl_Normal.y,
- attr_Tangent.z, attr_Binormal.z, gl_Normal.z );
-}
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "AUTHORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-// fresnel approximation
-float fast_fresnel(float3 I, float3 N, float3 fresnel_values)
-{
- float power = fresnel_values.x;
- float scale = fresnel_values.y;
- float bias = fresnel_values.z;
-
- return bias + pow(1.0 - dot(I, N), power) * scale;
-}
-
-float3 CG_Expand(float3 v)
-{
- return (v - 0.5) * 2; // expand a range-compressed vector
-}
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2003 Robert Beckebans <trebor_7@users.sourceforge.net>
-Copyright (C) 2003, 2004 contributors of the XreaL project
-Please see the file "AUTHORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-
-struct cg_vertex2fragment
-{
- float4 position : POSITION;
- float4 tex0 : TEXCOORD0;
-};
-
-struct cg_fragment2final
-{
- float4 color : COLOR;
-};
-
-
-cg_fragment2final main(in cg_vertex2fragment IN,
- uniform sampler2D colormap)
-{
- cg_fragment2final OUT;
-
- OUT.color.w = tex2D(colormap, IN.tex0.xy).a;
-
- OUT.color.xyz = 0;
-
- return OUT;
-}
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2003 Robert Beckebans <trebor_7@users.sourceforge.net>
-Copyright (C) 2003, 2004 contributors of the XreaL project
-Please see the file "AUTHORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-
-struct cg_app2vertex
-{
- float4 position : ATTR0;
- float4 texcoord0 : ATTR8;
-};
-
-struct cg_vertex2fragment
-{
- float4 position : POSITION;
- float4 tex0 : TEXCOORD0;
-};
-
-
-cg_vertex2fragment main(cg_app2vertex IN)
-{
- cg_vertex2fragment OUT;
-
- // transform vertex position into homogenous clip-space
- OUT.position = mul(glstate.matrix.mvp, IN.position);
-
- // transform texcoords into 1st texture space
- OUT.tex0 = mul(glstate.matrix.texture[0], IN.texcoord0);
-
- return OUT;
-}
+++ /dev/null
-!!ARBfp1.0
-# cgc version 1.3.0001, build date Aug 4 2004 10:01:10
-# command line args: -profile arbfp1
-# source file: ..\..\setup\data\tools\gl\zfill_arbfp1.cg
-#vendor NVIDIA Corporation
-#version 1.0.02
-#profile arbfp1
-#program main
-#semantic main.colormap
-#var float4 IN.position : : : 0 : 0
-#var float4 IN.tex0 : $vin.TEX0 : TEX0 : 0 : 1
-#var sampler2D colormap : : texunit 0 : 1 : 1
-#var float4 main.color : $vout.COL : COL : -1 : 1
-#const c[0] = 0
-PARAM c[1] = { { 0 } };
-MOV result.color.xyz, c[0].x;
-TEX result.color.w, fragment.texcoord[0], texture[0], 2D;
-END
-# 2 instructions, 0 R-regs
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "CONTRIBUTORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-uniform sampler2D u_colormap;
-
-void main()
-{
- gl_FragColor.a = texture2D(u_colormap, gl_TexCoord[0].st).a;
- gl_FragColor.rgb = vec3(0.0, 0.0, 0.0);
-}
+++ /dev/null
-!!ARBvp1.0
-# cgc version 1.3.0001, build date Aug 4 2004 10:01:10
-# command line args: -profile arbvp1
-# source file: ..\..\setup\data\tools\gl\zfill_arbvp1.cg
-#vendor NVIDIA Corporation
-#version 1.0.02
-#profile arbvp1
-#program main
-#semantic glstate : STATE
-#var float4 glstate.material.ambient : STATE.MATERIAL.AMBIENT : : -1 : 0
-#var float4 glstate.material.diffuse : STATE.MATERIAL.DIFFUSE : : -1 : 0
-#var float4 glstate.material.specular : STATE.MATERIAL.SPECULAR : : -1 : 0
-#var float4 glstate.material.emission : STATE.MATERIAL.EMISSION : : -1 : 0
-#var float4 glstate.material.shininess : STATE.MATERIAL.SHININESS : : -1 : 0
-#var float4 glstate.material.front.ambient : STATE.MATERIAL.FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.material.front.diffuse : STATE.MATERIAL.FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.material.front.specular : STATE.MATERIAL.FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.material.front.emission : STATE.MATERIAL.FRONT.EMISSION : : -1 : 0
-#var float4 glstate.material.front.shininess : STATE.MATERIAL.FRONT.SHININESS : : -1 : 0
-#var float4 glstate.material.back.ambient : STATE.MATERIAL.BACK.AMBIENT : : -1 : 0
-#var float4 glstate.material.back.diffuse : STATE.MATERIAL.BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.material.back.specular : STATE.MATERIAL.BACK.SPECULAR : : -1 : 0
-#var float4 glstate.material.back.emission : STATE.MATERIAL.BACK.EMISSION : : -1 : 0
-#var float4 glstate.material.back.shininess : STATE.MATERIAL.BACK.SHININESS : : -1 : 0
-#var float4 glstate.light[0].ambient : STATE.LIGHT[0].AMBIENT : : -1 : 0
-#var float4 glstate.light[0].diffuse : STATE.LIGHT[0].DIFFUSE : : -1 : 0
-#var float4 glstate.light[0].specular : STATE.LIGHT[0].SPECULAR : : -1 : 0
-#var float4 glstate.light[0].position : STATE.LIGHT[0].POSITION : : -1 : 0
-#var float4 glstate.light[0].attenuation : STATE.LIGHT[0].ATTENUATION : : -1 : 0
-#var float4 glstate.light[0].spot.direction : STATE.LIGHT[0].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[0].half : STATE.LIGHT[0].HALF : : -1 : 0
-#var float4 glstate.light[1].ambient : STATE.LIGHT[1].AMBIENT : : -1 : 0
-#var float4 glstate.light[1].diffuse : STATE.LIGHT[1].DIFFUSE : : -1 : 0
-#var float4 glstate.light[1].specular : STATE.LIGHT[1].SPECULAR : : -1 : 0
-#var float4 glstate.light[1].position : STATE.LIGHT[1].POSITION : : -1 : 0
-#var float4 glstate.light[1].attenuation : STATE.LIGHT[1].ATTENUATION : : -1 : 0
-#var float4 glstate.light[1].spot.direction : STATE.LIGHT[1].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[1].half : STATE.LIGHT[1].HALF : : -1 : 0
-#var float4 glstate.light[2].ambient : STATE.LIGHT[2].AMBIENT : : -1 : 0
-#var float4 glstate.light[2].diffuse : STATE.LIGHT[2].DIFFUSE : : -1 : 0
-#var float4 glstate.light[2].specular : STATE.LIGHT[2].SPECULAR : : -1 : 0
-#var float4 glstate.light[2].position : STATE.LIGHT[2].POSITION : : -1 : 0
-#var float4 glstate.light[2].attenuation : STATE.LIGHT[2].ATTENUATION : : -1 : 0
-#var float4 glstate.light[2].spot.direction : STATE.LIGHT[2].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[2].half : STATE.LIGHT[2].HALF : : -1 : 0
-#var float4 glstate.light[3].ambient : STATE.LIGHT[3].AMBIENT : : -1 : 0
-#var float4 glstate.light[3].diffuse : STATE.LIGHT[3].DIFFUSE : : -1 : 0
-#var float4 glstate.light[3].specular : STATE.LIGHT[3].SPECULAR : : -1 : 0
-#var float4 glstate.light[3].position : STATE.LIGHT[3].POSITION : : -1 : 0
-#var float4 glstate.light[3].attenuation : STATE.LIGHT[3].ATTENUATION : : -1 : 0
-#var float4 glstate.light[3].spot.direction : STATE.LIGHT[3].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[3].half : STATE.LIGHT[3].HALF : : -1 : 0
-#var float4 glstate.light[4].ambient : STATE.LIGHT[4].AMBIENT : : -1 : 0
-#var float4 glstate.light[4].diffuse : STATE.LIGHT[4].DIFFUSE : : -1 : 0
-#var float4 glstate.light[4].specular : STATE.LIGHT[4].SPECULAR : : -1 : 0
-#var float4 glstate.light[4].position : STATE.LIGHT[4].POSITION : : -1 : 0
-#var float4 glstate.light[4].attenuation : STATE.LIGHT[4].ATTENUATION : : -1 : 0
-#var float4 glstate.light[4].spot.direction : STATE.LIGHT[4].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[4].half : STATE.LIGHT[4].HALF : : -1 : 0
-#var float4 glstate.light[5].ambient : STATE.LIGHT[5].AMBIENT : : -1 : 0
-#var float4 glstate.light[5].diffuse : STATE.LIGHT[5].DIFFUSE : : -1 : 0
-#var float4 glstate.light[5].specular : STATE.LIGHT[5].SPECULAR : : -1 : 0
-#var float4 glstate.light[5].position : STATE.LIGHT[5].POSITION : : -1 : 0
-#var float4 glstate.light[5].attenuation : STATE.LIGHT[5].ATTENUATION : : -1 : 0
-#var float4 glstate.light[5].spot.direction : STATE.LIGHT[5].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[5].half : STATE.LIGHT[5].HALF : : -1 : 0
-#var float4 glstate.light[6].ambient : STATE.LIGHT[6].AMBIENT : : -1 : 0
-#var float4 glstate.light[6].diffuse : STATE.LIGHT[6].DIFFUSE : : -1 : 0
-#var float4 glstate.light[6].specular : STATE.LIGHT[6].SPECULAR : : -1 : 0
-#var float4 glstate.light[6].position : STATE.LIGHT[6].POSITION : : -1 : 0
-#var float4 glstate.light[6].attenuation : STATE.LIGHT[6].ATTENUATION : : -1 : 0
-#var float4 glstate.light[6].spot.direction : STATE.LIGHT[6].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[6].half : STATE.LIGHT[6].HALF : : -1 : 0
-#var float4 glstate.light[7].ambient : STATE.LIGHT[7].AMBIENT : : -1 : 0
-#var float4 glstate.light[7].diffuse : STATE.LIGHT[7].DIFFUSE : : -1 : 0
-#var float4 glstate.light[7].specular : STATE.LIGHT[7].SPECULAR : : -1 : 0
-#var float4 glstate.light[7].position : STATE.LIGHT[7].POSITION : : -1 : 0
-#var float4 glstate.light[7].attenuation : STATE.LIGHT[7].ATTENUATION : : -1 : 0
-#var float4 glstate.light[7].spot.direction : STATE.LIGHT[7].SPOT.DIRECTION : : -1 : 0
-#var float4 glstate.light[7].half : STATE.LIGHT[7].HALF : : -1 : 0
-#var float4 glstate.lightmodel.ambient : STATE.LIGHTMODEL.AMBIENT : : -1 : 0
-#var float4 glstate.lightmodel.scenecolor : STATE.LIGHTMODEL.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightmodel.front.scenecolor : STATE.LIGHTMODEL.FRONT.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightmodel.back.scenecolor : STATE.LIGHTMODEL.BACK.SCENECOLOR : : -1 : 0
-#var float4 glstate.lightprod[0].ambient : STATE.LIGHTPROD[0].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].diffuse : STATE.LIGHTPROD[0].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].specular : STATE.LIGHTPROD[0].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[0].front.ambient : STATE.LIGHTPROD[0].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].front.diffuse : STATE.LIGHTPROD[0].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].front.specular : STATE.LIGHTPROD[0].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[0].back.ambient : STATE.LIGHTPROD[0].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[0].back.diffuse : STATE.LIGHTPROD[0].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[0].back.specular : STATE.LIGHTPROD[0].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].ambient : STATE.LIGHTPROD[1].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].diffuse : STATE.LIGHTPROD[1].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].specular : STATE.LIGHTPROD[1].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].front.ambient : STATE.LIGHTPROD[1].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].front.diffuse : STATE.LIGHTPROD[1].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].front.specular : STATE.LIGHTPROD[1].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[1].back.ambient : STATE.LIGHTPROD[1].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[1].back.diffuse : STATE.LIGHTPROD[1].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[1].back.specular : STATE.LIGHTPROD[1].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].ambient : STATE.LIGHTPROD[2].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].diffuse : STATE.LIGHTPROD[2].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].specular : STATE.LIGHTPROD[2].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].front.ambient : STATE.LIGHTPROD[2].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].front.diffuse : STATE.LIGHTPROD[2].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].front.specular : STATE.LIGHTPROD[2].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[2].back.ambient : STATE.LIGHTPROD[2].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[2].back.diffuse : STATE.LIGHTPROD[2].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[2].back.specular : STATE.LIGHTPROD[2].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].ambient : STATE.LIGHTPROD[3].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].diffuse : STATE.LIGHTPROD[3].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].specular : STATE.LIGHTPROD[3].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].front.ambient : STATE.LIGHTPROD[3].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].front.diffuse : STATE.LIGHTPROD[3].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].front.specular : STATE.LIGHTPROD[3].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[3].back.ambient : STATE.LIGHTPROD[3].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[3].back.diffuse : STATE.LIGHTPROD[3].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[3].back.specular : STATE.LIGHTPROD[3].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].ambient : STATE.LIGHTPROD[4].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].diffuse : STATE.LIGHTPROD[4].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].specular : STATE.LIGHTPROD[4].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].front.ambient : STATE.LIGHTPROD[4].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].front.diffuse : STATE.LIGHTPROD[4].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].front.specular : STATE.LIGHTPROD[4].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[4].back.ambient : STATE.LIGHTPROD[4].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[4].back.diffuse : STATE.LIGHTPROD[4].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[4].back.specular : STATE.LIGHTPROD[4].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].ambient : STATE.LIGHTPROD[5].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].diffuse : STATE.LIGHTPROD[5].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].specular : STATE.LIGHTPROD[5].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].front.ambient : STATE.LIGHTPROD[5].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].front.diffuse : STATE.LIGHTPROD[5].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].front.specular : STATE.LIGHTPROD[5].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[5].back.ambient : STATE.LIGHTPROD[5].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[5].back.diffuse : STATE.LIGHTPROD[5].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[5].back.specular : STATE.LIGHTPROD[5].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].ambient : STATE.LIGHTPROD[6].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].diffuse : STATE.LIGHTPROD[6].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].specular : STATE.LIGHTPROD[6].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].front.ambient : STATE.LIGHTPROD[6].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].front.diffuse : STATE.LIGHTPROD[6].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].front.specular : STATE.LIGHTPROD[6].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[6].back.ambient : STATE.LIGHTPROD[6].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[6].back.diffuse : STATE.LIGHTPROD[6].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[6].back.specular : STATE.LIGHTPROD[6].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].ambient : STATE.LIGHTPROD[7].AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].diffuse : STATE.LIGHTPROD[7].DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].specular : STATE.LIGHTPROD[7].SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].front.ambient : STATE.LIGHTPROD[7].FRONT.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].front.diffuse : STATE.LIGHTPROD[7].FRONT.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].front.specular : STATE.LIGHTPROD[7].FRONT.SPECULAR : : -1 : 0
-#var float4 glstate.lightprod[7].back.ambient : STATE.LIGHTPROD[7].BACK.AMBIENT : : -1 : 0
-#var float4 glstate.lightprod[7].back.diffuse : STATE.LIGHTPROD[7].BACK.DIFFUSE : : -1 : 0
-#var float4 glstate.lightprod[7].back.specular : STATE.LIGHTPROD[7].BACK.SPECULAR : : -1 : 0
-#var float4 glstate.texgen[0].eye.s : STATE.TEXGEN[0].EYE.S : : -1 : 0
-#var float4 glstate.texgen[0].eye.t : STATE.TEXGEN[0].EYE.T : : -1 : 0
-#var float4 glstate.texgen[0].eye.r : STATE.TEXGEN[0].EYE.R : : -1 : 0
-#var float4 glstate.texgen[0].eye.q : STATE.TEXGEN[0].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[0].object.s : STATE.TEXGEN[0].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[0].object.t : STATE.TEXGEN[0].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[0].object.r : STATE.TEXGEN[0].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[0].object.q : STATE.TEXGEN[0].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[1].eye.s : STATE.TEXGEN[1].EYE.S : : -1 : 0
-#var float4 glstate.texgen[1].eye.t : STATE.TEXGEN[1].EYE.T : : -1 : 0
-#var float4 glstate.texgen[1].eye.r : STATE.TEXGEN[1].EYE.R : : -1 : 0
-#var float4 glstate.texgen[1].eye.q : STATE.TEXGEN[1].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[1].object.s : STATE.TEXGEN[1].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[1].object.t : STATE.TEXGEN[1].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[1].object.r : STATE.TEXGEN[1].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[1].object.q : STATE.TEXGEN[1].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[2].eye.s : STATE.TEXGEN[2].EYE.S : : -1 : 0
-#var float4 glstate.texgen[2].eye.t : STATE.TEXGEN[2].EYE.T : : -1 : 0
-#var float4 glstate.texgen[2].eye.r : STATE.TEXGEN[2].EYE.R : : -1 : 0
-#var float4 glstate.texgen[2].eye.q : STATE.TEXGEN[2].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[2].object.s : STATE.TEXGEN[2].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[2].object.t : STATE.TEXGEN[2].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[2].object.r : STATE.TEXGEN[2].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[2].object.q : STATE.TEXGEN[2].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[3].eye.s : STATE.TEXGEN[3].EYE.S : : -1 : 0
-#var float4 glstate.texgen[3].eye.t : STATE.TEXGEN[3].EYE.T : : -1 : 0
-#var float4 glstate.texgen[3].eye.r : STATE.TEXGEN[3].EYE.R : : -1 : 0
-#var float4 glstate.texgen[3].eye.q : STATE.TEXGEN[3].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[3].object.s : STATE.TEXGEN[3].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[3].object.t : STATE.TEXGEN[3].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[3].object.r : STATE.TEXGEN[3].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[3].object.q : STATE.TEXGEN[3].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[4].eye.s : STATE.TEXGEN[4].EYE.S : : -1 : 0
-#var float4 glstate.texgen[4].eye.t : STATE.TEXGEN[4].EYE.T : : -1 : 0
-#var float4 glstate.texgen[4].eye.r : STATE.TEXGEN[4].EYE.R : : -1 : 0
-#var float4 glstate.texgen[4].eye.q : STATE.TEXGEN[4].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[4].object.s : STATE.TEXGEN[4].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[4].object.t : STATE.TEXGEN[4].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[4].object.r : STATE.TEXGEN[4].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[4].object.q : STATE.TEXGEN[4].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[5].eye.s : STATE.TEXGEN[5].EYE.S : : -1 : 0
-#var float4 glstate.texgen[5].eye.t : STATE.TEXGEN[5].EYE.T : : -1 : 0
-#var float4 glstate.texgen[5].eye.r : STATE.TEXGEN[5].EYE.R : : -1 : 0
-#var float4 glstate.texgen[5].eye.q : STATE.TEXGEN[5].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[5].object.s : STATE.TEXGEN[5].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[5].object.t : STATE.TEXGEN[5].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[5].object.r : STATE.TEXGEN[5].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[5].object.q : STATE.TEXGEN[5].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[6].eye.s : STATE.TEXGEN[6].EYE.S : : -1 : 0
-#var float4 glstate.texgen[6].eye.t : STATE.TEXGEN[6].EYE.T : : -1 : 0
-#var float4 glstate.texgen[6].eye.r : STATE.TEXGEN[6].EYE.R : : -1 : 0
-#var float4 glstate.texgen[6].eye.q : STATE.TEXGEN[6].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[6].object.s : STATE.TEXGEN[6].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[6].object.t : STATE.TEXGEN[6].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[6].object.r : STATE.TEXGEN[6].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[6].object.q : STATE.TEXGEN[6].OBJECT.Q : : -1 : 0
-#var float4 glstate.texgen[7].eye.s : STATE.TEXGEN[7].EYE.S : : -1 : 0
-#var float4 glstate.texgen[7].eye.t : STATE.TEXGEN[7].EYE.T : : -1 : 0
-#var float4 glstate.texgen[7].eye.r : STATE.TEXGEN[7].EYE.R : : -1 : 0
-#var float4 glstate.texgen[7].eye.q : STATE.TEXGEN[7].EYE.Q : : -1 : 0
-#var float4 glstate.texgen[7].object.s : STATE.TEXGEN[7].OBJECT.S : : -1 : 0
-#var float4 glstate.texgen[7].object.t : STATE.TEXGEN[7].OBJECT.T : : -1 : 0
-#var float4 glstate.texgen[7].object.r : STATE.TEXGEN[7].OBJECT.R : : -1 : 0
-#var float4 glstate.texgen[7].object.q : STATE.TEXGEN[7].OBJECT.Q : : -1 : 0
-#var float4 glstate.fog.color : STATE.FOG.COLOR : : -1 : 0
-#var float4 glstate.fog.params : STATE.FOG.PARAMS : : -1 : 0
-#var float4 glstate.clip[0].plane : STATE.CLIP[0].PLANE : : -1 : 0
-#var float4 glstate.clip[1].plane : STATE.CLIP[1].PLANE : : -1 : 0
-#var float4 glstate.clip[2].plane : STATE.CLIP[2].PLANE : : -1 : 0
-#var float4 glstate.clip[3].plane : STATE.CLIP[3].PLANE : : -1 : 0
-#var float4 glstate.clip[4].plane : STATE.CLIP[4].PLANE : : -1 : 0
-#var float4 glstate.clip[5].plane : STATE.CLIP[5].PLANE : : -1 : 0
-#var float4 glstate.clip[6].plane : STATE.CLIP[6].PLANE : : -1 : 0
-#var float4 glstate.clip[7].plane : STATE.CLIP[7].PLANE : : -1 : 0
-#var float glstate.point.size : STATE.POINT.SIZE : : -1 : 0
-#var float glstate.point.attenuation : STATE.POINT.ATTENUATION : : -1 : 0
-#var float4x4 glstate.matrix.modelview[0] : STATE.MATRIX.MODELVIEW[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[1] : STATE.MATRIX.MODELVIEW[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[2] : STATE.MATRIX.MODELVIEW[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[3] : STATE.MATRIX.MODELVIEW[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[4] : STATE.MATRIX.MODELVIEW[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[5] : STATE.MATRIX.MODELVIEW[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[6] : STATE.MATRIX.MODELVIEW[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.modelview[7] : STATE.MATRIX.MODELVIEW[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.projection : STATE.MATRIX.PROJECTION : , 4 : -1 : 0
-#var float4x4 glstate.matrix.mvp : STATE.MATRIX.MVP : c[0], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[0] : STATE.MATRIX.TEXTURE[0] : c[4], 4 : -1 : 1
-#var float4x4 glstate.matrix.texture[1] : STATE.MATRIX.TEXTURE[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[2] : STATE.MATRIX.TEXTURE[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[3] : STATE.MATRIX.TEXTURE[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[4] : STATE.MATRIX.TEXTURE[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[5] : STATE.MATRIX.TEXTURE[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[6] : STATE.MATRIX.TEXTURE[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.texture[7] : STATE.MATRIX.TEXTURE[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[0] : STATE.MATRIX.PALETTE[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[1] : STATE.MATRIX.PALETTE[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[2] : STATE.MATRIX.PALETTE[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[3] : STATE.MATRIX.PALETTE[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[4] : STATE.MATRIX.PALETTE[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[5] : STATE.MATRIX.PALETTE[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[6] : STATE.MATRIX.PALETTE[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.palette[7] : STATE.MATRIX.PALETTE[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[0] : STATE.MATRIX.PROGRAM[0] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[1] : STATE.MATRIX.PROGRAM[1] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[2] : STATE.MATRIX.PROGRAM[2] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[3] : STATE.MATRIX.PROGRAM[3] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[4] : STATE.MATRIX.PROGRAM[4] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[5] : STATE.MATRIX.PROGRAM[5] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[6] : STATE.MATRIX.PROGRAM[6] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.program[7] : STATE.MATRIX.PROGRAM[7] : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[0] : STATE.MATRIX.MODELVIEW[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[1] : STATE.MATRIX.MODELVIEW[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[2] : STATE.MATRIX.MODELVIEW[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[3] : STATE.MATRIX.MODELVIEW[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[4] : STATE.MATRIX.MODELVIEW[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[5] : STATE.MATRIX.MODELVIEW[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[6] : STATE.MATRIX.MODELVIEW[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.modelview[7] : STATE.MATRIX.MODELVIEW[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.projection : STATE.MATRIX.PROJECTION.INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.mvp : STATE.MATRIX.MVP.INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[0] : STATE.MATRIX.TEXTURE[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[1] : STATE.MATRIX.TEXTURE[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[2] : STATE.MATRIX.TEXTURE[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[3] : STATE.MATRIX.TEXTURE[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[4] : STATE.MATRIX.TEXTURE[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[5] : STATE.MATRIX.TEXTURE[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[6] : STATE.MATRIX.TEXTURE[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.texture[7] : STATE.MATRIX.TEXTURE[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[0] : STATE.MATRIX.PALETTE[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[1] : STATE.MATRIX.PALETTE[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[2] : STATE.MATRIX.PALETTE[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[3] : STATE.MATRIX.PALETTE[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[4] : STATE.MATRIX.PALETTE[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[5] : STATE.MATRIX.PALETTE[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[6] : STATE.MATRIX.PALETTE[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.palette[7] : STATE.MATRIX.PALETTE[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[0] : STATE.MATRIX.PROGRAM[0].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[1] : STATE.MATRIX.PROGRAM[1].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[2] : STATE.MATRIX.PROGRAM[2].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[3] : STATE.MATRIX.PROGRAM[3].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[4] : STATE.MATRIX.PROGRAM[4].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[5] : STATE.MATRIX.PROGRAM[5].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[6] : STATE.MATRIX.PROGRAM[6].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.inverse.program[7] : STATE.MATRIX.PROGRAM[7].INVERSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[0] : STATE.MATRIX.MODELVIEW[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[1] : STATE.MATRIX.MODELVIEW[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[2] : STATE.MATRIX.MODELVIEW[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[3] : STATE.MATRIX.MODELVIEW[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[4] : STATE.MATRIX.MODELVIEW[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[5] : STATE.MATRIX.MODELVIEW[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[6] : STATE.MATRIX.MODELVIEW[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.modelview[7] : STATE.MATRIX.MODELVIEW[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.projection : STATE.MATRIX.PROJECTION.TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.mvp : STATE.MATRIX.MVP.TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[0] : STATE.MATRIX.TEXTURE[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[1] : STATE.MATRIX.TEXTURE[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[2] : STATE.MATRIX.TEXTURE[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[3] : STATE.MATRIX.TEXTURE[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[4] : STATE.MATRIX.TEXTURE[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[5] : STATE.MATRIX.TEXTURE[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[6] : STATE.MATRIX.TEXTURE[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.texture[7] : STATE.MATRIX.TEXTURE[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[0] : STATE.MATRIX.PALETTE[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[1] : STATE.MATRIX.PALETTE[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[2] : STATE.MATRIX.PALETTE[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[3] : STATE.MATRIX.PALETTE[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[4] : STATE.MATRIX.PALETTE[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[5] : STATE.MATRIX.PALETTE[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[6] : STATE.MATRIX.PALETTE[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.palette[7] : STATE.MATRIX.PALETTE[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[0] : STATE.MATRIX.PROGRAM[0].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[1] : STATE.MATRIX.PROGRAM[1].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[2] : STATE.MATRIX.PROGRAM[2].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[3] : STATE.MATRIX.PROGRAM[3].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[4] : STATE.MATRIX.PROGRAM[4].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[5] : STATE.MATRIX.PROGRAM[5].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[6] : STATE.MATRIX.PROGRAM[6].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.transpose.program[7] : STATE.MATRIX.PROGRAM[7].TRANSPOSE : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[0] : STATE.MATRIX.MODELVIEW[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[1] : STATE.MATRIX.MODELVIEW[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[2] : STATE.MATRIX.MODELVIEW[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[3] : STATE.MATRIX.MODELVIEW[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[4] : STATE.MATRIX.MODELVIEW[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[5] : STATE.MATRIX.MODELVIEW[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[6] : STATE.MATRIX.MODELVIEW[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.modelview[7] : STATE.MATRIX.MODELVIEW[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.projection : STATE.MATRIX.PROJECTION.INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.mvp : STATE.MATRIX.MVP.INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[0] : STATE.MATRIX.TEXTURE[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[1] : STATE.MATRIX.TEXTURE[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[2] : STATE.MATRIX.TEXTURE[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[3] : STATE.MATRIX.TEXTURE[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[4] : STATE.MATRIX.TEXTURE[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[5] : STATE.MATRIX.TEXTURE[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[6] : STATE.MATRIX.TEXTURE[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.texture[7] : STATE.MATRIX.TEXTURE[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[0] : STATE.MATRIX.PALETTE[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[1] : STATE.MATRIX.PALETTE[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[2] : STATE.MATRIX.PALETTE[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[3] : STATE.MATRIX.PALETTE[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[4] : STATE.MATRIX.PALETTE[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[5] : STATE.MATRIX.PALETTE[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[6] : STATE.MATRIX.PALETTE[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.palette[7] : STATE.MATRIX.PALETTE[7].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[0] : STATE.MATRIX.PROGRAM[0].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[1] : STATE.MATRIX.PROGRAM[1].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[2] : STATE.MATRIX.PROGRAM[2].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[3] : STATE.MATRIX.PROGRAM[3].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[4] : STATE.MATRIX.PROGRAM[4].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[5] : STATE.MATRIX.PROGRAM[5].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[6] : STATE.MATRIX.PROGRAM[6].INVTRANS : , 4 : -1 : 0
-#var float4x4 glstate.matrix.invtrans.program[7] : STATE.MATRIX.PROGRAM[7].INVTRANS : , 4 : -1 : 0
-#var float4 IN.position : $vin.ATTR0 : ATTR0 : 0 : 1
-#var float4 IN.texcoord0 : $vin.ATTR8 : ATTR8 : 0 : 1
-#var float4 main.position : $vout.HPOS : HPOS : -1 : 1
-#var float4 main.tex0 : $vout.TEX0 : TEX0 : -1 : 1
-PARAM c[8] = { state.matrix.mvp,
- state.matrix.texture[0] };
-DP4 result.position.w, vertex.attrib[0], c[3];
-DP4 result.position.z, vertex.attrib[0], c[2];
-DP4 result.position.y, vertex.attrib[0], c[1];
-DP4 result.position.x, vertex.attrib[0], c[0];
-DP4 result.texcoord[0].w, vertex.attrib[8], c[7];
-DP4 result.texcoord[0].z, vertex.attrib[8], c[6];
-DP4 result.texcoord[0].y, vertex.attrib[8], c[5];
-DP4 result.texcoord[0].x, vertex.attrib[8], c[4];
-END
-# 8 instructions, 0 R-regs
+++ /dev/null
-/// ============================================================================
-/*
-Copyright (C) 2004 Robert Beckebans <trebor_7@users.sourceforge.net>
-Please see the file "CONTRIBUTORS" for a list of contributors
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/// ============================================================================
-
-attribute vec4 attr_TexCoord0;
-
-void main()
-{
- // transform vertex position into homogenous clip-space
- gl_Position = ftransform();
-
- // transform texcoords
- gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
-
- // assign color
- gl_FrontColor = gl_Color;
-}
+++ /dev/null
-<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
-<!-- generated by Radiant setup, modify at your own risks -->
-<links>
-<item name="NetRadiant website" url="http://www.icculus.org/netradiant/"/>
-<item name="q3map2 handbook (web)" url="http://shaderlab.com/q3map2/manual/default.htm"/>
-<item name="ETB documentation (web)" url="http://www.map-craft.com/modules.php?name=ETB"/>
-</links>
+++ /dev/null
-common/areaportal
-common/clip
-common/clusterportal
-common/cushion
-common/donotenter
-common/full_clip
-common/hint
-common/missileclip
-common/nodraw
-common/nodrawnonsolid
-common/nodrop
-common/noimpact
-common/origin
-common/trigger
-common/weapclip
-liquid
-fog
\ No newline at end of file
+++ /dev/null
-base_support/support1rust
-base_support/support1shiny
-base_support/support2rust
-base_support/wplat1_1
-base_support/plate2_5
\ No newline at end of file
+++ /dev/null
-base_door/shinymetaldoor
-base_door/shinymetaldoor_outside
-gothic_door/door02_bred
-gothic_door/door02_bred2_shiny
-gothic_door/door02_eblue2_shiny
-gothic_door/door02_i_ornate5_fin
-gothic_door/door02_j
-gothic_door/door02_j3
-gothic_door/door02_j4
-gothic_door/door02_k2b
\ No newline at end of file
+++ /dev/null
-{
- "entity" "misc_model"
-
- "offset" "-16"
-
- "model" "models/mapobjects/trees_sd/tree_a.md3"
- "model" "models/mapobjects/trees_sd/tree_b.md3"
- "model" "models/mapobjects/trees_sd/tree_c.md3"
- "model" "models/mapobjects/trees_sd/tree_d.md3"
-
- "pitch" "-5" "5"
- "yaw" "0" "360"
- "scale" "1" "1.3"
-}
\ No newline at end of file
+++ /dev/null
-$aseconvert models/mapobjects/spotlamp/spotlamp_x.ase
-$exit
-
-
-$aseconvert models/weapons2/machinegun/machinegun.ase -weapon
-$aseconvert models/weapons2/bfg/bfg.ase -weapon
-$aseconvert models/weapons2/railgun/railgun.ase -weapon
-$aseconvert models/weapons2/shotgun/shotgun.ase -weapon
-
-$aseconvert models/weapons2/meshes/chaingun.ase -weapon
-$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
-$aseconvert models/weapons2/meshes/grapple.ase -weapon
-$aseconvert models/weapons2/meshes/grenadel.ase -weapon
-$aseconvert models/weapons2/meshes/lightning.ase -weapon
-$aseconvert models/weapons2/meshes/plasma.ase -weapon
-$aseconvert models/weapons2/meshes/railgun.ase -weapon
-$aseconvert models/weapons2/meshes/ricochet.ase -weapon
-$aseconvert models/weapons2/meshes/rocketl.ase -weapon
-$aseconvert models/weapons2/meshes/shotgun.ase -weapon
-
-
-$aseconvert models/mapobjects/chain1.ase
-$aseconvert models/mapobjects/chain2.ase
-$aseconvert models/mapobjects/chain3.ase
-$aseconvert models/mapobjects/chain4.ase
-
-$exit
-
-$aseanimconvert models/players/light/bandolier/bandolier.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/brandon/4brandon.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/cash/4cash.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/doom/doom.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/shauna/shauna.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/tim/4tim.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/xian/4xian.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/carmack/carmack.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/heavy/paulj/4paulj.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/heavy/brock/brock.ase -origin 0 0 24 -playerparms 75 138 140 1
-
-$exit
-
-// note: playerparms are "skipStart skipEnd maxUpperFrames maxHeadFrames"
-$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/visor/4visor.ase -lod 1 0 -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/visor/4visor.ase -lod 2 0 -origin 0 0 24 -playerparms 75 138 140 1
-
-
-
-$aseconvert models/powerups/ammo/backpack.ase
-
-$aseconvert models/weapons2/meshes/assault.ase -weapon
-$aseconvert models/weapons2/meshes/chaingun.ase -weapon
-$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
-$aseconvert models/weapons2/meshes/grapple.ase -weapon
-$aseconvert models/weapons2/meshes/grenadel.ase -weapon
-$aseconvert models/weapons2/meshes/lightning.ase -weapon
-$aseconvert models/weapons2/meshes/plasma.ase -weapon
-$aseconvert models/weapons2/meshes/railgun.ase -weapon
-$aseconvert models/weapons2/meshes/ricochet.ase -weapon
-$aseconvert models/weapons2/meshes/rocketl.ase -weapon
-$aseconvert models/weapons2/meshes/shotgun.ase -weapon
-
-$aseconvert models/mapobjects/arenalogo.ase
-
-//
-// talk sprite
-//
-$modelname sprites/balloon
-$cd sprites
-$spritebase -8 -8 16 16
-$spriteshader sprites/balloon3.tga
-
-// plasma ball sprite
-$modelname sprites/plasma
-$cd sprites
-$spritebase -16 -16 32 32
-$spriteshader sprites/plasma1.tga
-$spriteshader sprites/plasma2.tga
-
-//
-// player models
-// note: playerparms are "skipStart skipEnd maxUpperFrames maxHeadFrames"
-//
-$aseanimconvert models/players/light/bandolier/bandolier.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/brandon/4brandon.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/cash/4cash.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/doom/doom.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/light/shauna/shauna.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/tim/4tim.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/xian/4xian.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/medium/carmack/carmack.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/heavy/paulj/4paulj.ase -origin 0 0 24 -playerparms 75 138 140 1
-$aseanimconvert models/players/heavy/brock/brock.ase -origin 0 0 24 -playerparms 75 138 140 1
-
-//
-// weaphits
-//
-$modelname models/weaphits/bullet
-$cd models/weaphits
-$base bullet01.3ds
-$frame bullet01.3ds
-$frame bullet02.3ds
-$frame bullet03.3ds
-$frame bullet04.3ds
-$frame bullet05.3ds
-$frame bullet06.3ds
-$skin bullet01.3ds
-$skin bullet03.3ds
-$skin bullet05.3ds
-
-$modelname models/weaphits/ring01
-$cd models/weaphits
-$base ring01_1.3ds
-$frame ring01_1.3ds
-$frame ring01_2.3ds
-$frame ring01_3.3ds
-$frame ring01_4.3ds
-$frame ring01_5.3ds
-$frame ring01_6.3ds
-$skin ring01_1.3ds
-$skin ring01_3.3ds
-$skin ring01_5.3ds
-
-$modelname models/weaphits/ring02
-$cd models/weaphits
-$base ring02_1.3ds
-$frame ring02_1.3ds
-$frame ring02_2.3ds
-$frame ring02_3.3ds
-$frame ring02_4.3ds
-$frame ring02_5.3ds
-$frame ring02_6.3ds
-$skin ring02_1.3ds
-$skin ring02_3.3ds
-$skin ring02_5.3ds
-
-$modelname models/weaphits/boomgra
-$cd models/weaphits
-$base boomgra1.3ds
-$frame boomgra1.3ds
-$frame boomgra2.3ds
-$frame boomgra3.3ds
-$frame boomgra4.3ds
-$frame boomgra5.3ds
-$frame boomgra6.3ds
-$skin boomgra1.3ds
-$skin boomgra3.3ds
-$skin boomgra5.3ds
-
-$modelname models/weaphits/boom01
-$cd models/weaphits
-$base boom01_1.3ds
-$frame boom01_1.3ds
-$frame boom01_2.3ds
-$frame boom01_3.3ds
-$frame boom01_4.3ds
-$frame boom01_5.3ds
-$frame boom01_6.3ds
-$skin boom01_1.3ds
-$skin boom01_3.3ds
-$skin boom01_5.3ds
-
-$modelname models/weaphits/boom02
-$cd models/weaphits
-$base boom02_1.3ds
-$frame boom02_1.3ds
-$frame boom02_2.3ds
-$frame boom02_3.3ds
-$frame boom02_4.3ds
-$frame boom02_5.3ds
-$frame boom02_6.3ds
-$skin boom02_1.3ds
-$skin boom02_3.3ds
-$skin boom02_5.3ds
-
-$modelname models/weaphits/boom03
-$cd models/weaphits
-$base boom03_1.3ds
-$frame boom03_1.3ds
-$frame boom03_2.3ds
-$frame boom03_3.3ds
-$frame boom03_4.3ds
-$frame boom03_5.3ds
-$frame boom03_6.3ds
-$skin boom03_1.3ds
-$skin boom03_3.3ds
-$skin boom03_5.3ds
-
-$modelname models/weaphits/boom04
-$cd models/weaphits
-$base boom04_1.3ds
-$frame boom04_1.3ds
-$frame boom04_2.3ds
-$frame boom04_3.3ds
-$frame boom04_4.3ds
-$frame boom04_5.3ds
-$frame boom04_6.3ds
-$skin boom04_1.3ds
-$skin boom04_3.3ds
-$skin boom04_5.3ds
-
-$modelname models/weaphits/boom05
-$cd models/weaphits
-$base boom05_1.3ds
-$frame boom05_1.3ds
-$frame boom05_2.3ds
-$frame boom05_3.3ds
-$frame boom05_4.3ds
-$frame boom05_5.3ds
-$frame boom05_6.3ds
-$skin boom05_1.3ds
-$skin boom05_3.3ds
-$skin boom05_5.3ds
-
-//
-// point powerups
-//
-$aseconvert models/powerups/points/small.ase
-$aseconvert models/powerups/points/medium.ase
-$aseconvert models/powerups/points/large.ase
-
-//
-// ammo
-//
-$aseconvert models\powerups\ammo\bfgam.ASE
-$aseconvert models\powerups\ammo\bfgam_1.ASE
-$aseconvert models\powerups\ammo\bouncyam.ASE
-$aseconvert models\powerups\ammo\bouncyam_1.ASE
-$aseconvert models\powerups\ammo\carbineam.ASE
-$aseconvert models\powerups\ammo\carbineam_1.ASE
-$aseconvert models\powerups\ammo\flameam.ASE
-$aseconvert models\powerups\ammo\flameam_1.ASE
-$aseconvert models\powerups\ammo\grenadeam.ASE
-$aseconvert models\powerups\ammo\grenadeam_1.ASE
-$aseconvert models\powerups\ammo\lightningam.ASE
-$aseconvert models\powerups\ammo\lightningam_1.ASE
-$aseconvert models\powerups\ammo\machinegunam.ASE
-$aseconvert models\powerups\ammo\machinegunam_1.ASE
-$aseconvert models\powerups\ammo\plasmaam.ASE
-$aseconvert models\powerups\ammo\plasmaam_1.ASE
-$aseconvert models\powerups\ammo\railgunam.ASE
-$aseconvert models\powerups\ammo\railgunam_1.ASE
-$aseconvert models\powerups\ammo\rocketam.ASE
-$aseconvert models\powerups\ammo\rocketam_1.ASE
-$aseconvert models\powerups\ammo\shotgunam.ASE
-$aseconvert models\powerups\ammo\shotgunam_1.ASE
-
-$aseconvert models/powerups/ammo/backpack.ase
-
-//
-// missiles
-//
-$modelname models/ammo/plasma/plasma
-$cd models/ammo/plasma
-$base plasma1.3ds
-$frame plasma1.3ds
-$skin plasma1.3ds
-
-$modelname models/ammo/laser/laser
-$cd models/ammo/laser
-$base laser1.3ds
-$frame laser1.3ds
-$skin laser1.3ds
-
-$modelname models/ammo/rocket/rocket
-$cd models/ammo/rocket
-$base rocket1.3ds
-$frame rocket1.3ds
-$skin rocket1.3ds
-$skin rocket2.3ds
-
-$aseconvert models/ammo/grenade1.ase
-$aseconvert models/explosions/smoke2.ase
-
-//
-// map objects
-//
-$aseconvert models/mapobjects/ceilinglamp1.ase
-$aseconvert models/mapobjects/ceilinglamp2.ase
-$aseconvert models/mapobjects/chain1.ase
-$aseconvert models/mapobjects/chain2.ase
-$aseconvert models/mapobjects/chain3.ase
-$aseconvert models/mapobjects/chain4.ase
-$aseconvert models/mapobjects/crux.ase
-$aseconvert models/mapobjects/floorlamp1.ase
-$aseconvert models/mapobjects/floorlamp2.ase
-$aseconvert models/mapobjects/hook.ase
-$aseconvert models/mapobjects/impale.ase
-$aseconvert models/mapobjects/standinglamp1.ase
-$aseconvert models/mapobjects/standinglamp2.ase
-$aseconvert models/mapobjects/standinglamp3.ase
-$aseconvert models/mapobjects/walllamp1.ase
-$aseconvert models/mapobjects/walllamp2.ase
-$aseconvert models/mapobjects/walllamp3.ase
-
-
-//
-// objects
-//
-$aseconvert models/objects/dmspot.ase -origin 0 0 24
-$aseconvert models/objects/box01.ase
-
-//
-// weapons
-//
-$aseconvert models/weapons2/meshes/assault.ase -weapon
-$aseconvert models/weapons2/meshes/bfg.ase -weapon
-$aseconvert models/weapons2/meshes/chaingun.ase -weapon
-$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
-$aseconvert models/weapons2/meshes/grapple.ase -weapon
-$aseconvert models/weapons2/meshes/grenadel.ase -weapon
-$aseconvert models/weapons2/meshes/lightning.ase -weapon
-$aseconvert models/weapons2/meshes/plasma.ase -weapon
-$aseconvert models/weapons2/meshes/railgun.ase -weapon
-$aseconvert models/weapons2/meshes/ricochet.ase -weapon
-$aseconvert models/weapons2/meshes/rocketl.ase -weapon
-$aseconvert models/weapons2/meshes/shotgun.ase -weapon
-
-//
-// blood
-//
-$modelname models/weaphits/blood
-$cd models/weaphits
-$spritebase -16 -16 32 32
-$spriteshader models/weaphits/blood201.tga
-$spriteshader models/weaphits/blood202.tga
-$spriteshader models/weaphits/blood203.tga
-$spriteshader models/weaphits/blood204.tga
-$spriteshader models/weaphits/blood205.tga
-
-
-//
-// missiles
-//
-$modelname models/ammo/plasma/plasma
-$cd models/ammo/plasma
-$base plasma1.3ds
-$frame plasma1.3ds
-$skin plasma1.3ds
-
-$modelname models/ammo/laser/laser
-$cd models/ammo/laser
-$base laser1.3ds
-$frame laser1.3ds
-$skin laser1.3ds
-
-
-$modelname models/ammo/rocket/rocket
-$cd models/ammo/rocket
-$base rocket1.3ds
-$frame rocket1.3ds
-$skin rocket1.3ds
-$skin rocket2.3ds
-
-
-// weaphits
-
-$modelname models/weaphits/bullet
-$cd models/weaphits
-$base bullet01.3ds
-$frame bullet01.3ds
-$frame bullet02.3ds
-$frame bullet03.3ds
-$frame bullet04.3ds
-$frame bullet05.3ds
-$frame bullet06.3ds
-$skin bullet01.3ds
-$skin bullet03.3ds
-$skin bullet05.3ds
-
-$modelname models/weaphits/ring01
-$cd models/weaphits
-$base ring01_1.3ds
-$frame ring01_1.3ds
-$frame ring01_2.3ds
-$frame ring01_3.3ds
-$frame ring01_4.3ds
-$frame ring01_5.3ds
-$frame ring01_6.3ds
-$skin ring01_1.3ds
-$skin ring01_3.3ds
-$skin ring01_5.3ds
-
-$modelname models/weaphits/ring02
-$cd models/weaphits
-$base ring02_1.3ds
-$frame ring02_1.3ds
-$frame ring02_2.3ds
-$frame ring02_3.3ds
-$frame ring02_4.3ds
-$frame ring02_5.3ds
-$frame ring02_6.3ds
-$skin ring02_1.3ds
-$skin ring02_3.3ds
-$skin ring02_5.3ds
-
-$modelname models/weaphits/boomgra
-$cd models/weaphits
-$base boomgra1.3ds
-$frame boomgra1.3ds
-$frame boomgra2.3ds
-$frame boomgra3.3ds
-$frame boomgra4.3ds
-$frame boomgra5.3ds
-$frame boomgra6.3ds
-$skin boomgra1.3ds
-$skin boomgra3.3ds
-$skin boomgra5.3ds
-
-$modelname models/weaphits/boom01
-$cd models/weaphits
-$base boom01_1.3ds
-$frame boom01_1.3ds
-$frame boom01_2.3ds
-$frame boom01_3.3ds
-$frame boom01_4.3ds
-$frame boom01_5.3ds
-$frame boom01_6.3ds
-$skin boom01_1.3ds
-$skin boom01_3.3ds
-$skin boom01_5.3ds
-
-$modelname models/weaphits/boom02
-$cd models/weaphits
-$base boom02_1.3ds
-$frame boom02_1.3ds
-$frame boom02_2.3ds
-$frame boom02_3.3ds
-$frame boom02_4.3ds
-$frame boom02_5.3ds
-$frame boom02_6.3ds
-$skin boom02_1.3ds
-$skin boom02_3.3ds
-$skin boom02_5.3ds
-
-$modelname models/weaphits/boom03
-$cd models/weaphits
-$base boom03_1.3ds
-$frame boom03_1.3ds
-$frame boom03_2.3ds
-$frame boom03_3.3ds
-$frame boom03_4.3ds
-$frame boom03_5.3ds
-$frame boom03_6.3ds
-$skin boom03_1.3ds
-$skin boom03_3.3ds
-$skin boom03_5.3ds
-
-$modelname models/weaphits/boom04
-$cd models/weaphits
-$base boom04_1.3ds
-$frame boom04_1.3ds
-$frame boom04_2.3ds
-$frame boom04_3.3ds
-$frame boom04_4.3ds
-$frame boom04_5.3ds
-$frame boom04_6.3ds
-$skin boom04_1.3ds
-$skin boom04_3.3ds
-$skin boom04_5.3ds
-
-$modelname models/weaphits/boom05
-$cd models/weaphits
-$base boom05_1.3ds
-$frame boom05_1.3ds
-$frame boom05_2.3ds
-$frame boom05_3.3ds
-$frame boom05_4.3ds
-$frame boom05_5.3ds
-$frame boom05_6.3ds
-$skin boom05_1.3ds
-$skin boom05_3.3ds
-$skin boom05_5.3ds
-
-
-//
-// armor
-//
-$aseconvert models/powerups/armor/armor_red.ase
-$aseconvert models/powerups/armor/armor_yel.ase
-$aseconvert models/powerups/armor/armor_grn.ase
-$aseconvert models/powerups/armor/shard.ase
-$aseconvert models/powerups/armor/shard_sphere.ase
-$aseconvert models/powerups/armor/shard_sphere_1.ase
-
-//
-// health
-//
-$aseconvert models/powerups/health/small.ase
-$aseconvert models/powerups/health/small_1.ase
-$aseconvert models/powerups/health/medium.ase
-$aseconvert models/powerups/health/medium_1.ase
-$aseconvert models/powerups/health/large.ase
-$aseconvert models/powerups/health/large_1.ase
-$aseconvert models/powerups/health/mega.ase
-$aseconvert models/powerups/health/mega_1.ase
-
-//
-// holdable powerups
-//
-$aseconvert models/powerups/holdable/ringodeth.ase
-$aseconvert models/powerups/holdable/medkit.ase
-$aseconvert models/powerups/holdable/teleporter.ase
-
-//
-// instant powerups
-//
-$aseconvert models/powerups/instant/enviro.ase
-$aseconvert models/powerups/instant/enviro_1.ase
-$aseconvert models/powerups/instant/enviro_ring.ase
-$aseconvert models/powerups/instant/enviro_ring_1.ase
-$aseconvert models/powerups/instant/flight.ase
-$aseconvert models/powerups/instant/flight_1.ase
-$aseconvert models/powerups/instant/flight_ring.ase
-$aseconvert models/powerups/instant/flight_ring_1.ase
-$aseconvert models/powerups/instant/haste.ase
-$aseconvert models/powerups/instant/haste_1.ase
-$aseconvert models/powerups/instant/haste_ring.ase
-$aseconvert models/powerups/instant/haste_ring_1.ase
-$aseconvert models/powerups/instant/invis.ase
-$aseconvert models/powerups/instant/invis_1.ase
-$aseconvert models/powerups/instant/invis_ring.ase
-$aseconvert models/powerups/instant/invis_ring_1.ase
-$aseconvert models/powerups/instant/scan.ase
-$aseconvert models/powerups/instant/scan_1.ase
-$aseconvert models/powerups/instant/scan_ring.ase
-$aseconvert models/powerups/instant/scan_ring_1.ase
-$aseconvert models/powerups/instant/quad.ase
-$aseconvert models/powerups/instant/quad_1.ase
-$aseconvert models/powerups/instant/quad_ring.ase
-$aseconvert models/powerups/instant/quad_ring_1.ase
-$aseconvert models/powerups/instant/regen.ase
-$aseconvert models/powerups/instant/regen_1.ase
-$aseconvert models/powerups/instant/regen_ring.ase
-$aseconvert models/powerups/instant/regen_ring_1.ase
-
-$exit
-
-//
-// maps
-//
-$maps test_box test_items mirror mirror2
-
-
-//
-// misc
-//
-$file q3default.cfg
-
-
+++ /dev/null
-//**********************************************************************//
-// shaderlist.txt modified for Q3Radiant //
-// by Eutectic - 13 May 2000 //
-// //
-// Rev history: //
-// 08/11/2000
-// TTimo - changed liquid to liquids and sky to skies for better //
-// consistency with the directories and actual shader names //
-// //
-// Added the names of the new shader files created as a result //
-// of the cleanup of the old shader files so Q3Radiant will read //
-// and display all the shaders in the texture window. //
-// //
-// SHADER FILE NAMES ADDED: //
-// base_door //
-// gothic_button //
-// gothic_door //
-//**********************************************************************//
-
-// this file lists all the separate shader files
-
-blacksky
-cel
-common
-desertfactory
-domination
-dsi
-e7
-egyptsoc
-el3dm1
-evil1_grates
-evil2
-evil3
-evil4_techtrims
-evil5
-evil6_floors
-evil6_lights
-evil6_support
-evil6_trims
-evil6_walls
-evil8_base
-eX
-exosystem
-final_rage
-flags
-harlequin_sky
-hip_interstellar
-kaznexctf2
-leiprojectile
-liquids
-mandelbrotsky
-mflag
-morphed
-newsky_asteroids
-newsky_nebulae
-newsky_planets
-nexdm18_rmx
-official_cmp1
-onslaught
-reaper
-ruiner
-savdm6ish
-sav-graysky1
-sav-liquids
-sbshield
-sfx
-stralenex1
-stralenex8
-strength
-stormkeep
-swamp
-teamfx
-terrain_alphafade
-terrain_dotproduct2projected
-terrain_dotproduct2
-test3
-trak4
-trak5
-tree
-tuba
-turrets
-tutorial
-tznex01
-water
-mirceakitsune
-artwork
-gasolinepowered
-ab
-greatwall_overloaded
-greatwall_overloaded-ter
-greatwall_revisited
-brokenworld
-warpzone
+++ /dev/null
-/*QUAKED _skybox (0.77 0.88 1.0) (-4 -4 -4) (4 4 4)
-Compiler-only entity that specifies a the origin of a sky box (a wholly contained, separate area of the map), similar to some games' portal skies. When compiled with Q3Map2, the sky box surfaces will be visible from any place where sky is normally visible. It will cast shadows on the normal parts of the map, and can be used with cloud layers and other effects. As it is compiler-only, it can't "scale up" entities in its box.
-To use this, carve a small box in some larger structure on your map, place this entity inside that box hole, and make a small version on what should be seen in the sky there.
--------- KEYS --------
-angle: rotation angle of the sky surfaces.
-angles: Individual control of PITCH, YAW, and ROLL (default 0 0 0).
-_scale: scaling factor (default 64), good values are between 50 and 300, depending on the map.
-*/
-
-/*QUAKED dom_controlpoint (.3 .3 1) (-16 -16 -16) (16 16 16)
-Domination control point
-In order to get Domination working well in your map, you need to place dom_team and dom_controlpoint entities. You *must* have at least 3 dom_team entities - 2 minimum teams and one blank one (empty netname and no team). You can have up to 4 teams (5 dom_team entities).
--------- KEYS --------
-message: message to be displayed to all players when this point is captured, preceded by the team's name. This defaults to " has captured a control point". You can specify different names for each point, for example " has captured the Lava Room".
-wait: How often this point gives its controlling team frags.
-frags: How many frags this point gives each wait cycle.
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-zbqry="zbqryf/qbzvangvba/qbz_hapynvzrq.zq3"
-
-*/
-
-/*QUAKED dom_team (.3 .3 1) (-16 -16 -16) (16 16 16)
-Domination team.
-In order to get Domination working well in your map, you need to place dom_team and dom_controlpoint entities. You *must* have at least 3 dom_team entities - 2 minimum teams and one blank one (empty netname and no team). You can have up to 4 teams (5 dom_team entities).
--------- KEYS --------
-netname: name of team (Red Team). Set to "" or don't define for the required blank team.
-cnt: color of the team. See the "Helpful Extras" section for info.
-model: When this team captures control points, the points turn to this model. If this is the neutral team, points start out as this model.
-noise: Sound to be played on the control point when it's captured. Only players nearby will hear it.
-noise1: Sound to be played to all players when the control point is captured. Also good for an announcer voice ("Red Team has captured a control point")
-*/
-
-/*QUAKED func_assault_destructible (.5 0 .5) ?
-This is a brush model which can be damaged. Once triggered it's active and will happily receive damage players inflict upon it. Once all health is consumed it'll disappear and trigger the targeted entity/entities. As damage is received the brush model will be tinted in an increasingly visible flavor of red to give visible feedback.
--------- KEYS --------
-health: The damage this trigger can take
-target: The entity/entities to be triggered once this entity gets invisible
-targetname: The name other entities can use to target this entity
-mdl: particle effect name to show when destroyed
-count: particle effect multiplier
-mdl_dead: optional replacement model to show when destroyed
-debris: names of debris models to show when destroyed, separated by spaces
-noise: sound to play when destroyed
-dmg: damage to deal to the environment when destroyed
-dmg_edge: edge damage to deal to the environment when destroyed
-dmg_radius: damage radius
-dmg_force: damage force
-message: death message when a player gets hit by the explosion
-message2: death message when someone gets pushed into this (default: "was pushed into an explosion by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-debrismovetype: way in which the debris moves: one of 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-debrissolid: solidity of the debris: one of 0 = NOT, 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE
-debrisvelocity: initial velocity vector of the debris (static part)
-debrisvelocityjitter: initial velocity vector of the debris (random part)
-debrisavelocityjitter: initial angular velocity vector of the debris (random part)
-debristime: time till the debris fades (average)
-debristimejitter: time till the debris fades (random part)
-debrisfadetime: how long debris takes to fade
-debrisdamageforcescale: how much debris is affected by damage force (e.g. explosions)
-debrisskin: skin number of debris
-*/
-
-/*QUAKED func_assault_wall (.5 0 .5) ?
-Brush model that will disappear once the targeted target_objective is fulfilled. This can be used to restrict access to parts of the map until a certain objective has been conquered.
--------- KEYS --------
-target: targetname of a target_objective
-*/
-
-/*QUAKED func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
-Solid entity that oscillates back and forth in a linear motion. By default, it will have an amount of displacement in either direction equal to the dimension of the brush in the axis in which it's bobbing. Entity bobs on the Z axis (up-down) by default. It can also emit sound if the "noise" key is set. Will crush the player when blocked.
--------- KEYS --------
-speed: amount of time in seconds for one complete oscillation cycle (default 4).
-height: sets the amount of travel of the oscillation movement (default 32).
-phase: sets the start offset of the oscillation cycle. Values must be 0 < phase < 1. Any integer phase value is the same as no offset (default 0).
-noise: path/name of .wav or .ogg file to play. Use looping sounds only (e.g. sound/world/drone6.wav - See Notes).
-dmg: damage a player who gets crushed by it receives
-dmgtime: interval to apply dmg to a player who is s in the way
-message: death message when a player gets crushed
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
--------- SPAWNFLAGS --------
-X_AXIS: entity will bob along the X axis.
-Y_AXIS: entity will bob along the Y axis.
-*/
-
-/*QUAKED func_button (0 .5 .8) ?
-When a button is touched by a player, it moves in the direction set by the "angle" key, triggers all its targets, stays pressed by an amount of time set by the "wait" key, then returns to it's original position where it can be operated again.
--------- KEYS --------
-angle: determines the direction in which the button will move (up = -1, down = -2).
-target: all entities with a matching targetname will be triggered.
-target2: all entities with a matching targetname will be triggered.
-target3: all entities with a matching targetname will be triggered.
-target4: all entities with a matching targetname will be triggered.
-speed: speed of button's displacement (default 40).
-wait: number of seconds button stays pressed (default 1, -1 = return immediately).
-lip: lip remaining at end of move (default 4 units).
-health: (default 0) if set to any non-zero value, the button must take damage (any amount) to activate.
-*/
-
-/*QUAKED func_door (0 .5 .8) ? START_OPEN - DOOR_DONT_LINK - - TOGGLE
-Normal sliding door entity. By default, the door will activate when player walks close to it or when damage is inflicted to it.
-If DOOR_DONT_LINK is not set, the door will be linked with all doors it touches. Note however that for linked doors to work properly, it is necessary that ALL linked doors have SOME volume of common area (that is, there must be a point that is part of ALL doors).
--------- KEYS --------
-message: is printed when the door is touched if it is a trigger door and it hasn't been fired yet, or death message if dmg is set
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-angle: determines the opening direction
-targetname: if set, no touch field will be spawned and a remote button or trigger field activates the door.
-health: if set, door must be shot open
-speed: movement speed (100 default)
-wait: wait before returning (3 default, -1 = never return)
-lip: lip remaining at end of move (8 default)
-dmg: damage to inflict when blocked (when triggered and someone is in the way)
-sounds: when 1, use default door sounds
-noise1: sound when the door opens
-noise2: sound when the door closes
--------- SPAWNFLAGS --------
-START_OPEN: causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or damage triggered doors).
-DOOR_DONT_LINK: the door won't link with another door it touches
-TOGGLE: causes the door to wait in both the start and end states for a trigger event.
-*/
-
-/*QUAKED func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN - TOGGLE X_AXIS Y_AXIS
-Normal rotating door entity that opens by rotating around an axis (default: Z). Use an origin brush to specify the rotation axis.
-By default, the door will activate when player walks close to it or when damage is inflicted to it.
-If DOOR_DONT_LINK is not set, the door will be linked with all doors it touches.
-BIDIR makes the door work bidirectional, so that the opening direction is always away from the requestor.
-The usage of bidirectional doors requires two manually instantiated triggers (trigger_multiple), the one to open it in the other direction
-must have set trigger_reverse to 1.
-BIDIR_IN_DOWN will the door prevent from reopening while closing if it is triggered from the other side.
--------- KEYS --------
-message: is printed when the door is touched if it is a trigger door and it hasn't been fired yet, or death message if dmg is set
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-angle: determines the destination angle for opening. negative values reverse the direction (90 default)
-targetname: if set, no touch field will be spawned and a remote button or trigger field activates the door.
-health: if set, door must be shot open
-speed: speed to rotate (in degrees per second)
-wait: wait before returning (3 default, -1 = never return)
-dmg: damage to inflict when blocked (when triggered and someone is in the way)
-sounds: when 1, use default door sounds
-noise1: sound when the door opens
-noise2: sound when the door closes
--------- SPAWNFLAGS --------
-START_OPEN: causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or damage triggered doors).
-DOOR_DONT_LINK: the door won't link with another door it touches
-TOGGLE: causes the door to wait in both the start and end states for a trigger event.
-*/
-
-/*QUAKED func_door_secret (0 .5 .8) ? OPEN_ONCE 1ST_LEFT 1ST_DOWN NO_SHOOT ALWAYS_SHOOT
-Basic secret door. Slides back, then to the side. Angle determines direction. Opens when targeted or when shot; does not create its own trigger field like func_door does.
--------- KEYS --------
-wait: # of seconds before coming back
-key1: first entity key with one-line description
-key2: second entity key with one-line description
-t_width: override WIDTH to move back (or height if going down)
-t_length: override LENGTH to move sideways
-dmg: damage to inflict when blocked (2 default)
-message: text to display when activating the door, or death message if dmg is set
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-noise1: sound when opening backwards or closing
-noise2: sound when opening sideways
-noise3: sound when stopping
--------- SPAWNFLAGS --------
-OPEN_ONCE: only work once, then stay open
-1ST_LEFT: 1st move is left of arrow
-1ST_DOWN: 1st move is down from arrow
-NO_SHOOT: never respond to shots
-ALWAYS_SHOOT: even if targetname is set, respond to shots
-*/
-
-/*QUAKED func_group (0 .5 .8) ?
-This is not an entity as such. It is strictly an editor utility to group world brushes and patches together for convenience (selecting, moving, copying, etc). You cannot group entities with this.
--------- Q3MAP2 KEYS --------
-_lightmapscale: light map resolution factor
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
--------- KEYS --------
-_indexmap: Path/name for the TGA file used to guide the mapping of textures on the terrain surface.
-_layers: number of unique root shaders that will be use on the terrain.
-_shader: Path to the metashader used to assign textures to the terrain entity. Note: Omit the "textures/" prefix.
-_offsets: space separated list of height offsets for the index map
-*/
-
-/*QUAKED func_ladder (0 .5 .8) ?
-a ladder, need i say no more
-grab a trigger brush and put it in front of the part that you want the player to climb
-*/
-
-/*QUAKED func_plat (0 .5 .8) ? - - CRUSH
-Rising platform the player can ride to reach higher places. Plats must always be drawn in the raised position, so they will operate and be lighted correctly but they spawn in the lowered position. The plat will stay in the raised position until the player steps off.
--------- KEYS --------
-speed: determines how fast the plat moves (default 150).
-lip: lip remaining at end of move (default 16). Has no effect if "height" is set.
-height: if set, this will determine the total amount of vertical travel of the plat.
-dmg: damage to inflict on player when he blocks operation of plat. Plat will reverse direction when blocked.
-targetname: if set, the trigger that points to this will lower the plat each time it fires. The plat lowers and lifts someone up later.
-sounds: 2 for alternate sound set, -1 for silence, or use the fields below
-sound1: platform starts moving sound
-sound2: platform stop sound
-message: kill message, when someone gets killed by this plat
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
--------- SPAWNFLAGS --------
-CRUSH: crush players hit by the platform instantly
--------- NOTES --------
-By default, the total amount of vertical travel of a platform is implicitly determined by the overall vertical size of the brushes of which it's made minus the lip value. But if the "height" key is used, then the total amount of vertical travel of the plat will be exactly that value regardless of the shape and size of the plat and regardless of the value of the "lip" key. Using the "height" key is the best method for any kind of platforms and the only possible one for thin plats which need to travel vertical distances many times their own thickness. Setting the origin key is simply an alternate method to using an origin brush. When using the model2 key, the origin point of the model will correspond to the origin point defined by either the origin brush or the origin coordinate value.
-*/
-
-/*QUAKED func_rain (0 .5 .8) ?
-This is an invisible area like a trigger, which rain falls inside of.
--------- KEYS --------
-velocity: falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
-cnt: sets color of rain in the Quake palette (default 12 - white)
-count: adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-
-/*QUAKED func_rotating (0 .5 .8) ? - - X_AXIS Y_AXIS
-Brush entity that spins in place on one axis (default Z). Use an origin brush to specify the rotation axis.
-To rotate around another axis, make a func_wall with an explicit avelocity given.
--------- KEYS --------
-speed: speed to rotate (in degrees per second)
-noise: path/name of looping .wav file to play.
-dmg: Do this much dmg every .dmgtime interval when blocked
-dmgtime: See above. (0.25s default)
-message: kill message when crushed by this
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
--------- SPAWNFLAGS --------
-X_AXIS: rotate around the X axis
-Y_AXIS: rotate around the Y axis
-*/
-
-/*QUAKED func_snow (0 .5 .8) ?
-This is an invisible area like a trigger, which snow falls inside of.
--------- KEYS --------
-velocity: falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
-cnt: sets color of snow in the Quake palette (default 12 - white)
-count: adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-
-/*QUAKED func_stardust (.5 .5 .5) (-8 -8 -8) (8 8 8)
-Point entity with EF_STARDUST applied. This will spawn a particle cloud with mostly golden particles. Used as eye-candy.
-*/
-
-/*QUAKED func_train (0 .5 .8) ?
-Trains are moving solids that follow a cycle of path_corner entities. Origin brushes are NOT supported; they use the "mins" corner as reference (that is, lowest x, y, and z coordinates).
-At each node, the train's mins corner hits exactly the path_corner.
-Trains always start on in the game.
-Trains do not damage the played when blocked.
-Trains cannot emit sound.
-Trains are not trigger-able or toggle-able.
-Trains cannot be block-stopped just by getting in their way, the player must be wedged between the train and another obstacle to block it.
--------- KEYS --------
-speed: default/initial speed of train (default 100 or overridden by speed value of targeted path_corner)
-target: targetname of first path_corner to move to at the default speed; ideally, this path_corner shall be exactly where the train starts
-noise: path/name of .wav or .ogg file to play while moving. Use looping sounds only (e.g. sound/world/drone6.wav - See Notes).
-dmg: damage a player who gets crushed by it receives
-dmgtime: interval to apply dmg to a player who is s in the way
-message: death message when a player gets crushed
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-*/
-
-/*QUAKED info_location (1 1 0) (-8 -8 -8) (8 8 8)
-Location for use by the %l escape in "say" messages.
-The closest "visible" info_location entity is chosen to find the right location name for a point.
--------- KEYS --------
-message: name of location, possibly with color codes
-*/
-
-/*QUAKED info_notnull (0 .5 0) (-8 -8 -8) (8 8 8)
-Entity that does nothing, but may be targeted (e.g. to use its position)
--------- KEYS --------
-targetname: must match the target key of entity that uses this for pointing.
-*/
-
-/*QUAKED info_null (0 .5 0) (-8 -8 -8) (8 8 8)
-Aiming target for q3map2-internal entities like _decal or light. Removes itself when loaded, so it can NOT be used for in-game stuff!
--------- KEYS --------
-targetname: the entity that requires an aiming direction points to this.
-*/
-
-/*QUAKED info_player_attacker (1 0.5 0) (-16 -16 -24) (16 16 45)
-Attacking team's player spawning location in Assault. Should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-target: this should point to a target_objective to decide when this spawning point is active.
-target2: trigger all entities with this targetname when someone spawns
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_deathmatch (0 1 0) (-16 -16 -24) (16 16 45)
-Normal player spawning location in game types without team spawns. Should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-target: trigger all entities with this targetname when someone spawns
-targetname: when targeted by a func_button, pressing the button will assign the spawn point to the team of the activator as an additional spawn point, or reassign it if it was already assigned. Also used to assign spawn points to Onslaught control points.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_defender (.5 .5 .5) (-16 -16 -24) (16 16 45)
-Defending team's player spawning location in Assault. Should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-target: this should point to a target_objective to decide when this spawning point is active.
-target2: trigger all entities with this targetname when someone spawns
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_team1 (1 0 0) (-16 -16 -24) (16 16 45)
-Red team's player spawning location in e.g. CTF and Onslaught. Should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-target: trigger all entities with this targetname when someone spawns
-targetname: when targeted by a func_button, pressing the button will reassign the spawn point to the team of the activator. If a team has no more spawn point left, it immediately loses.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_team2 (0 0 1) (-16 -16 -24) (16 16 45)
-Blue team's player spawning location in e.g. CTF and Onslaught. Should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-target: trigger all entities with this targetname when someone spawns
-targetname: when targeted by a func_button, pressing the button will reassign the spawn point to the team of the activator. If a team has no more spawn point left, it immediately loses.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_team3 (1 1 0) (-16 -16 -24) (16 16 45)
-Yellow team's player spawning location, but there is no game mode to use this yet. Anyway, should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-target: trigger all entities with this targetname when someone spawns
-targetname: when targeted by a func_button, pressing the button will reassign the spawn point to the team of the activator. If a team has no more spawn point left, it immediately loses.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED info_player_team4 (1 0 1) (-16 -16 -24) (16 16 45)
-Pink team's player spawning location, but there is no game mode to use this yet. Anyway, should touch the floor, but not the walls, and should point where the player should look when he spawns there.
--------- KEYS --------
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-target: trigger all entities with this targetname when someone spawns
-targetname: when targeted by a func_button, pressing the button will reassign the spawn point to the team of the activator. If a team has no more spawn point left, it immediately loses.
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED item_flag_team1 (1 0 0) (-32 -32 0) (32 32 74)
-CTF flag for team one (Red). Use more than one if you really insist.
--------- KEYS --------
-model: model to use
-scale: scaling factor (DO set this when using your own model!)
-noise: sound played when flag is picked up
-noise1: sound played when flag is returned
-noise2: sound played when flag is captured
-noise3: sound played when flag is lost in the field and respawns itself
--------- ZBQRY SBE ENQVNAG BAYL - QB ABG FRG GUVF NF N XRL --------
-zbqry="zbqryf/pgs/enqvnag/synt_erq_enqvnag.zq3"
-*/
-
-/*QUAKED item_flag_team2 (0 0 1) (-32 -32 0) (32 32 74)
-CTF flag for team two (Blue). Use more than one if you really insist.
--------- KEYS --------
-model: model to use
-scale: scaling factor (DO set this when using your own model!)
-noise: sound played when flag is picked up
-noise1: sound played when flag is returned
-noise2: sound played when flag is captured
-noise3: sound played when flag is lost in the field and respawns itself
--------- ZBQRY SBE ENQVNAG BAYL - QB ABG FRG GUVF NF N XRL --------
-zbqry="zbqryf/pgs/enqvnag/synt_oyhr_enqvnag.zq3"
-*/
-
-/*QUAKED item_health_large (.9 .3 .3) (-30 -30 0) (30 30 48) FLOATING
-Large Health (default 50 health points)
--------- KEYS --------
-respawntime: time till it respawns (default: 20)
-health: amount of health it gives (default: 50 (g_pickup_healthlarge))
-max_health: max of health it increases to (default: 999 (g_pickup_healthlarge_max))
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_h50.md3"
-*/
-
-/*QUAKED item_health_medium (.9 .3 .3) (-30 -30 0) (30 30 48) FLOATING
-Medium Health (default 25 health points)
--------- KEYS --------
-respawntime: time till it respawns (default: 15)
-health: amount of health it gives (default: 25 (g_pickup_healthmedium))
-max_health: max of health it increases to (default: 999 (g_pickup_healthmedium_max))
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_h25.md3"
-*/
-
-/*QUAKED item_health_mega (.9 .3 .3) (-30 -30 0) (30 30 48) FLOATING
-Mega Health (default 100 health points)
-In Minstagib, this randomly turns into either an invisibility, an extra lives or a speed power-up with a default respawn time of 120.
--------- KEYS --------
-respawntime: time till it respawns (default: 30)
-health: amount of health it gives (default: 100 (g_pickup_healthmega))
-max_health: max of health it increases to (default: 999 (g_pickup_healthmega_max))
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_h100.md3"
-*/
-
-/*QUAKED item_health_small (.9 .3 .3) (-30 -30 0) (30 30 48) FLOATING
-Small Health (default 5 health points)
--------- KEYS --------
-respawntime: time till it respawns (default: 15)
-health: amount of health it gives (default: 5 (g_pickup_healthsmall))
-max_health: max of health it increases to (default: 5 (g_pickup_healthsmall_max))
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_h1.md3"
-*/
-
-/*QUAKED item_invincible (.3 .3 1) (-30 -30 0) (30 30 48) FLOATING
-Strong Shield
-In Minstagib, this randomly turns into either an invisibility, an extra lives or a speed power-up with a default respawn time of 120.
--------- KEYS --------
-respawntime: time till it respawns (default: 120)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_invincible.md3"
-*/
-
-/*QUAKED item_strength (.3 .3 1) (-30 -30 0) (30 30 48) FLOATING
-Strength aka Quad damage
-In Minstagib, this randomly turns into either an invisibility, an extra lives or a speed power-up with a default respawn time of 120.
--------- KEYS --------
-respawntime: time till it respawns (default: 120)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_strength.md3"
-*/
-
-/*QUAKED light (.65 .65 1) (-8 -8 -8) (8 8 8) LINEAR NOANGLE - - NOGRIDLIGHT
-Non-displayed point light source. The -pointscale and -scale arguments to Q3Map2 affect the brightness of these lights. The -skyscale argument affects brightness of entity sun lights.
-Maximum intensity (in a radius 16 sphere around the light): regular lights have light/256, linear lights have light/8000-16*fade.
-Falloff radius to a negligible light amount: regular lights have light have 16*sqrt(light), linear lights have light/(fade*8000).
-By this you see that you HAVE to specify fade for a linear light... use values below 0.01 there.
--------- KEYS --------
-light: intensity factor (default: 300). A linear
-_color: weighted RGB value of light color (default white - 1.0 1.0 1.0).
-target: Lights pointed at a target will be spotlights.
-radius: radius of a spotlight at the target point (default: 64)
-_anglescale: scales angle attenuation
-fade: Fade factor of light attenuation of linear lights. Linear lights completely vanish at distance light/(fade*8000), so if you want the light to vanish at distance X, specify light/(8000*X) here.
-_filterradius: filter radius for this light, similar to -light -filter
-_sun: if 1, this light is an infinite sun light
-_samples: number of samples to use to get soft shadows from a light
-_deviance: position deviance of the samples of a regular light (distributes the light samples in a cube of side length 2*_deviance around the origin), or angle deviance of the sun light samples in radians
--------- SPAWNFLAGS --------
-LINEAR: Use a linear falloff. Default is inverse distance squared (more realistic).
-NOANGLE: Ignore angle attenuation.
-NOGRIDLIGHT: Do not affect the light grid (dynamic entity lighting).
-*/
-
-/*QUAKED lightJunior (.65 .65 1) (-8 -8 -8) (8 8 8) LINEAR NOANGLE
-Non-displayed point light source that JUST APPLIES TO THE LIGHT GRID. No idea what this is good for. The -pointscale and -scale arguments to Q3Map2 affect the brightness of these lights. The -skyscale argument affects brightness of entity sun lights.
-Maximum intensity (in a radius 16 sphere around the light): regular lights have light/256, linear lights have light/8000-16*fade.
-Falloff radius to a negligible light amount: regular lights have light have 16*sqrt(light), linear lights have light/(fade*8000).
-By this you see that you HAVE to specify fade for a linear light... use values below 0.01 there.
--------- KEYS --------
-light: intensity factor (default: 300). A linear
-_color: weighted RGB value of light color (default white - 1.0 1.0 1.0).
-target: Lights pointed at a target will be spotlights.
-radius: radius of a spotlight at the target point (default: 64)
-_anglescale: scales angle attenuation
-fade: Fade factor of light attenuation of linear lights. Linear lights completely vanish at distance light/(fade*8000), so if you want the light to vanish at distance X, specify light/(8000*X) here.
-_filterradius: filter radius for this light, similar to -light -filter
-_sun: if 1, this light is an infinite sun light
-_samples: number of samples to use to get soft shadows from a light
-_deviance: position deviance of the samples of a regular light (distributes the light samples in a cube of side length 2*_deviance around the origin), or angle deviance of the sun light samples in radians
--------- SPAWNFLAGS --------
-LINEAR: Use a linear falloff. Default is inverse distance squared (more realistic).
-NOANGLE: Ignore angle attenuation.
-*/
-
-/*QUAKED misc_laser (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON FINITE
-Laser beam emitter. Note that for the laser to be deadly, it has to start OUTSIDE the player's collision box. To ensure this, you may want to put this entity inside the walls (or directly on their surface), or cover it with a playerclip brush.
--------- KEYS --------
-target: target_position the laser targets (may be another entity, preferably target_position, possibly controlled by misc_follow)
-mdl: name of particle effect for the beam end point (see effectinfo.txt; default is laser_deadly if dmg is set, and none if not)
-colormod: color of the laser beam (default: red, that is, 1 0 0)
-dmg: damage inflicted by the beam per second, or -1 for an instant-death ray
-targetname: name to target this (then its state is toggled)
-alpha: when set, makes a dark laser of the given strength; may be combined with colormod
-scale: scales the beam thickness (default 1)
-modelscale: scales the dynamic light radius at the endpoint (default 1, -1 to turn off)
--------- SPAWNFLAGS --------
-START_ON: when targeted, the laser will start switched on
-FINITE: the laser does not extend over its target like light would do, but stops there (takes more bandwidth)
--------- NOTES --------
-Use trigger_monoflop if you want the laser to turn off for a while, then turn back on.
-When the laser's target has itself target set, its targets are triggered when someone enters or leaves the laser.
-*/
-
-/*QUAKED misc_model (1 .5 .25) (-16 -16 -16) (16 16 16) - SOLID - EXTRUDE_NORMALS EXTRUDE_TERRAIN COLOR_TO_ALPHA
-Generic placeholder for inserting MD3 models in game. Requires compilation of map geometry to be added to level. If the map is compiled with Q3Map2, then ASE, 3DS, OBJ and other model formats are supported.
--------- Q3MAP2 KEYS --------
-model: file name of model to include
-_frame: frame of model to include
-_remap: string of the form from;to specifying which texture name of the model to replace by which shader; * is allowed. Any key starting with this prefix will work, so if you need more remappings, create _remap2, etc.
-angle: view direction of the model
-angles: view direction of the model in PITCH YAW ROLL
-modelscale: scaling factor
-modelscale_vec: scaling vector for non-uniform scaling
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_lightmapscale: light map resolution factor
-_celshader: the cel shader for this
--------- SPAWNFLAGS --------
-SOLID: make the model solid
-EXTRUDE_NORMALS: for converting triangles to clip brushes, extrude along the model normals (by default, extrusion happens in a coordinate axis direction that is decided per triangle)
-EXTRUDE_TERRAIN: always extrude downwards (for terrain)
-COLOR_TO_ALPHA: use the color value as alpha (for terrain blending)
-*/
-
-/*QUAKED misc_gamemodel (0 .5 .8) (-8 -8 -8) (8 8 8) ALIGN_ORIGIN ALIGN_BOTTOM
-A way to load models from a map by the engine (e.g. self-animated zym models).
-Is non-solid by default.
-The keys below actually apply to most engine-loaded model entities as they are engine features; however, they are described here as they aren't overridden by game code in misc_gamemodel. Its q3map2 keys below will work on any brush entity!
--------- KEYS --------
-model: when used as a point entity, file name of model to load; when used as a brush entity, do not specify that
-frame: animation frame to play (for self-animated zym models)
-skin: number of skin to load (when model is used)
-movetype: way in which it moves: one of 0 = NONE, 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-solid: solidity: one of 0 = NOT, 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE
-avelocity: vector giving its angular velocity (useful for spinning models)
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-velocity: when movetype isn't 0, initial velocity vector
-angles: initial looking direction
-modelscale: scaling factor
-effects: sum of 1 = BRIGHTFIELD, 4 = BRIGHTLIGHT, 8 = DIMLIGHT, 32 = ADDITIVE, 64 = BLUE, 128 = RED, 512 = FULLBRIGHT, 1024 = FLAME, 2048 = STARDUST, 4096 = NOSHADOW, 8192 = NODEPTHTEST, 32768 = DOUBLESIDED, 8388608 = NOMODELFLAGS (ignores the following coming from a model file), 16777216 = ROCKET, 33554432 = GRENADE, 67108864 = GIB, 134217728 = ROTATE, 268435456 = TRACER, 536870912 = ZOMGIB, 1073741824 = TRACER2, -2147483648 = TRACER3
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature.
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- SPAWNFLAGS --------
-ALIGN_ORIGN: align the origin to the surface below the model
-ALIGN_BOTTOM: align the bottom of the model to the surface below it
-*/
-
-/*QUAKED func_illusionary (0 .5 .8) ?
-NOTE: THIS ENTITY IS BROKEN REGARDING CLIENT AND PROJECTILE PREDICTION. DO NOT USE IT. USE NONSOLID SHADERS OR FUNC_CLIENTILLUSIONARY INSTEAD.
-A non-solid brush entity. Use func_wall if you want it solid.
-The keys below actually apply to most brush entities as they are engine features; however, they are described here as they aren't overridden by game code in misc_models. Its q3map2 keys below will work on any brush entity!
--------- KEYS --------
-movetype: way in which it moves: one of 0 = NONE, 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-avelocity: vector giving its angular velocity (useful for spinning models)
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-velocity: when movetype isn't 0, initial velocity vector
-angles: initial looking direction
-effects: sum of 1 = BRIGHTFIELD, 4 = BRIGHTLIGHT, 8 = DIMLIGHT, 32 = ADDITIVE, 64 = BLUE, 128 = RED, 512 = FULLBRIGHT, 1024 = FLAME, 2048 = STARDUST, 4096 = NOSHADOW, 8192 = NODEPTHTEST, 32768 = DOUBLESIDED, 8388608 = NOMODELFLAGS (ignores the following coming from a model file), 16777216 = ROCKET, 33554432 = GRENADE, 67108864 = GIB, 134217728 = ROTATE, 268435456 = TRACER, 536870912 = ZOMGIB, 1073741824 = TRACER2, -2147483648 = TRACER3
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- Q3MAP2 KEYS --------
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
-_clonename: template name so one can clone from it
-min: override automatically found minimum coordinate bounds
-max: override automatically found maximum coordinate bounds
-targetname: if targeted by a misc_model, its brushes get inserted into this
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
-*/
-
-/*QUAKED func_wall (0 .5 .8) ?
-A solid brush entity. Use func_clientillusionary if you want it non-solid.
-The keys below actually apply to most brush entities as they are engine features; however, they are described here as they aren't overridden by game code in misc_models. Its q3map2 keys below will work on any brush entity!
--------- KEYS --------
-movetype: way in which it moves: one of 0 = NONE, 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-solid: solidity: one of 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE (default: 4, any other value causes prediction problems and should not be used until further notice)
-avelocity: vector giving its angular velocity (useful for spinning models)
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-velocity: when movetype isn't 0, initial velocity vector
-angles: initial looking direction
-effects: sum of 1 = BRIGHTFIELD, 4 = BRIGHTLIGHT, 8 = DIMLIGHT, 32 = ADDITIVE, 64 = BLUE, 128 = RED, 512 = FULLBRIGHT, 1024 = FLAME, 2048 = STARDUST, 4096 = NOSHADOW, 8192 = NODEPTHTEST, 32768 = DOUBLESIDED, 8388608 = NOMODELFLAGS (ignores the following coming from a model file), 16777216 = ROCKET, 33554432 = GRENADE, 67108864 = GIB, 134217728 = ROTATE, 268435456 = TRACER, 536870912 = ZOMGIB, 1073741824 = TRACER2, -2147483648 = TRACER3
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- Q3MAP2 KEYS --------
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
-_clonename: template name so one can clone from it
-min: override automatically found minimum coordinate bounds
-max: override automatically found maximum coordinate bounds
-targetname: if targeted by a misc_model, its brushes get inserted into this
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
-*/
-
-/*QUAKED misc_clientmodel (0 .5 .8) (-8 -8 -8) (8 8 8) ALIGN_ORIGIN ALIGN_BOTTOM
-A way to load models from a map by the engine (e.g. self-animated zym models) on client side.
-Is non-solid by default.
--------- KEYS --------
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-angles: initial looking direction
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
-bgmscript: emitter class from the BGM script (if prefixed with <, movedir is treated as an angle value)
-bgmscriptattack: attack time of the effect strength (0 to 3.9)
-bgmscriptdecay: decay time of the effect strength (0 to 3.9)
-bgmscriptsustain: sustain level of the effect strength (0.1 to 1, set to -1 to disable sustain)
-bgmscriptrelease: release time of the effect strength (0 to 3.9)
-movedir: vector by which the entity moves when "pressed" by the bgmscript
-lip: alpha change when "pressed" by the bgmscript (if > 0, it fades in when pressed, if < 0, it fades out when pressed)
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- SPAWNFLAGS --------
-ALIGN_ORIGN: align the origin to the surface below the model
-ALIGN_BOTTOM: align the bottom of the model to the surface below it
-*/
-
-/*QUAKED func_clientillusionary (0 .5 .8) ?
-A client-side non-solid brush entity. Use func_wall if you want it solid.
--------- KEYS --------
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-angles: initial looking direction
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
-bgmscript: emitter class from the BGM script
-bgmscriptattack: attack time of the effect strength (0 to 3.9)
-bgmscriptdecay: decay time of the effect strength (0 to 3.9)
-bgmscriptsustain: sustain level of the effect strength (0.1 to 1, set to -1 to disable sustain)
-bgmscriptrelease: release time of the effect strength (0 to 3.9)
-movedir: vector by which the entity moves when "pressed" by the bgmscript
-lip: alpha change when "pressed" by the bgmscript (if > 0, it fades in when pressed, if < 0, it fades out when pressed)
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- Q3MAP2 KEYS --------
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
-_clonename: template name so one can clone from it
-min: override automatically found minimum coordinate bounds
-max: override automatically found maximum coordinate bounds
-targetname: if targeted by a misc_model, its brushes get inserted into this
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
-*/
-
-/*QUAKED func_clientwall (0 .5 .8) ?
-NOTE: THIS ENTITY IS IN MOST USE CASES BROKEN REGARDING CLIENT AND PROJECTILE PREDICTION. DO NOT USE IT. USE FUNC_WALL INSTEAD.
-A client-side solid brush entity. Use func_clientillusionary if you want it non-solid.
--------- KEYS --------
-solid: solidity: one of 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE (default: 4, any other value causes prediction problems and should not be used until further notice)
-scale: scale factor of the model (range: 0.0625 to 15.9375)
-colormap: 1024 + 16 * pantscolor + shirtcolor
-angles: initial looking direction
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
-bgmscript: emitter class from the BGM script
-bgmscriptattack: attack time of the effect strength (0 to 3.9)
-bgmscriptdecay: decay time of the effect strength (0 to 3.9)
-bgmscriptsustain: sustain level of the effect strength (0.1 to 1, set to -1 to disable sustain)
-bgmscriptrelease: release time of the effect strength (0 to 3.9)
-movedir: vector by which the entity moves when "pressed" by the bgmscript
-lip: alpha change when "pressed" by the bgmscript (if > 0, it fades in when pressed, if < 0, it fades out when pressed)
-originjitter: a vector describing a random offset this entity will be moved on initial spawn. This corresponds to the "origin" field. Works on any non-q3map2-only entity.
-anglesjitter: a vector in the order "pitch yaw roll" describing a random angles change on this entity on initial spawn. The value 180 180 180 makes the angles entirely random and uniformly distributed (among euler angles). This corresponds to the "angles" field. Works on any non-q3map2-only entity.
-anglejitter: a float describing a random yaw angle change on this entity on initial spawn. The value 180 makes the yaw angle entirely random (maybe good for items). This corresponds to the "angle" field. Works on any non-q3map2-only entity.
-gametypefilter: either a + sign and a comma separated list of game types or the aliases "teams" and "noteams" to ONLY show the entity in the listed game types, or a - sign and a comma separated list of game types or the aliases "teams" and "noteams" to NOT show the entity in the listed game types. The syntax is the same as in sbar_columns_set strings. Works on any non-q3map2-only entity.
--------- Q3MAP2 KEYS --------
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
-_clonename: template name so one can clone from it
-min: override automatically found minimum coordinate bounds
-max: override automatically found maximum coordinate bounds
-targetname: if targeted by a misc_model, its brushes get inserted into this
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
-*/
-
-/*QUAKED misc_teleporter_dest (1 .5 .25) (-16 -16 -24) (16 16 45)
-Teleport destination location point for trigger_teleport entities. Do not let it touch the floor, but place it slightly higher (like, 16 units above) for better flow when jumping through it.
--------- KEYS --------
-targetname: make the trigger_teleporter point to this.
-target: target to activate when a teleporter targeting this is used
-angle: direction in which player will look when teleported, OR use
-angles: pitch and yaw when coming out of the teleporter (also specifies the direction the player will aim when coming out)
-cnt: weight for random selection, in case a teleporter points at multiple misc_teleporter_dest
-speed: maximum speed cap for the teleported player (if -1, teleported players will have no speed)
-*/
-
-/*QUAKED onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
-Control point. Be sure to give this enough clearance so that the shootable part has room to exist
-This should link to an onslaught_controlpoint entity or onslaught_generator entity.
--------- KEYS --------
-targetname: name that onslaught_link entities will use to target this.
-target: target any entities that are tied to this control point, such as vehicles and buildable structure entities.
-message: name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
-*/
-
-/*QUAKED onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
-Base generator.
-
-onslaught_link entities can target this.
--------- KEYS --------
-team: team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
-targetname: name that onslaught_link entities will use to target this.
-*/
-
-/*QUAKED onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
-Link between control points.
-
-This entity targets two different onslaught_controlpoint or onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
--------- KEYS --------
-target: first control point.
-target2: second control point.
-*/
-
-/*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8)
-Path corner entity that func_train will follow.
-All path_corner entities of a train have to connect in a circular manner, while the func_train shall point to one of the path_corners (ideally the one at the train's starting point)
--------- KEYS --------
-target: point to next path_corner in the path.
-targetname: the train following the path or the previous path_corner in the path points to this.
-speed: speed of func_train while moving to this path corner. If unset, the value from the func_train will be used.
-wait: number of seconds func_train will pause on this path corner before moving to next path corner (default: 0.1; to not wait, set this to -1
-*/
-
-/*QUAKED target_assault_roundend (1 0 0) (-8 -8 -8) (8 8 8)
-This entity ends the current assault round if triggered or if the timelimit is reached.
-Ending a round means swapping attacker/defender teams, resetting objectives and rewarding the winning team.
-Every assault map needs this entity. There should only be one per map.
--------- KEYS --------
-targetname: Name to target this entity
-*/
-
-/*QUAKED target_assault_roundstart (.5 0 .5) (-8 -8 -8) (8 8 8)
-This entity triggers its targets whenever a new assault round is started. This can be used to e.g. activate the first objective.
--------- KEYS --------
-target: targetname of entities to be enabled/triggered on round start (e.g. the first target_objective)
-target2: targetname of entities to be enabled/triggered on round start (e.g. the func_assault_destructibles targeting the target_objective)
-target3: targetname of entities to be enabled/triggered on round start
-target4: targetname of entities to be enabled/triggered on round start
-*/
-
-/*QUAKED target_objective (.5 0 .5) (-8 -8 -8) (8 8 8)
-target_objective controls an objective. Once triggered the objective is active and has 100 "health" points. If this "health" falls below zero it is assumed this objective has been fulfilled and entities targeted will be triggered (e.g. to activate the next objective or to end this round). Use target_objective_decrease to decrease the objective health.
--------- KEYS --------
-target: targetname of entities to be enabled/triggered on objective fulfilling (e.g. the next target_objective, or target_assault_roundend)
-target2: targetname of entities to be enabled/triggered on objective fulfilling (e.g. the func_assault_destructibles targeting the target_objective)
-target3: targetname of entities to be enabled/triggered on objective fulfilling
-target4: targetname of entities to be enabled/triggered on objective fulfilling
-targetname: targetname for this entity so it can be triggered by other entities.
-*/
-
-/*QUAKED target_objective_decrease (0 1 0) (-8 -8 -8) (8 8 8)
-When triggered decreases health of the targeted target_objective by the amount specified in dmg. Remember, target_objective has 100 health points and is considered conquered if health falls below zero.
-If you want e.g. two events to happen to conquer an objective you'd need two target_objective_decrease, each with a value for cnt of e.g. 51. To show attackers and defenders where to go, target_objective_decrease will show a fitting sprite ("Defend" to defenders, "Destroy"/"Push" to attackers) which can be seen through walls.
--------- KEYS --------
-target: The targetname of the target_objective you want to manipulate.
-targetname: Name for other entities to target this entity.
-dmg: The amount of "health"-points you want to subtract from the objective health. Defaults to 101. Also used as score for triggering this objective.
-*/
-
-/*QUAKED target_position (0 .5 0) (-8 -8 -8) (8 8 8)
-Aiming target for entities like light and trigger_push.
--------- KEYS --------
-targetname: the entity that requires an aiming direction points to this.
-target: target to activate when a jumppad targeting this is used
-*/
-
-/*QUAKED target_speaker (0 .7 .7) (-8 -8 -8) (8 8 8)
-Sound generating entity that plays sound files.
-If targeted, it plays the sound file every time when triggered.
-If not targeted, it loops the sound file as an ambient noise.
--------- KEYS --------
-noise: path/name of .wav/.ogg file to play
-targetname: the activating button or trigger points to this.
-atten: distance attenuation of the sound (a value from 0.1 to 3.9), default is 0.5 if targeted, 3 otherwise; set to -1 for no attenuation (global sound)
-volume: volume of the sound
-*/
-
-/*QUAKED trigger_counter (.5 .5 .5) ? NOMESSAGE
-Acts as an intermediary for an action that takes multiple inputs.
-After the counter has been triggered "count" times, it will fire all of its targets and remove itself.
--------- KEYS --------
-count: how many times this needs to be triggered to activate its targets
-target: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-delay: delay the triggering by the given time
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
--------- SPAWNFLAGS --------
-NOMESSAGE: don't print a "2 more to go..."-like message when triggered
-*/
-
-/*QUAKED trigger_delay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-Trigger that delays triggering by a given amount of time. Only one action can be waited for; if triggered again before the "wait" time expires, the timer will restart (as opposed to trigger_relay).
--------- KEYS --------
-wait: delay the triggering by the given time
-target: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
-*/
-
-/*QUAKED trigger_hurt (.5 .5 .5) ?
-Any object touching this will be hurt.
-Has the useful effect of automatically returning flags, keys and runes when they touch it.
--------- KEYS --------
-dmg: amount of damage to deal (default: 1000)
-message: kill message when someone gets killed by this (default: "was in the wrong place")
-message2: kill message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-*/
-
-/*QUAKED trigger_impulse (.5 .5 .5) ?
-An accelerator/dampener/wind field.
-Can be used in two ways:
-"dampener field": just set strength to a value from 0 to 1. Entering the field will slow down to this factor.
-"accelerator field": just set strength to a value from 1 to infinity. Entering the field will accelerate by this factor.
-"wind field": set strength to the amount of velocity to add per second, and target a target_position. The field will apply force in the direction from its own origin to the target (use an origin brush to specify its own origin, or this will fail) when touched.
-"gravity field": set strength to the amount of velocity to add per second at the center, and set radius to the radius of the field. Set falloff to the desired falloff characteristics.
--------- KEYS --------
-target: "wind field": points to the target_position to which the player will get pushed.
-strength: "wind field", "gravity field": amount of force per second to apply. "dampener/accelerator field": slowdown/speedup factor.
-falloff: "gravity field": 0 means no falloff, 1 means linear falloff (zero at the outside), 2 means inverted linear falloff (zero at the inside)
-*/
-
-/*QUAKED trigger_multiple (.5 .5 .5) ? NOTOUCH ALLENTS
-Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
--------- KEYS --------
-health: amount of damage that has to be dealt to the trigger to activate (it then won't respond to merely touching it)
-wait: prevent triggering again for this amount of time
-sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav
-noise: path to sound file, if you want to play something else
-target: trigger all entities with this targetname when triggered
-target2: trigger all entities with this targetname when triggered
-target3: trigger all entities with this targetname when triggered
-target4: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-delay: delay the triggering by the given time
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
--------- SPAWNFLAGS --------
-NOTOUCH: the trigger can only be triggered by other entities, not by touching or firing (you should probably use trigger_relay or trigger_delay instead)
-ALLENTS: the trigger responds to all entities, not just players (useful for targetting trigger_items)
-*/
-
-/*QUAKED trigger_once (.5 .5 .5) ? NOTOUCH
-Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
-Basically, it's a use-once trigger_multiple.
--------- KEYS --------
-health: amount of damage that has to be dealt to the trigger to activate (it then won't respond to merely touching it)
-sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav
-noise: path to sound file, if you want to play something else
-target: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-delay: delay the triggering by the given time
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
--------- SPAWNFLAGS --------
-NOTOUCH: the trigger can only be triggered by other entities, not by touching or firing (you should probably use trigger_relay or trigger_delay instead)
-*/
-
-/*QUAKED trigger_push (1 .5 0) ? - - INVERT_TEAM
-Jump pad. What else?
-Can be used in three ways:
-Nexuiz "target/height" way: put the target_position where the player should land, and tune height to get a nice jump path. A good starting value for height is 100.
-Q3A "target" way: put the target_position at the apex of the jump, and hope the player will land at the right spot. Good luck.
-Quake "movedir/speed" way: player will get velocity movedir * speed * 10 when using the jump pad
--------- KEYS --------
-target: point the player will fly to when using the jump pad (use a target_position here)
-height: if height is 0, the (player's origin at the) apex of the jump will be at the target; otherwise, the apex will be abs(height) above the higher point of player's origin and the target; if positive, the apex will be reached in the jump from initial origin to target
-movedir: when target is not set, direction vector to push to
-speed: speed of jump pad (default: 1000)
-noise: sound to play when jump pad is used; default is misc/jumppad.wav; you can set it to "" to make the pad silent
-team: team that owns this jump pad (5 = red, 14 = blue, etc) (when set, only this team can teleport)
-targetname: when targeted by a func_button, pressing the button will reassign the teleporter to the team of the activator.
--------- SPAWNFLAGS --------
-INVERT_TEAM: the team that owns the teleporter will NOT jump when touching this
-*/
-
-/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-This fixed size trigger cannot be touched, it can only be fired by other events. It can, like any other trigger, contain killtargets, targets, delays, and messages.
-One possible use is to trigger entities with more than one targetname on an action, e.g. a button. For this, set target of your button to foobar. Create two trigger_relay with targetname=foobar. Give one of the trigger_relay entities target=ent1, and give the other target=ent2.
-More than one "trigger event" can be delayed at once, as opposed to trigger_delay.
--------- KEYS --------
-target: trigger all entities with this targetname when triggered
-target2: trigger all entities with this targetname when triggered
-target3: trigger all entities with this targetname when triggered
-target4: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-delay: delay the triggering by the given time
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
-*/
-
-/*QUAKED trigger_swamp (.5 .5 .5) ?
-Players getting into the swamp will get slowed down and damaged
--------- KEYS --------
-dmg: damage per interval to deal (default is 5)
-swamp_interval: interval of damage when in swamp (default is 1)
-swamp_slowdown: amount of slowdown caused by the swamp (default is 0.5)
-*/
-
-/*QUAKED trigger_teleport (.5 .5 .5) ? - - INVERT_TEAM
-Touching this will teleport players to the location of the targeted misc_teleporter_dest entity.
-Note that in Nexuiz, teleporters preserve momentum of the player using them.
--------- KEYS --------
-target: this must point to a misc_teleporter_dest entity. If it points to more than one, a destination is randomly selected on teleport.
-team: team that owns this teleporter (5 = red, 14 = blue, etc) (when set, only this team can teleport)
-targetname: when targeted by a func_button, pressing the button will reassign the teleporter to the team of the activator.
--------- SPAWNFLAGS --------
-INVERT_TEAM: the team that owns the teleporter will NOT teleport when touching this
-*/
-
-/*QUAKED worldspawn (0 0 0) ?
-The world.
-If you see this, the currently selected brush is not of an entity.
--------- KEYS --------
-fog: fog parameters of the map (density red green blue alpha mindist maxdist); works just like the "fog" console command
-author: name of the author of the map, if not specified in "message". Will get copied to the "author" entry of the mapinfo file when none is present.
-message: text to print at user logon. Used for name of level. Ideally: "NAMEOFLEVEL by AUTHOR". Will get copied to the "title" and "author" entries of the mapinfo file when none is present.
-_description: one-line description of the map. Will get copied to the "description" entry of the mapinfo file when none is present.
--------- Q3MAP2 KEYS --------
-_blocksize: vector specifying the automatic vis subdivision block size (default: 1024 1024 1024)
-gridsize: lightgrid granularity vector (default: 64 64 128)
-_color: color of the global light parameters
-_ambient: light added to all surfaces
-_mingridlight: minimum grid light
-_minlight: minimum light value on both surfaces and lightgrid
-_keepLights: do not remove light entities from the map (useful e.g. for realtime lighting)
-_floodlight: flood light parameters (red green blue distance intensity), start with 240 240 255 1024 128
-_farplanedist: range after which everything is completely invisible by fog (when fog is being used)
-_noshadersun: turn off sun defined by shaders (useful if you defined your own light entity to be a sun)
-_ignoreleaks: ignore leaks when compiling
-_lightmapscale: light map resolution factor
-_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting.1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
-_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
-_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
-*/
-
-/*QUAKED trigger_race_checkpoint (0 1 0) ? NOTOUCH STRICTTRIGGER CRUSH FINISH
-A checkpoint, for the race game mode. Be sure to make them quite long, so they actually catch a player reliably!
--------- KEYS --------
-cnt: Number of the checkpoint. 0 for start/finish line, and at least two other checkpoints have to exist. They MUST be touched in sequential order!
-message: Death message, when touching checkpoints in the wrong order.
-message2: Death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-targetname: Name of the checkpoint. info_player_race can target this to assign a spawn to a checkpoint. Also used for triggering a checkpoint by an event.
-target: when the checkpoint is passed, these entities are triggered. Useful for forcing items in certain areas using trigger_items
-race_penalty: when set, this penalty time is given if passing this checkpoint, and the checkpoint does not show up with a sprite. Useful for invisible checkpoints to detect driving around the intended checkpoint
-race_penalty_reason: reason to display when the penalty time is imposed. Default: "missing a checkpoint"
--------- SPAWNFLAGS --------
-NOTOUCH: the checkpoint will not become active when touched, it HAS to be targeted
-STRICTTRIGGER: only trigger the targets when the checkpoint actually was reached in a valid way (that is, not when going back)
-CRUSH: the checkpoint kills when used at the wrong time
-FINISH: when set on the last checkpoint (i.e. the one with highest cnt), it is marked as finish line and the CP with cnt=0 is the start line
-*/
-
-/*QUAKED trigger_race_penalty (0 1 0) ? NOTOUCH
-A penalty trigger.
--------- KEYS --------
-race_penalty: this penalty time is given if passing this trigger
-race_penalty_reason: reason to display when the penalty time is imposed. Default: "leaving the track"
--------- SPAWNFLAGS --------
-NOTOUCH: the trigger will not become active when touched, it HAS to be targeted
-*/
-
-/*QUAKED info_player_race (1 0.5 0) (-16 -16 -24) (16 16 45)
-Race spawn point.
-NOTE for race_place: when the race starts after the qualifying, the player with the fastest map ends up at the info_player_race with race_place 1, and so on. If there are too many players, or if someone comes in later, he will spawn at an info_player_race with race_place not set. So for each trigger_race_checkpoint, there must be at least one corresponding info_player_race with race_place NOT set.
--------- KEYS --------
-target: this should point to a trigger_race_checkpoint to decide when this spawning point is active. The checkpoint has to be AFTER this spawn.
-target2: trigger all entities with this targetname when someone spawns
-cnt: weight of spawn point for random selection. Set to a lower value if you have many spawn points close together. Default value is 1.
-race_place: if target points to the trigger_race_checkpoint with cnt 0 (finish line), this sets which place the spawn corresponds to; the special value 0 stands for spawns for players who come in later (have to be behind the ones with race_place set to an actual place), and -1 marks the spawnpoint for qualifying mode only; any race map must have spawnpoints with race_place being 1, 2, 3 or it gets marked as a frustrating map
-restriction: when 1, only bots can spawn here; when 2, only humans can spawn here (be careful with these, or the game will crash because someone cannot spawn)
-*/
-
-/*QUAKED func_pointparticles (.5 .5 .5) ? START_ON IMPULSE
-A brush that emits particles.
--------- KEYS --------
-mdl: particle effect name from effectinfo.txt
-impulse: when positive, number of particles to emit per second; when negative; number of particles to emit per second and 64^3 block
-velocity: particle direction and speed
-waterlevel: extra velocity jitter amount
-count: particle count multiplier (per spawned particle)
-movedir: when set, trace direction (particles will then be emitted from the surface the trace hits); the length of the vector is used as strength of taking the normal of the trace into account
-noise: sound to play when the particle is emitted
-atten: distance attenuation of the sound (a value from 0.1 to 3.9), default is 0.5; set to -1 for no attenuation (global sound)
-volume: volume of the sound
-targetname: name to target this (then its state is toggled)
-bgmscript: emitter class from the BGM script
-bgmscriptattack: attack time of the effect strength (0 to 3.9)
-bgmscriptdecay: decay time of the effect strength (0 to 3.9)
-bgmscriptsustain: sustain level of the effect strength (0.1 to 1, set to -1 to disable sustain)
-bgmscriptrelease: release time of the effect strength (0 to 3.9)
--------- SPAWNFLAGS --------
-START_ON: when targeted, the particle emitter will start switched on
-IMPULSE: only send the full amount of impulse particles when the entity is triggered
--------- NOTES --------
-Use trigger_monoflop if you want the particles to turn off for a while, then turn back on.
-A BGM script is a .bgs file named like the map, in the maps directory. Its format is lines of the form
- <emitter class> <time since start of background music> <0 if the emitters are to be switched off, >0 and <=1 if they are to be switched on>
-e.g.
- smokers 4.7 1
- smokers 4.9 0
-The lines MUST be sorted by emitter class as primary key, and by the time since start of the BGM as secondary key.
-*/
-
-/*QUAKED trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
-"Flip-flop" trigger gate... lets only every second trigger event through
--------- KEYS --------
-target: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
--------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (so the first event is NOT passed through)
-*/
-
-/*QUAKED trigger_monoflop (.5 .5 .5) (-8 -8 -8) (8 8 8) FIXED
-"Mono-flop" trigger gate... turns trigger events into pairs of events
--------- KEYS --------
-target: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-wait: time to wait until the "off" event is fired
--------- SPAWNFLAGS --------
-FIXED: do pulses of fixed length (so the "off" delay is NOT extended as usual and new events are just ignored)
-*/
-
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
-"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
--------- KEYS --------
-target: trigger all entities with this targetname when it goes off
-targetname: name that identifies this entity so it can be triggered
-phase: phase of the multivibrator (it is added to the time)
-wait: "on" cycle time (default: 1)
-respawntime: "off" cycle time (default: same as wait)
--------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
-*/
-
-/*QUAKED trigger_gamestart (.5 .5 .5) (-8 -8 -8) (8 8 8)
-Triggers once when the game starts, then no longer does anything.
--------- KEYS --------
-target: trigger all entities with this targetname when starting the game
-target2: trigger all entities with this targetname when starting the game
-target3: trigger all entities with this targetname when starting the game
-target4: trigger all entities with this targetname when starting the game
-wait: wait so many seconds before triggering
-*/
-
-/*QUAKED misc_follow (.5 .5 .5) (-8 -8 -8) (8 8 8) ATTACH LOCAL
-Makes one entity follow another. Will not work with all entities.
--------- KEYS --------
-target: points to the entity to move (e.g. something that won't move by itself)
-killtarget: points to the entity that is to be used as the source (e.g. a func_plat)
-message: tag name to attach to (if ATTACH is used)
-punchangle: angle modifier (if LOCAL is used, and ATTACH is not)
--------- SPAWNFLAGS --------
-ATTACH: attachment will be used instead of MOVETYPE_FOLLOW (mostly useful for attaching stuff to ZYM models)
-LOCAL: do not untransform the coordinates (that is, the map specifies local coordinates, not global ones). Mostly useful with ATTACH.
-*/
-
-/*QUAKED target_items (0 0 1) (-8 -8 -8) (8 8 8) AND OR ANDNOT
-Sets the items of any player who triggers this.
-For the number fields, not specifying a value means not changing it. To clear armor, you need to explicitly set "armor" to "-1".
-You may want to target this by a race checkpoint, a teleporter, or a trigger_multiple with ALLENTS set (so it removes weapons thrown through the field to avoid getting a weapon through it).
--------- KEYS --------
-targetname: used to trigger this
-netname: space separated list of items (either weapon short names (like in g_start_weapon_* cvars), or item short names "unlimited_ammo", "unlimited_weapon_ammo", "unlimited_superweapons", "invincible", "strength", "jetpack" and "fuel_regen"
-message: message to print
-ammo_fuel: amount of fuel
-health: amount of health
-armorvalue: amount of armor (note that armor is NOT supported in Vore Tournament by default)
-strength_finished: if "strength" is specified, the time in seconds for which the strength will hold
-invincible_finished: if "invincible" is specified, the time in seconds for which the invincibility will hold
--------- SPAWNFLAGS --------
-AND: any items not listed will get removed, and none will get added
-OR: the player may keep items not listed
-ANDNOT: the items listed will get removed from the player
-*/
-
-/*QUAKED target_spawn (1 0 1) (-8 -8 -8) (8 8 8) - ONLOAD
-Spawns or modifies an entity when triggered.
-The entity field list is a single string of the form:
-'field' 'value' 'field' 'value' ... 'classname' 'item_bullets' ... 'field' 'value'
-The special "field" name $ calls a void(void) function, for example a spawn function.
-Special function names available are _setmodel and _setsize.
-Field values can use various variable replacements:
-$E
-$E.field
-$E.field+offset
-$E.field+offset+randomoffset
-where "E" can be self, activator, target (the entity being created/modified), killtarget, target2, target3, target4 and pusher.
-Example is a Mario-style question mark block which could throw a new weapon_nex when activated like this:
-{
-"classname" "func_button"
-"angle" "-1"
-"wait" "5"
-"target" "makenex"
-"speed" "1000"
-"lip" "64"
-...
-}
-{
-"classname" "target_spawn"
-"origin" "0 0 448"
-"targetname" "makenex"
-"message" "origin $self.origin owner $activator flags 65536 colormap $activator.colormap classname droppedweapon $ spawnfunc_weapon_nex think thrown_wep_think nextthink $time+0.5 velocity $activator.velocity velocity_z 512 movetype 3"
-}
--------- KEYS --------
-targetname: used to trigger this
-message: entity field list
-target: when set, target_spawn edits entities, instead of creating new ones
-count: make sure no more than count entities have been created by this (refuse to spawn new ones if exceeded)
-killtarget: reference entity (can be used as $killtarget)
-target2: reference entity (can be used as $target2)
-target3: reference entity (can be used as $target3)
-target4: reference entity (can be used as $target4)
--------- SPAWNFLAGS --------
-ONLOAD: create a first entity on map load
-*/
-
-/*QUAKED func_breakable (1 0 0) ? DISABLED INDICATE
-This is a brush model which can be damaged.
-Once all health is consumed it'll disappear and trigger the targeted entity/entities.
-When triggered, it resets to full health, and unbreaks.
--------- KEYS --------
-health: The damage this trigger can take
-target: The entity/entities to be triggered once this entity gets invisible
-targetname: The name other entities can use to target this entity
-mdl: particle effect name to show when destroyed
-count: particle effect multiplier
-mdl_dead: optional replacement model to show when destroyed
-debris: names of debris models to show when destroyed, separated by spaces
-noise: sound to play when destroyed
-dmg: damage to deal to the environment when destroyed
-dmg_edge: edge damage to deal to the environment when destroyed
-dmg_radius: damage radius
-dmg_force: damage force
-message: death message when a player gets hit by the explosion
-message2: death message when someone gets pushed into this (default: "was pushed into an explosion by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-debrismovetype: way in which the debris moves: one of 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-debrissolid: solidity of the debris: one of 0 = NOT, 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE
-debrisvelocity: initial velocity vector of the debris (static part)
-debrisvelocityjitter: initial velocity vector of the debris (random part)
-debrisavelocityjitter: initial angular velocity vector of the debris (random part)
-debristime: time till the debris fades (average)
-debristimejitter: time till the debris fades (random part)
-debrisfadetime: how long debris takes to fade
-debrisdamageforcescale: how much debris is affected by damage force (e.g. explosions)
-debrisskin: skin number of debris
--------- SPAWNFLAGS --------
-DISABLED: do not allow damaging this until it is first activated
-INDICATE: indicate amount of damage already taken by coloring
-*/
-
-/*QUAKED trigger_relay_if (0 1 0) (-8 -8 -8) (8 8 8) NEGATE
-Relays the trigger event if a cvar is set to a specified value.
--------- KEYS --------
-target: The entity/entities to relay the trigger events to
-targetname: The name other entities can use to target this entity
-netname: The name of the cvar to check
-message: The value of the cvar to check
-count: The count of entities that must be found
--------- SPAWNFLAGS --------
-NEGATE: trigger if the cvar does NOT match the value.
-*/
-
-/*QUAKED weapon_grabber (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
-the Grabber.
--------- KEYS --------
-ammo_fuel: initial fuel of the weapon (if unset, g_pickup_fuel is used)
-respawntime: time till it respawns (default: 30)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/weapons/g_grabber.md3"
-*/
-
-/*QUAKED trigger_heal (.5 .5 .5) ?
-Any object touching this will be healed.
--------- KEYS --------
-health: health to give per second (default 10)
-max_health: max health this trigger will give (default 200)
-noise: sound file to play (use misc/null.wav to make it silent), default = item_health_medium sound
-*/
-
-/*QUAKED func_fourier (0 .5 .8) ?
-Solid entity that oscillates according to a sum of sine waves.
--------- KEYS --------
-speed: amount of time in seconds for one complete oscillation cycle in the base frequency (default 4).
-height: sets the amount of travel of the oscillation movement (default 32).
-phase: sets the start offset of the oscillation cycle. Values must be 0 < phase < 1. Any integer phase value is the same as no offset (default 0).
-noise: path/name of .wav or .ogg file to play. Use looping sounds only (e.g. sound/world/drone6.wav - See Notes).
-dmg: damage a player who gets crushed by it receives
-dmgtime: interval to apply dmg to a player who is s in the way
-message: death message when a player gets crushed
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
-netname: list of <frequencymultiplier> <phase> <x> <y> <z> quadruples, separated by spaces; note that phase 0 represents a sine wave, and phase 0.25 a cosine wave (by default, it uses 1 0 0 0 1, to match func_bobbing's defaults
-*/
-
-/*QUAKED func_vectormamamam (0 .5 .8) ? PROJECT_ON_TARGETNORMAL TARGET2NORMAL_IS_DIRECTION TARGET3NORMAL_IS_DIRECTION TARGET4NORMAL_IS_DIRECTION
-Solid entity that moves according to the movement of multiple given entities (max 4)
--------- KEYS --------
-target: first reference entity
-targetfactor: factor by which to take the first reference entity (default 1).
-targetnormal: if set, the first reference entity's location is first projected onto a plane with that normal
-target2: second reference entity
-target2factor: factor by which to take the second reference entity (default 1).
-target2normal: if set, the second reference entity's location is first projected onto a plane with that normal
-target3: third reference entity (optional)
-target3factor: factor by which to take the third reference entity (default 1).
-target3normal: if set, the third reference entity's location is first projected onto a plane with that normal
-target4: fourth reference entity (optional)
-target4factor: factor by which to take the fourth reference entity (default 1).
-target4normal: if set, the fourth reference entity's location is first projected onto a plane with that normal
-noise: path/name of .wav or .ogg file to play. Use looping sounds only (e.g. sound/world/drone6.wav - See Notes).
-dmg: damage a player who gets crushed by it receives
-dmgtime: interval to apply dmg to a player who is s in the way
-message: death message when a player gets crushed
-message2: death message when someone gets pushed into this (default: "was thrown into a world of hurt by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end)
--------- SPAWNFLAGS --------
-PROJECT_ON_TARGETNORMAL: target's origin is projected onto the given direction vector, not on the plane perpendicular to it
-PROJECT_ON_TARGET2NORMAL: target2's origin is projected onto the given direction vector, not on the plane perpendicular to it
-PROJECT_ON_TARGET3NORMAL: target3's origin is projected onto the given direction vector, not on the plane perpendicular to it
-PROJECT_ON_TARGET4NORMAL: target4's origin is projected onto the given direction vector, not on the plane perpendicular to it
-*/
-
-/*QUAKED trigger_relay_teamcheck (.5 .5 .5) (-8 -8 -8) (8 8 8) NOTEAM_TOO INVERT
-Works similar to trigger_relay, but only relays trigger events if the team of the activator matches this entity's team
--------- KEYS --------
-target: trigger all entities with this targetname when triggered
-target2: trigger all entities with this targetname when triggered
-target3: trigger all entities with this targetname when triggered
-target4: trigger all entities with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-delay: delay the triggering by the given time
-message: print this message to the player who activated the trigger
-killtarget: remove all entities with this targetname when triggered
-team: 5 for red, 14 for blue, 13 for yellow, 10 for pink team
--------- SPAWNFLAGS --------
-NOTEAM_TOO: also relay events if the activator has no team set
-INVERT: only relay the event if this entity has the matching team
-*/
-
-/*QUAKED trigger_disablerelay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-Disables a trigger_relay temporarily (until triggered again)
--------- KEYS --------
-target: disable/enable all relays with this targetname when triggered
-targetname: name that identifies this entity so it can be triggered
-*/
-
-/*QUAKED item_fuel (.3 .3 1) (-30 -30 0) (30 30 32) FLOATING
-Jetpack fuel
--------- KEYS --------
-ammo_fuel: fuel units gained by this item (if unset, g_pickup_fuel is used)
-respawntime: time till it respawns (default: 15)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_fuel.md3"
-*/
-
-/*QUAKED item_fuel_regen (1 .3 1) (-30 -30 0) (30 30 48) FLOATING
-Fuel regenerator
--------- KEYS --------
-respawntime: time till it respawns (default: 120)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_fuelregen.md3"
-*/
-
-/*QUAKED item_jetpack (.3 .3 1) (-30 -30 0) (30 30 48) FLOATING
-Jetpack
--------- KEYS --------
-ammo_fuel: fuel units gained by this item (if unset, g_pickup_fuel_jetpack is used)
-respawntime: time till it respawns (default: 120)
-team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/items/g_jetpack.md3"
-*/
-
-/*QUAKED trigger_warpzone (1 .5 1) ?
-A warp zone, i.e. seamlessly connecting two parts of the map.
-One surface of this entity must have the common/warpzone shader (or a similar selfmade shader) - this will be the warp plane - the others must be common/trigger.
-Must target, or be targeted by, another trigger_warpzone with a congruent common/warpzone surface.
-Should target a target_position, or be targeted by a misc_warpzone_position.
-Should be thick enough to fit a player entity (i.e. 32 units), preferably even thicker.
--------- KEYS --------
-target: must point to another trigger_warpzone, or...
-targetname: must be pointed to by another trigger_warpzone. Should be pointed to by a misc_warpzone_position entity, or...
-killtarget: should point to a target_position entity, or
-*/
-
-/*QUAKED trigger_warpzone_reconnect (1 .5 1) (-8 -8 -8) (8 8 8)
-Reconnects (randomly) all warpzones with matching target when triggered
--------- KEYS --------
-target: must point to multiple trigger_warpzones, or be not set (then all warpzones may get changed)
-targetname: name that identifies this entity so it can be triggered
-*/
-
-/*QUAKED misc_warpzone_position (1 .5 .25) (-8 -8 -8) (8 8 8)
-Orientation specification for a trigger_warpzone
--------- KEYS --------
-target: must point to a trigger_warpzone
-angles: must point perpendicular to the common/warpzone surface of the trigger_warpzone, and away from the trigger brush
-origin: must be on the common/warpzone surface of the trigger_warpzone
-*/
-
-/*QUAKED func_camera (1 .5 1) ?
-A camera, i.e. a surface that shows a view from another part of the map.
-One surface of this entity must have the common/camera shader, the others should be common/caulk.
-Must target a target_position that indicates the view to be shown (and whose angles also indicate the orientation of the view)
--------- KEYS --------
-target: must point to a target_position
-*/
-
-/*QUAKED target_music (1 0 0) (-8 -8 -8) (8 8 8)
-Background music target (when this is used, the cdtrack line in mapinfo must not be used, and there MUST be a default target_music).
-When triggered, the background music is switched to the given track.
-When targetname is not set, this is the default track of the map.
--------- KEYS --------
-targetname: The name other entities can use to target this entity (when not set, this one is the default)
-noise: the music to play (as full sound file name)
-volume: the volume (default: 1)
-fade_time: fade-in time
-fade_rate: fade-out time
-lifetime: when set, the music created by this target is switched back to the default one when this time expires
--------- SPAWNFLAGS --------
-START_OFF: the trigger is off initially
-*/
-
-/*QUAKED trigger_music (1 0 0) ?
-Background music trigger (when this is used, the cdtrack line in mapinfo must not be used, and there MUST be a default target_music).
-When triggered, its effect is turned off until triggered again.
--------- KEYS --------
-targetname: The name other entities can use to target this entity
-noise: the music to play (as full sound file name)
-volume: the volume (default: 1)
-fade_time: fade-in time
-fade_rate: fade-out time
--------- SPAWNFLAGS --------
-START_OFF: the trigger is off initially
-*/
-
-/*QUAKED target_changelevel (.5 .5 0) (-8 -8 -8) (8 8 8)
-Loads another map when triggered. Useful for RPG and single player maps.
-When no chmap key is set, the entity just ends the match when triggered. The player / team with the highest score at that moment wins.
--------- KEYS --------
-targetname: The name other entities can use to target this entity
-chmap: Map file to switch to, leave empty to make this entity just end the match
-gametype: Switch to this gametype. If empty, the same gametype stays
-*/
\ No newline at end of file
+++ /dev/null
-/*QUAKED turret_tesla (1 0 0) (-32 -32 0) (32 32 50)\r
-Fires a lightning bolt that will jump to up to 10 targets if they are close enough to each other. Missiles included.\r
--------- KEYS --------\r
-turret_scale_damage: 2 = double damage, 0.5 = half\r
-turret_scale_range: 2 = double range, 0.5 = half\r
-turret_scale_refire: 2 = double refire (SLOWER!), 0.5 = half (FASTER!)\r
-turret_scale_ammo: 2 = double ammo carry & regen, 0.5 = half ammo carry & regen\r
-turret_scale_aim: 2 = aim twice as fast, 0,5 = aim at half speed\r
-turret_scale_health: 2 = double health, 0.5 = half\r
-master_name: This turret controls what all turrets with master_nameof set to this aim at\r
-master_nameof: Dont select own targets, use the target of the turret with this master_name\r
-target: Defend the position of this entity\r
-team: 5=red, 14=blue\r
--------- SPAWNFLAGS --------\r
-PILLAR: Adds a supporting pillar under this turret, for turrets on terrain/uneven surfaces. (only for visuals)\r
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------\r
-model="models/turrets/radiant/tesla.md3"\r
-*/\r
-\r
-/*QUAKED turret_phaser (1 0 0) (-32 -32 0) (32 32 50)\r
-Constant beam weapon that will considerably slow its target down while dealing low but constant damage.\r
--------- KEYS --------\r
-turret_scale_damage: 2 = double damage, 0.5 = half\r
-turret_scale_range: 2 = double range, 0.5 = half\r
-turret_scale_refire: 2 = double refire (SLOWER!), 0.5 = half (FASTER!)\r
-turret_scale_ammo: 2 = double ammo carry & regen, 0.5 = half ammo carry & regen\r
-turret_scale_aim: 2 = aim twice as fast, 0,5 = aim at half speed\r
-turret_scale_health: 2 = double health, 0.5 = half\r
-master_name: This turret controls what all turrets with master_nameof set to this aim at\r
-master_nameof: Dont select own targets, use the target of the turret with this master_name\r
-target: Defend the position of this entity\r
-team: 5=red, 14=blue\r
--------- SPAWNFLAGS --------\r
-PILLAR: Adds a supporting pillar under this turret, for turrets on terrain/uneven surfaces. (only for visuals)\r
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------\r
-model="models/turrets/radiant/phaser.md3"\r
-*/\r
-\r
-/*QUAKED turret_fusionreactor (1 0 0) (-32 -32 0) (32 32 50)\r
--------- KEYS --------\r
-turret_scale_damage: 2 = double damage, 0.5 = half\r
-turret_scale_range: 2 = double range, 0.5 = half\r
-turret_scale_refire: 2 = double refire (SLOWER!), 0.5 = half (FASTER!)\r
-turret_scale_ammo: 2 = double ammo carry & regen, 0.5 = half ammo carry & regen\r
-turret_scale_aim: 2 = aim twice as fast, 0,5 = aim at half speed\r
-turret_scale_health: 2 = double health, 0.5 = half\r
-team: 5=red, 14=blue\r
--------- SPAWNFLAGS --------\r
-PILLAR: Adds a supporting pillar under this turret, for turrets on terrain/uneven surfaces. (only for visuals)\r
----------NOTES----------\r
-Supplies neerby energy based turrets with more power so they can fire more often.\r
--------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------\r
-model="models/turrets/radiant/reactor.md3"\r
-*/\r
+++ /dev/null
-<?xml version="1.0"?>
-<!--
-build commands
-[RadiantPath]: path to Radiant .. C:\Program Files\Gtkradiant
-[EnginePath]: path to the engine .. C:\quake3\ C:\Program Files\Quake III Arena\ /usr/local/games/quake3/
--->
-<project version="2.0">
-<var name="q3map2">"[RadiantPath]q3map2.[ExecutableType]" -v<cond value="[MonitorAddress]"> -connect [MonitorAddress]</cond> -game voretournament -fs_basepath "[EnginePath]"<cond value="[GameName]"> -fs_game [GameName]</cond></var>
-<build name="Q3Map2: (single) BSP">
-<command>[q3map2] -meta "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (single) -vis">
-<command>[q3map2] -vis "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (single) -light, low quality">
-<command>[q3map2] -light -deluxe -cheapgrid -faster "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (single) -light, medium quality">
-<command>[q3map2] -light -deluxe -fast "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (single) -light, high quality">
-<command>[q3map2] -light -deluxe -fast -samples 3 "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (single) -minimap">
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (rebuild only entitys) ">
-<command>[q3map2] -onlyents "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (test)">
-<command>[q3map2] -meta -v -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -samples 3 "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (test) fast vis, fast light">
-<command>[q3map2] -meta -v -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt -fast "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -faster -cheapgrid -filter "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (test) fast vis, good light">
-<command>[q3map2] -meta -v -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt -fast "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -samples 2 "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (final) simple lighting">
-<command>[q3map2] -meta -v -samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -patchshadows -samples 2 "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (final) long distance lighting">
-<command>[q3map2] -meta -v -samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -patchshadows -samples 3 "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (final) + radiosity">
-<command>[q3map2] -meta -v -samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -patchshadows -samples 3 -bounce 8 -fastbounce -bouncegrid "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (final) + highres external lightmaps">
-<command>[q3map2] -meta -v -samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -patchshadows -samples 3 -lightmapsize 512 -bounce 8 -fastbounce -bouncegrid "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-<build name="Q3Map2: (final) + ambient occlusion (VoreTournament default)">
-<command>[q3map2] -meta -v -samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000 "[MapFile]"</command>
-<command>[q3map2] -vis -saveprt "[MapFile]"</command>
-<command>[q3map2] -light -deluxe -fast -patchshadows -samples 3 -lightmapsize 512 -bounce 8 -fastbounce -bouncegrid -dirty -dirtscale 2 "[MapFile]"</command>
-<command>[q3map2] -minimap "[MapFile]"</command>
-</build>
-</project>
-
+++ /dev/null
-<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
-<!-- generated by Radiant setup, modify at your own risks -->
-<links>
-<item name="Vore Tournament" url="http://sourceforge.net/projects/voretournament/"/>
-</links>
--- /dev/null
+cat darkplaces-linux32-glx darkplaces.zip > voretournament-linux32-glx\r
+cat darkplaces-linux32-sdl darkplaces.zip > voretournament-linux32-sdl\r
+cat darkplaces-linux32-dedicated darkplaces.zip > voretournament-linux32-dedicated\r
+cat darkplaces-linux64-glx darkplaces.zip > voretournament-linux64-glx\r
+cat darkplaces-linux64-sdl darkplaces.zip > voretournament-linux64-sdl\r
+cat darkplaces-linux64-dedicated darkplaces.zip > voretournament-linux64-dedicated\r
--- /dev/null
+cat darkplaces.exe darkplaces.zip > voretournament.exe\r
+cat darkplaces-sdl.exe darkplaces.zip > voretournament-sdl.exe\r
+cat darkplaces-dedicated.exe darkplaces.zip > voretournament-dedicated.exe\r
+cat darkplaces-x64.exe darkplaces.zip > voretournament-x64.exe\r
+cat darkplaces-x64-sdl.exe darkplaces.zip > voretournament-x64-sdl.exe\r
+cat darkplaces-x64-dedicated.exe darkplaces.zip > voretournament-x64-dedicated.exe
\ No newline at end of file
yuv_buffer *yuv;
int x, y;
int blockr, blockg, blockb;
- unsigned char *b = cls.capturevideo.outbuffer;
+ unsigned char *b;
int w = cls.capturevideo.width;
int h = cls.capturevideo.height;
int inpitch = w*4;
float maxfrac, maxrealfrac;
int n;
entity_render_t *ent;
- float tracemins[3], tracemaxs[3];
+ vec_t tracemins[3], tracemaxs[3];
trace_t trace;
- float tempnormal[3], starttransformed[3], endtransformed[3];
+ vec_t tempnormal[3], starttransformed[3], endtransformed[3];
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
vec3_t end;
vec_t len = 0;
}
}
maxfrac = bound(0, maxfrac, 1);
- maxrealfrac = bound(0, maxrealfrac, 1);
+ //maxrealfrac = bound(0, maxrealfrac, 1);
//if (maxfrac < 0 || maxfrac > 1) Con_Printf("fraction out of bounds %f %s:%d\n", maxfrac, __FILE__, __LINE__);
if (impact)
VectorLerp(start, maxfrac, end, impact);
VectorCopy(mins, PRVM_clientedictvector(ent, absmin));
VectorCopy(maxs, PRVM_clientedictvector(ent, absmax));
- World_LinkEdict(&cl.world, ent, PRVM_clientedictvector(ent, absmin), PRVM_clientedictvector(ent, absmax));
+ World_LinkEdict(&cl.world, ent, mins, maxs);
}
int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
int passedictprog;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may need conversion
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size when clipping against monsters
else
Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
if ((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
else
- Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+ Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
*hitnetworkentity = 0;
int passedictprog;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may need conversion
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size when clipping against monsters
else
Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
if (type == MOVE_MISSILE && (int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, hitsurfaces);
+ Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, hitsurfaces);
if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
*hitnetworkentity = 0;
qboolean pointtrace;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may need conversion
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size of the moving object
else
Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
if ((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
*hitnetworkentity = 0;
#include "quakedef.h"
extern cvar_t cl_capturevideo;
+extern cvar_t cl_capturevideo_demo_stop;
int old_vsync = 0;
static void CL_FinishTimeDemo (void);
// LordHavoc: now called only by CL_Disconnect
void CL_StopPlayback (void)
{
+ if (cl_capturevideo_demo_stop.integer)
+ Cvar_Set("cl_capturevideo", "0");
+
if (!cls.demoplayback)
return;
{
// digital direction, analog amount
vec_t wishvel_x, wishvel_y;
- f *= max(cl_sidespeed.value, max(cl_forwardspeed.value, cl_backspeed.value));
wishvel_x = fabs(cl.cmd.forwardmove);
wishvel_y = fabs(cl.cmd.sidemove);
if(wishvel_x != 0 && wishvel_y != 0 && wishvel_x != wishvel_y)
else
{
cl.moveflags = 0;
- cl.movevars_ticrate = slowmo.value / bound(1.0f, cl_netfps.value, 1000.0f);
- cl.movevars_timescale = slowmo.value;
+ cl.movevars_ticrate = (cls.demoplayback ? 1.0f : slowmo.value) / bound(1.0f, cl_netfps.value, 1000.0f);
+ cl.movevars_timescale = (cls.demoplayback ? 1.0f : slowmo.value);
cl.movevars_gravity = sv_gravity.value;
cl.movevars_stopspeed = cl_movement_stopspeed.value;
cl.movevars_maxspeed = cl_movement_maxspeed.value;
// update the inverse matrix for the renderer
Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
// update the animation blend state
- VM_FrameBlendFromFrameGroupBlend(ent->frameblend, ent->framegroupblend, ent->model);
+ VM_FrameBlendFromFrameGroupBlend(ent->frameblend, ent->framegroupblend, ent->model, cl.time);
// we need the matrix origin to center the box
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
// update entity->render.scale because the renderer needs it
const matrix4x4_t *matrix;
matrix4x4_t blendmatrix, tempmatrix, matrix2;
int frame;
- float origin[3], angles[3], lerp;
+ vec_t origin[3], angles[3], lerp;
entity_t *t;
entity_render_t *r;
//entity_persistent_t *p = &e->persistent;
if ((e->state_current.lightpflags & PFLAGS_FULLDYNAMIC) && r_refdef.scene.numlights < MAX_DLIGHTS)
{
matrix4x4_t dlightmatrix;
- float light[4];
+ vec4_t light;
VectorScale(e->state_current.light, (1.0f / 256.0f), light);
light[3] = e->state_current.light[3];
if (light[0] == 0 && light[1] == 0 && light[2] == 0)
e->render.flags |= RENDER_SHADOW;
VectorSet(e->render.colormod, 1, 1, 1);
VectorSet(e->render.glowmod, 1, 1, 1);
- VM_FrameBlendFromFrameGroupBlend(e->render.frameblend, e->render.framegroupblend, e->render.model);
+ VM_FrameBlendFromFrameGroupBlend(e->render.frameblend, e->render.framegroupblend, e->render.model, cl.time);
e->render.allowdecals = true;
CL_UpdateRenderEntity(&e->render);
r_refdef.scene.entities[r_refdef.scene.numentities++] = &e->render;
{
Con_Printf("Downloaded \"%s\" (%i bytes, %i CRC)\n", name, size, crc);
FS_WriteFile(name, cls.qw_downloadmemory, cls.qw_downloadmemorycursize);
+ if(!strcmp(cls.qw_downloadname, csqc_progname.string))
+ {
+ if(cls.caughtcsprogsdata)
+ Mem_Free(cls.caughtcsprogsdata);
+ cls.caughtcsprogsdata = (unsigned char *) Mem_Alloc(cls.permanentmempool, cls.qw_downloadmemorycursize);
+ memcpy(cls.caughtcsprogsdata, cls.qw_downloadmemory, cls.qw_downloadmemorycursize);
+ cls.caughtcsprogsdatasize = cls.qw_downloadmemorycursize;
+ Con_DPrintf("Buffered \"%s\"\n", name);
+ }
}
}
}
cl.stats[STAT_NAILS] = MSG_ReadByte(&cl_message);
cl.stats[STAT_ROCKETS] = MSG_ReadByte(&cl_message);
cl.stats[STAT_CELLS] = MSG_ReadByte(&cl_message);
- if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || gamemode == GAME_NEXUIZ)
cl.stats[STAT_ACTIVEWEAPON] = (1<<MSG_ReadByte(&cl_message));
else
cl.stats[STAT_ACTIVEWEAPON] = MSG_ReadByte(&cl_message);
break;
case qw_svc_chokecount:
- i = MSG_ReadByte(&cl_message);
+ (void) MSG_ReadByte(&cl_message);
// FIXME: apply to netgraph
//for (j = 0;j < i;j++)
// cl.frames[(cls.netcon->qw.incoming_acknowledged-1-j)&QW_UPDATE_MASK].receivedtime = -2;
"SVC_PARTICLE"
};
-static void CL_Particles_LoadEffectInfo(void)
+static void CL_Particles_LoadEffectInfo(const char *customfile)
{
int i;
int filepass;
for (filepass = 0;;filepass++)
{
if (filepass == 0)
- dpsnprintf(filename, sizeof(filename), "effectinfo.txt");
+ {
+ if (customfile)
+ strlcpy(filename, customfile, sizeof(filename));
+ else
+ strlcpy(filename, "effectinfo.txt", sizeof(filename));
+ }
else if (filepass == 1)
{
- if (!cl.worldbasename[0])
+ if (!cl.worldbasename[0] || customfile)
continue;
dpsnprintf(filename, sizeof(filename), "%s_effectinfo.txt", cl.worldnamenoextension);
}
}
}
+static void CL_Particles_LoadEffectInfo_f(void)
+{
+ CL_Particles_LoadEffectInfo(Cmd_Argc() > 1 ? Cmd_Argv(1) : NULL);
+}
+
/*
===============
CL_InitParticles
void CL_Particles_Init (void)
{
Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "display point file produced by qbsp when a leak was detected in the map (a line leading through the leak hole, to an entity inside the level)");
- Cmd_AddCommand ("cl_particles_reloadeffects", CL_Particles_LoadEffectInfo, "reloads effectinfo.txt and maps/levelname_effectinfo.txt (where levelname is the current map)");
+ Cmd_AddCommand ("cl_particles_reloadeffects", CL_Particles_LoadEffectInfo_f, "reloads effectinfo.txt and maps/levelname_effectinfo.txt (where levelname is the current map) if parameter is given, loads from custom file (no levelname_effectinfo are loaded in this case)");
Cvar_RegisterVariable (&cl_particles);
Cvar_RegisterVariable (&cl_particles_quality);
void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, float alpha, int texnum, int color1, int color2)
{
int i;
- float bestfrac, bestorg[3], bestnormal[3];
- float org2[3];
+ vec_t bestfrac;
+ vec3_t bestorg;
+ vec3_t bestnormal;
+ vec3_t org2;
int besthitent = 0, hitent;
trace_t trace;
bestfrac = 10;
void CL_EntityParticles (const entity_t *ent)
{
int i;
- float pitch, yaw, dist = 64, beamlength = 16, org[3], v[3];
+ vec_t pitch, yaw, dist = 64, beamlength = 16;
+ vec3_t org, v;
static vec3_t avelocities[NUMVERTEXNORMALS];
if (!cl_particles.integer) return;
if (cl.time <= cl.oldtime) return; // don't spawn new entity particles while paused
void CL_ReadPointFile_f (void)
{
- vec3_t org, leakorg;
+ double org[3], leakorg[3];
+ vec3_t vecorg;
int r, c, s;
char *pointfile = NULL, *pointfilepos, *t, tchar;
char name[MAX_QPATH];
#if _MSC_VER >= 1400
#define sscanf sscanf_s
#endif
- r = sscanf (pointfilepos,"%f %f %f", &org[0], &org[1], &org[2]);
+ r = sscanf (pointfilepos,"%lf %lf %lf", &org[0], &org[1], &org[2]);
+ VectorCopy(org, vecorg);
*t = tchar;
pointfilepos = t;
if (r != 3)
if (cl.num_particles < cl.max_particles - 3)
{
s++;
- CL_NewParticle(org, pt_alphastatic, particlepalette[(-c)&15], particlepalette[(-c)&15], tex_particle, 2, 0, 255, 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, true, 1<<30, 1, PBLEND_ALPHA, PARTICLE_BILLBOARD, -1, -1, -1, 1, 1, 0, 0, NULL);
+ CL_NewParticle(vecorg, pt_alphastatic, particlepalette[(-c)&15], particlepalette[(-c)&15], tex_particle, 2, 0, 255, 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, true, 1<<30, 1, PBLEND_ALPHA, PARTICLE_BILLBOARD, -1, -1, -1, 1, 1, 0, 0, NULL);
}
}
Mem_Free(pointfile);
- VectorCopy(leakorg, org);
- Con_Printf("%i points read (%i particles spawned)\nLeak at %f %f %f\n", c, s, org[0], org[1], org[2]);
+ VectorCopy(leakorg, vecorg);
+ Con_Printf("%i points read (%i particles spawned)\nLeak at %f %f %f\n", c, s, leakorg[0], leakorg[1], leakorg[2]);
- CL_NewParticle(org, pt_beam, 0xFF0000, 0xFF0000, tex_beam, 64, 0, 255, 0, 0, 0, org[0] - 4096, org[1], org[2], org[0] + 4096, org[1], org[2], 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
- CL_NewParticle(org, pt_beam, 0x00FF00, 0x00FF00, tex_beam, 64, 0, 255, 0, 0, 0, org[0], org[1] - 4096, org[2], org[0], org[1] + 4096, org[2], 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
- CL_NewParticle(org, pt_beam, 0x0000FF, 0x0000FF, tex_beam, 64, 0, 255, 0, 0, 0, org[0], org[1], org[2] - 4096, org[0], org[1], org[2] + 4096, 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
+ CL_NewParticle(vecorg, pt_beam, 0xFF0000, 0xFF0000, tex_beam, 64, 0, 255, 0, 0, 0, org[0] - 4096, org[1], org[2], org[0] + 4096, org[1], org[2], 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
+ CL_NewParticle(vecorg, pt_beam, 0x00FF00, 0x00FF00, tex_beam, 64, 0, 255, 0, 0, 0, org[0], org[1] - 4096, org[2], org[0], org[1] + 4096, org[2], 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
+ CL_NewParticle(vecorg, pt_beam, 0x0000FF, 0x0000FF, tex_beam, 64, 0, 255, 0, 0, 0, org[0], org[1], org[2] - 4096, org[0], org[1], org[2] + 4096, 0, 0, 0, 0, false, 1<<30, 1, PBLEND_ADD, PARTICLE_HBEAM, -1, -1, -1, 1, 1, 0, 0, NULL);
}
/*
particlepalette[i] = palette_rgb[i][0] * 65536 + palette_rgb[i][1] * 256 + palette_rgb[i][2];
particletexturepool = R_AllocTexturePool();
R_InitParticleTexture ();
- CL_Particles_LoadEffectInfo();
+ CL_Particles_LoadEffectInfo(NULL);
}
static void r_part_shutdown(void)
{
if (decalskinframe)
R_SkinFrame_MarkUsed(decalskinframe);
- CL_Particles_LoadEffectInfo();
+ CL_Particles_LoadEffectInfo(NULL);
}
unsigned short particle_elements[MESHQUEUE_TRANSPARENT_BATCHSIZE*6];
const decal_t *d;
float *v3f, *t2f, *c4f;
particletexture_t *tex;
- float right[3], up[3], size, ca;
+ vec_t right[3], up[3], size, ca;
float alphascale = (1.0f / 65536.0f) * cl_particles_alpha.value;
RSurf_ActiveWorldEntity();
continue;
if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
continue;
killdecal:
decal->typeindex = 0;
static void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
+ vec3_t vecorg, vecvel, baseright, baseup;
int surfacelistindex;
int batchstart, batchcount;
const particle_t *p;
particletexture_t *tex;
float up2[3], v[3], right[3], up[3], fog, ifog, size, len, lenfactor, alpha;
// float ambient[3], diffuse[3], diffusenormal[3];
- float palpha, spintime, spinrad, spincos, spinsin, spinm1, spinm2, spinm3, spinm4, baseright[3], baseup[3];
+ float palpha, spintime, spinrad, spincos, spinsin, spinm1, spinm2, spinm3, spinm4;
vec4_t colormultiplier;
float minparticledist_start, minparticledist_end;
qboolean dofade;
c4f[3] = alpha;
// note: lighting is not cheap!
if (particletype[p->typeindex].lighting)
- R_LightPoint(c4f, p->org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+ {
+ vecorg[0] = p->org[0];
+ vecorg[1] = p->org[1];
+ vecorg[2] = p->org[2];
+ R_LightPoint(c4f, vecorg, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+ }
// mix in the fog color
if (r_refdef.fogenabled)
{
t2f[6] = tex->s2;t2f[7] = tex->t2;
break;
case PARTICLE_ORIENTED_DOUBLESIDED:
- VectorVectors(p->vel, baseright, baseup);
+ vecvel[0] = p->vel[0];
+ vecvel[1] = p->vel[1];
+ vecvel[2] = p->vel[2];
+ VectorVectors(vecvel, baseright, baseup);
if (p->angle + p->spin)
{
spinrad = (p->angle + p->spin * (spintime - p->delayedspawn)) * (float)(M_PI / 180.0f);
{
case pt_beam:
// beams have no culling
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
default:
if(cl_particles_visculling.integer)
}
// anything else just has to be in front of the viewer and visible at this distance
if (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size))
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
}
cvar_t scr_loadingscreen_scale = {0, "scr_loadingscreen_scale","1", "scale factor of the background"};
cvar_t scr_loadingscreen_scale_base = {0, "scr_loadingscreen_scale_base","0", "0 = console pixels, 1 = video pixels"};
cvar_t scr_loadingscreen_scale_limit = {0, "scr_loadingscreen_scale_limit","0", "0 = no limit, 1 = until first edge hits screen edge, 2 = until last edge hits screen edge, 3 = until width hits screen width, 4 = until height hits screen height"};
+cvar_t scr_loadingscreen_picture = {CVAR_SAVE, "scr_loadingscreen_picture", "gfx/loading", "picture shown during loading"};
cvar_t scr_loadingscreen_count = {0, "scr_loadingscreen_count","1", "number of loading screen files to use randomly (named loading.tga, loading2.tga, loading3.tga, ...)"};
cvar_t scr_loadingscreen_firstforstartup = {0, "scr_loadingscreen_firstforstartup","0", "remove loading.tga from random scr_loadingscreen_count selection and only display it on client startup, 0 = normal, 1 = firstforstartup"};
cvar_t scr_loadingscreen_barcolor = {0, "scr_loadingscreen_barcolor", "0 0 1", "rgb color of loadingscreen progress bar"};
cvar_t scr_loadingscreen_barheight = {0, "scr_loadingscreen_barheight", "8", "the height of the loadingscreen progress bar"};
+cvar_t scr_loadingscreen_maxfps = {0, "scr_loadingscreen_maxfps", "10", "restrict maximal FPS for loading screen so it will not update very often (this will make lesser loading times on a maps loading large number of models)"};
cvar_t scr_infobar_height = {0, "scr_infobar_height", "8", "the height of the infobar items"};
cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system"};
cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
cvar_t scr_screenshot_timestamp = {CVAR_SAVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
// scr_screenshot_name is defined in fs.c
cvar_t cl_capturevideo = {0, "cl_capturevideo", "0", "enables saving of video to a .avi file using uncompressed I420 colorspace and PCM audio, note that scr_screenshot_gammaboost affects the brightness of the output)"};
+cvar_t cl_capturevideo_demo_stop = {CVAR_SAVE, "cl_capturevideo_demo_stop", "1", "automatically stops video recording when demo ends"};
cvar_t cl_capturevideo_printfps = {CVAR_SAVE, "cl_capturevideo_printfps", "1", "prints the frames per second captured in capturevideo (is only written to the log file, not to the console, as that would be visible on the video)"};
cvar_t cl_capturevideo_width = {CVAR_SAVE, "cl_capturevideo_width", "0", "scales all frames to this resolution before saving the video"};
cvar_t cl_capturevideo_height = {CVAR_SAVE, "cl_capturevideo_height", "0", "scales all frames to this resolution before saving the video"};
float *c;
DrawQ_Fill(graphx, graphy, graphwidth, graphheight + textsize * 2, 0, 0, 0, 0.5, 0);
// draw the bar graph itself
- // advance the packet counter because it is the latest packet column being
- // built up and should come last
- packetcounter = (packetcounter + 1) % NETGRAPH_PACKETS;
memset(g, 0, sizeof(g));
for (j = 0;j < NETGRAPH_PACKETS;j++)
{
Cvar_RegisterVariable (&scr_loadingscreen_scale);
Cvar_RegisterVariable (&scr_loadingscreen_scale_base);
Cvar_RegisterVariable (&scr_loadingscreen_scale_limit);
+ Cvar_RegisterVariable (&scr_loadingscreen_picture);
Cvar_RegisterVariable (&scr_loadingscreen_count);
Cvar_RegisterVariable (&scr_loadingscreen_firstforstartup);
Cvar_RegisterVariable (&scr_loadingscreen_barcolor);
Cvar_RegisterVariable (&scr_loadingscreen_barheight);
+ Cvar_RegisterVariable (&scr_loadingscreen_maxfps);
Cvar_RegisterVariable (&scr_infobar_height);
Cvar_RegisterVariable (&scr_showram);
Cvar_RegisterVariable (&scr_showturtle);
Cvar_RegisterVariable (&scr_screenshot_alpha);
Cvar_RegisterVariable (&scr_screenshot_timestamp);
Cvar_RegisterVariable (&cl_capturevideo);
+ Cvar_RegisterVariable (&cl_capturevideo_demo_stop);
Cvar_RegisterVariable (&cl_capturevideo_printfps);
Cvar_RegisterVariable (&cl_capturevideo_width);
Cvar_RegisterVariable (&cl_capturevideo_height);
R_Mesh_Start();
R_EntityMatrix(&identitymatrix);
// draw the loading plaque
- loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "gfx/loading%d", loadingscreenpic_number+1) : "gfx/loading", loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
+ loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "%s%d", scr_loadingscreen_picture.string, loadingscreenpic_number+1) : scr_loadingscreen_picture.string, loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
w = loadingscreenpic->width;
h = loadingscreenpic->height;
VID_Finish();
}
+static double loadingscreen_lastupdate;
+
void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
{
keydest_t old_key_dest;
if (vid_hidden || cls.state == ca_dedicated)
return;
+ // limit update rate
+ if (scr_loadingscreen_maxfps.value)
+ {
+ double t = Sys_DirtyTime();
+ if ((t - loadingscreen_lastupdate) < 1.0f/scr_loadingscreen_maxfps.value)
+ return;
+ loadingscreen_lastupdate = t;
+ }
+
if(!scr_loadingscreen_background.integer)
clear = true;
#include "quakedef.h"
#include "cl_dyntexture.h"
#include "cl_video.h"
-#include "dpvsimpledecode.h"
-
-// VorteX: JAM video module used by Blood Omnicide
-#define USEJAM
-#ifdef USEJAM
- #include "cl_video_jamdecode.c"
-#endif
// cvars
cvar_t cl_video_subtitles = {CVAR_SAVE, "cl_video_subtitles", "0", "show subtitles for videos (if they are present)"};
cvar_t cl_video_fadein = {CVAR_SAVE, "cl_video_fadein", "0", "fading-from-black effect once video is started, in seconds"};
cvar_t cl_video_fadeout = {CVAR_SAVE, "cl_video_fadeout", "0", "fading-to-black effect once video is ended, in seconds"};
+cvar_t v_glslgamma_video = {CVAR_SAVE, "v_glslgamma_video", "1", "applies GLSL gamma to played video, could be a fraction, requires r_glslgamma_2d 1."};
+
+// DPV stream decoder
+#include "dpvsimpledecode.h"
+
+// VorteX: libavcodec implementation
+#include "cl_video_libavw.c"
+
+// JAM video decoder used by Blood Omnicide
+#ifdef JAMVIDEO
+#include "cl_video_jamdecode.c"
+#endif
+
// constants (and semi-constants)
static int cl_videormask;
static int cl_videobmask;
static qboolean OpenStream( clvideo_t * video )
{
const char *errorstring;
+
video->stream = dpvsimpledecode_open( video, video->filename, &errorstring);
- if (!video->stream )
- {
-#ifdef USEJAM
- video->stream = jam_open( video, video->filename, &errorstring);
- if (video->stream)
- return true;
+ if (video->stream)
+ return true;
+
+#ifdef JAMVIDEO
+ video->stream = jam_open( video, video->filename, &errorstring);
+ if (video->stream)
+ return true;
#endif
- Con_Printf("unable to open \"%s\", error: %s\n", video->filename, errorstring);
- return false;
- }
- return true;
+
+ video->stream = LibAvW_OpenVideo( video, video->filename, &errorstring);
+ if (video->stream)
+ return true;
+
+ Con_Printf("unable to open \"%s\", error: %s\n", video->filename, errorstring);
+ return false;
}
static void VideoUpdateCallback(rtexture_t *rt, void *data)
UnlinkVideoTexture(video);
// if we are in firstframe mode, also close the stream
if (video->state == CLVIDEO_FIRSTFRAME)
- video->close(video->stream);
+ {
+ if (video->stream)
+ video->close(video->stream);
+ video->stream = NULL;
+ }
}
static qboolean WakeVideo( clvideo_t * video )
subtitle_text = NULL;
if (langcvar)
{
- dpsnprintf(overridename, sizeof(overridename), "script/locale/%s/%s", langcvar->string, subtitlesfile);
+ dpsnprintf(overridename, sizeof(overridename), "locale/%s/%s", langcvar->string, subtitlesfile);
subtitle_text = (char *)FS_LoadFile(overridename, cls.permanentmempool, false, NULL);
}
if (!subtitle_text)
video->framenum = -1;
// reopen stream
- video->close(video->stream);
+ if (video->stream)
+ video->close(video->stream);
+ video->stream = NULL;
if (!OpenStream(video))
video->state = CLVIDEO_UNUSED;
}
// close stream
if (!video->suspended || video->state != CLVIDEO_FIRSTFRAME)
- video->close(video->stream);
+ {
+ if (video->stream)
+ video->close(video->stream);
+ video->stream = NULL;
+ }
// unlink texture
if (!video->suspended)
UnlinkVideoTexture(video);
cl_num_videos--;
}
-void CL_Video_Shutdown( void )
-{
- int i;
- for (i = 0 ; i < cl_num_videos ; i++)
- CL_CloseVideo(&cl_videos[ i ]);
-}
-
void CL_PurgeOwner( int owner )
{
int i;
st[6] = 1.0; st[7] = 1.0;
if (cl_video_keepaspectratio.integer)
{
- float a = ((float)video->cpif.width / (float)video->cpif.height) / ((float)vid.width / (float)vid.height);
+ float a = video->getaspectratio(video->stream) / ((float)vid.width / (float)vid.height);
if (cl_video_keepaspectratio.integer >= 2)
{
// clip instead of scale
#endif
// draw video
- DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
+ if (v_glslgamma_video.value >= 1)
+ DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
+ else
+ {
+ DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, DRAWFLAG_NOGAMMA);
+ if (v_glslgamma_video.value > 0.0)
+ DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, v_glslgamma_video.value, st[2], st[3], b, b, b, v_glslgamma_video.value, st[4], st[5], b, b, b, v_glslgamma_video.value, st[6], st[7], b, b, b, v_glslgamma_video.value, 0);
+ }
#ifndef USE_GLES2
// disable video-only stipple
Cvar_RegisterVariable(&cl_video_fadein);
Cvar_RegisterVariable(&cl_video_fadeout);
+ Cvar_RegisterVariable(&v_glslgamma_video);
+
R_RegisterModule( "CL_Video", cl_video_start, cl_video_shutdown, cl_video_newmap, NULL, NULL );
-}
\ No newline at end of file
+
+ LibAvW_OpenLibrary();
+}
+
+void CL_Video_Shutdown( void )
+{
+ int i;
+
+ for (i = 0 ; i < cl_num_videos ; i++)
+ CL_CloseVideo(&cl_videos[ i ]);
+
+ LibAvW_CloseLibrary();
+}
unsigned int (*getwidth) (void *stream);
unsigned int (*getheight) (void *stream);
double (*getframerate) (void *stream);
+ double (*getaspectratio) (void *stream);
int (*decodeframe) (void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
// if a video is suspended, it is automatically paused (else we'd still have to process the frames)
// JAM format decoder, used by Blood Omnicide
+#ifdef LIBAVCODEC
+//#define JAM_USELIBAVCODECSCALE
+#endif
+
typedef struct jamdecodestream_s
{
- int error;
+ qfile_t *file;
+ double info_framerate;
+ unsigned int info_frames;
+ unsigned int info_imagewidth;
+ unsigned int info_imageheight;
+ double info_aspectratio;
+ float colorscale;
+ unsigned char colorsub;
- qfile_t *file;
- double info_framerate;
- unsigned int info_frames;
- unsigned int info_imagewidth;
- unsigned int info_imageheight;
- int doubleres;
- float colorscale;
- unsigned char colorsub;
- float stipple;
+ // info used during decoding
+ unsigned char *frame;
+ unsigned char *frame_prev;
+ unsigned char frame_palette[768];
+ unsigned char *frame_compressed;
+ unsigned int framesize;
+ unsigned int framenum;
- // info used durign decoding
- unsigned char *videopixels;
- unsigned char *compressed;
- unsigned char *framedata;
- unsigned char *prevframedata;
- unsigned char colormap[768];
- unsigned int framesize;
- unsigned int framenum;
+ // libavcodec scaling
+#ifdef JAM_USELIBAVCODECSCALE
+ unsigned char *frame_output_buffer;
+ AVFrame *frame_output;
+ AVFrame *frame_output_scale;
+ unsigned int framewidth;
+ unsigned int frameheight;
+#endif
// channel the sound file is being played on
int sndchan;
}
jamdecodestream_t;
-#define JAMDECODEERROR_NONE 0
-#define JAMDECODEERROR_EOF 1
-#define JAMDECODEERROR_READERROR 2
-#define JAMDECODEERROR_BAD_FRAME_HEADER 3
-#define JAMDECODEERROR_BAD_OUTPUT_SIZE 4
-#define JAMDECODEERROR_BAD_COLORMAP 5
-
// opens a stream
void jam_close(void *stream);
unsigned int jam_getwidth(void *stream);
unsigned int jam_getheight(void *stream);
double jam_getframerate(void *stream);
+double jam_getaspectratio(void *stream);
int jam_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
-static void *jam_open(clvideo_t *video, char *filename, const char **errorstring)
+void *jam_open(clvideo_t *video, char *filename, const char **errorstring)
{
- unsigned char jamHead[16];
- char *wavename;
+ char jamHead[16];
jamdecodestream_t *s;
- qfile_t *file;
+ char *wavename;
+ // allocate stream structure
s = (jamdecodestream_t *)Z_Malloc(sizeof(jamdecodestream_t));
- if (s != NULL)
+ memset(s, 0, sizeof(jamdecodestream_t));
+ if (s == NULL)
{
- if ((file = FS_OpenVirtualFile(filename, false)))
- {
- s->file = file;
- if (FS_Read(s->file, &jamHead, 16))
- {
- if (!memcmp(jamHead, "JAM", 3))
- {
- s->info_imagewidth = LittleLong(*(jamHead + 4));
- s->info_imageheight = LittleLong(*(jamHead + 8));
- s->info_frames = LittleLong(*(jamHead + 12));
- s->info_framerate = 15;
- s->doubleres = 0;
- s->colorscale = 0.70;
- s->colorsub = 8;
- s->stipple = 0.4;
- s->framesize = s->info_imagewidth * s->info_imageheight;
- if (s->framesize > 0)
- {
- s->compressed = (unsigned char *)Z_Malloc(s->framesize);
- s->framedata = (unsigned char *)Z_Malloc(s->framesize * 2);
- s->prevframedata = (unsigned char *)Z_Malloc(s->framesize * 2);
- s->videopixels = (unsigned char *)Z_Malloc(s->framesize * 4); // bgra, doubleres
- if (s->compressed != NULL && s->framedata != NULL && s->prevframedata != NULL && s->videopixels != NULL)
- {
- size_t namelen;
+ *errorstring = "unable to allocate memory for stream info structure";
+ return NULL;
+ }
+ s->sndchan = -1;
- namelen = strlen(filename) + 10;
- wavename = (char *)Z_Malloc(namelen);
- if (wavename)
- {
- sfx_t* sfx;
+ // open file
+ s->file = FS_OpenVirtualFile(filename, true);
+ if (!s->file)
+ {
+ *errorstring = "unable to open videofile";
+ jam_close(s);
+ return NULL;
+ }
- FS_StripExtension(filename, wavename, namelen);
- strlcat(wavename, ".wav", namelen);
- sfx = S_PrecacheSound(wavename, false, false);
- if (sfx != NULL)
- s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
- else
- s->sndchan = -1;
- Z_Free(wavename);
- }
- // all is well...
- // set the module functions
- s->framenum = 0;
- video->close = jam_close;
- video->getwidth = jam_getwidth;
- video->getheight = jam_getheight;
- video->getframerate = jam_getframerate;
- video->decodeframe = jam_video;
- return s;
- }
- else if (errorstring != NULL)
- *errorstring = "unable to allocate memory for stream info structure";
- if (s->compressed != NULL)
- Z_Free(s->compressed);
- if (s->framedata != NULL)
- Z_Free(s->framedata);
- if (s->prevframedata != NULL)
- Z_Free(s->prevframedata);
- if (s->videopixels != NULL)
- Z_Free(s->videopixels);
- }
- else if (errorstring != NULL)
- *errorstring = "bad framesize";
- }
- else if (errorstring != NULL)
- *errorstring = "not JAM videofile";
- }
- else if (errorstring != NULL)
- *errorstring = "unexpected EOF";
- FS_Close(file);
- }
- else if (errorstring != NULL)
- *errorstring = "unable to open videofile";
+ // read header
+ if (!FS_Read(s->file, jamHead, 16))
+ {
+ *errorstring = "JamDecoder: unexpected EOF reading header";
+ jam_close(s);
+ return NULL;
+ }
+ if (memcmp(jamHead, "JAM", 4))
+ {
+ *errorstring = "JamDecoder: not a JAM file";
+ jam_close(s);
+ return NULL;
+ }
+
+ s->info_imagewidth = LittleLong(*(jamHead + 4));
+ s->info_imageheight = LittleLong(*(jamHead + 8));
+ s->info_frames = LittleLong(*(jamHead + 12)) - 1;
+ s->info_framerate = 15;
+ s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
+ s->colorscale = 0.90;
+ s->colorsub = 4;
+ s->framesize = s->info_imagewidth * s->info_imageheight;
+
+ // allocate frame input/output
+ if (s->framesize < 0)
+ {
+ *errorstring = "JamDecoder: bad framesize";
+ jam_close(s);
+ return NULL;
+ }
+ s->frame = (unsigned char *)Z_Malloc(s->framesize * 2);
+ s->frame_prev = (unsigned char *)Z_Malloc(s->framesize * 2);
+ s->frame_compressed = (unsigned char *)Z_Malloc(s->framesize);
+ if (s->frame_compressed == NULL || s->frame == NULL || s->frame_prev == NULL)
+ {
+ *errorstring = "JamDecoder: unable to allocate memory for video decoder";
+ jam_close(s);
+ return NULL;
+ }
+
+ // scale support provided by libavcodec
+#ifdef JAM_USELIBAVCODECSCALE
+ s->framewidth = s->info_imagewidth;
+ s->frameheight = s->info_imageheight;
+
+ // min size
+ if (cl_video_libavcodec_minwidth.integer > 0)
+ s->info_imagewidth = max(s->info_imagewidth, (unsigned int)cl_video_libavcodec_minwidth.integer);
+ if (cl_video_libavcodec_minheight.integer > 0)
+ s->info_imageheight = max(s->info_imageheight, (unsigned int)cl_video_libavcodec_minheight.integer);
+
+ // allocate output
+ s->frame_output_buffer = (unsigned char *)Z_Malloc(s->framesize * 4);
+ s->frame_output = AvCodec_AllocFrame();
+ s->frame_output_scale = AvCodec_AllocFrame();
+ if (!s->frame_output_buffer || !s->frame_output || !s->frame_output_scale)
+ {
+ *errorstring = "JamDecoder: failed to allocate LibAvcodec frame";
+ jam_close(s);
Z_Free(s);
+ return NULL;
}
- else if (errorstring != NULL)
- *errorstring = "unable to allocate memory for stream info structure";
- return NULL;
+#endif
+
+ // everything is ok
+ // set the module functions
+ s->framenum = 0;
+ video->close = jam_close;
+ video->getwidth = jam_getwidth;
+ video->getheight = jam_getheight;
+ video->getframerate = jam_getframerate;
+ video->decodeframe = jam_video;
+ video->getaspectratio = jam_getaspectratio;
+
+ // set sound
+ size_t namelen;
+ namelen = strlen(filename) + 10;
+ wavename = (char *)Z_Malloc(namelen);
+ if (wavename)
+ {
+ sfx_t* sfx;
+ FS_StripExtension(filename, wavename, namelen);
+ strlcat(wavename, ".wav", namelen);
+ sfx = S_PrecacheSound(wavename, false, false);
+ if (sfx != NULL)
+ s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
+ else
+ s->sndchan = -1;
+ Z_Free(wavename);
+ }
+
+ return s;
}
// closes a stream
jamdecodestream_t *s = (jamdecodestream_t *)stream;
if (s == NULL)
return;
- Z_Free(s->compressed);
- Z_Free(s->framedata);
- Z_Free(s->prevframedata);
- Z_Free(s->videopixels);
+ if (s->frame_compressed)
+ Z_Free(s->frame_compressed);
+ s->frame_compressed = NULL;
+ if (s->frame)
+ Z_Free(s->frame);
+ s->frame = NULL;
+ if (s->frame_prev)
+ Z_Free(s->frame_prev);
+ s->frame_prev = NULL;
if (s->sndchan != -1)
S_StopChannel(s->sndchan, true, true);
+ s->sndchan = -1;
if (s->file)
FS_Close(s->file);
+ s->file = NULL;
+#ifdef JAM_USELIBAVCODECSCALE
+ if (s->frame_output_buffer)
+ Z_Free(s->frame_output_buffer);
+ s->frame_output_buffer = NULL;
+ if (s->frame_output)
+ AvUtil_Free(s->frame_output);
+ s->frame_output = NULL;
+ if (s->frame_output_scale)
+ AvUtil_Free(s->frame_output_scale);
+ s->frame_output_scale = NULL;
+#endif
Z_Free(s);
}
unsigned int jam_getwidth(void *stream)
{
jamdecodestream_t *s = (jamdecodestream_t *)stream;
- if (s->doubleres)
- return s->info_imagewidth * 2;
return s->info_imagewidth;
}
unsigned int jam_getheight(void *stream)
{
jamdecodestream_t *s = (jamdecodestream_t *)stream;
- if (s->doubleres)
- return s->info_imageheight * 2;
return s->info_imageheight;
}
return s->info_framerate;
}
+// returns aspect ration of the stream
+double jam_getaspectratio(void *stream)
+{
+ jamdecodestream_t *s = (jamdecodestream_t *)stream;
+ return s->info_aspectratio;
+}
// decode JAM frame
static void jam_decodeframe(unsigned char *inbuf, unsigned char *outbuf, unsigned char *prevbuf, int outsize, int frametype)
int jam_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
{
unsigned char frameHead[16], *b;
- unsigned int compsize, outsize, i, j;
+ unsigned int compsize, outsize, i;
jamdecodestream_t *s = (jamdecodestream_t *)stream;
- s->error = DPVSIMPLEDECODEERROR_NONE;
- if (s->framenum < s->info_frames)
- {
+ // EOF
+ if (s->framenum >= s->info_frames)
+ return 1;
+ s->framenum++;
+
readframe:
- if (FS_Read(s->file, &frameHead, 16))
- {
- compsize = LittleLong(*(frameHead + 8)) - 16;
- outsize = LittleLong(*(frameHead + 12));
- if (compsize > s->framesize || outsize > s->framesize)
- s->error = JAMDECODEERROR_BAD_FRAME_HEADER;
- else if (FS_Read(s->file, s->compressed, compsize))
- {
- // palette goes interleaved with special flag
- if (frameHead[0] == 2)
- {
- if (compsize == 768)
- {
- memcpy(s->colormap, s->compressed, 768);
- for(i = 0; i < 768; i++)
- s->colormap[i] = (unsigned char)(bound(0, (s->colormap[i] * s->colorscale) - s->colorsub, 255));
- goto readframe;
- }
- //else
- // s->error = JAMDECODEERROR_BAD_COLORMAP;
- }
- else
- {
- // decode frame
- // shift buffers to provide current and previous one, decode
- b = s->prevframedata;
- s->prevframedata = s->framedata;
- s->framedata = b;
- jam_decodeframe(s->compressed, s->framedata, s->prevframedata, outsize, frameHead[4]);
- // make 32bit imagepixels from 8bit palettized frame
- if (s->doubleres)
- b = s->videopixels;
- else
- b = (unsigned char *)imagedata;
- for(i = 0; i < s->framesize; i++)
- {
- // bgra
- *b++ = s->colormap[s->framedata[i]*3 + 2];
- *b++ = s->colormap[s->framedata[i]*3 + 1];
- *b++ = s->colormap[s->framedata[i]*3];
- *b++ = 255;
- }
- // nearest 2x
- if (s->doubleres)
- {
- for (i = 0; i < s->info_imageheight; i++)
- {
- b = (unsigned char *)imagedata + (s->info_imagewidth*2*4)*(i*2);
- for (j = 0; j < s->info_imagewidth; j++)
- {
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 1];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 2];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 3];
- //
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 1];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 2];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 3];
- }
- b = (unsigned char *)imagedata + (s->info_imagewidth*2*4)*(i*2 + 1);
- for (j = 0; j < s->info_imagewidth; j++)
- {
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 1];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 2];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 3];
- //
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 1];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 2];
- *b++ = s->videopixels[i*s->info_imagewidth*4 + j*4 + 3];
- }
- }
- // do stippling
- if (s->stipple)
- {
- for (i = 0; i < s->info_imageheight; i++)
- {
- b = (unsigned char *)imagedata + (s->info_imagewidth * 4 * 2 * 2 * i);
- for (j = 0; j < s->info_imagewidth; j++)
- {
- b[0] = b[0] * s->stipple;
- b[1] = b[1] * s->stipple;
- b[2] = b[2] * s->stipple;
- b += 4;
- b[0] = b[0] * s->stipple;
- b[1] = b[1] * s->stipple;
- b[2] = b[2] * s->stipple;
- b += 4;
- }
- }
- }
- }
+ // read frame header
+ if (!FS_Read(s->file, &frameHead, 16))
+ {
+ Con_Printf("JamDecoder: unexpected EOF on frame %i\n", s->framenum);
+ return 1;
+ }
+ compsize = LittleLong(*(frameHead + 8)) - 16;
+ outsize = LittleLong(*(frameHead + 12));
+ if (compsize > s->framesize || outsize > s->framesize)
+ {
+ Con_Printf("JamDecoder: got bogus header on frame %i\n", s->framenum);
+ return 1;
+ }
- }
- }
- else
- s->error = JAMDECODEERROR_READERROR;
+ // read frame contents
+ if (!FS_Read(s->file, s->frame_compressed, compsize))
+ {
+ Con_Printf("JamDecoder: unexpected EOF on frame %i\n", s->framenum);
+ return 1;
+ }
+
+ // palette goes interleaved with special flag
+ if (frameHead[0] == 2)
+ {
+ if (compsize == 768)
+ {
+ memcpy(s->frame_palette, s->frame_compressed, 768);
+ for(i = 0; i < 768; i++)
+ s->frame_palette[i] = (unsigned char)(bound(0, (s->frame_palette[i] * s->colorscale) - s->colorsub, 255));
+ goto readframe;
}
- else
- s->error = JAMDECODEERROR_READERROR;
}
else
- s->error = DPVSIMPLEDECODEERROR_EOF;
- return s->error;
+ {
+ // decode frame
+ // shift buffers to provide current and previous one, decode
+ b = s->frame_prev;
+ s->frame_prev = s->frame;
+ s->frame = b;
+ jam_decodeframe(s->frame_compressed, s->frame, s->frame_prev, outsize, frameHead[4]);
+#ifdef JAM_USELIBAVCODECSCALE
+ // make BGRA imagepixels from 8bit palettized frame
+ b = (unsigned char *)s->frame_output_buffer;
+ for(i = 0; i < s->framesize; i++)
+ {
+ *b++ = s->frame_palette[s->frame[i]*3 + 2];
+ *b++ = s->frame_palette[s->frame[i]*3 + 1];
+ *b++ = s->frame_palette[s->frame[i]*3];
+ *b++ = 255;
+ }
+ // scale
+ AvCodec_FillPicture((AVPicture *)s->frame_output, (uint8_t *)s->frame_output_buffer, PIX_FMT_BGRA, s->framewidth, s->frameheight);
+ AvCodec_FillPicture((AVPicture *)s->frame_output_scale, (uint8_t *)imagedata, PIX_FMT_BGRA, s->info_imagewidth, s->info_imageheight);
+ SwsContext *scale_context = SwScale_GetCachedContext(NULL, s->framewidth, s->frameheight, PIX_FMT_BGRA, s->info_imagewidth, s->info_imageheight, PIX_FMT_BGRA, libavcodec_scalers[max(0, min(LIBAVCODEC_SCALERS, cl_video_libavcodec_scaler.integer))], NULL, NULL, NULL);
+ if (!scale_context)
+ {
+ Con_Printf("JamDecoder: LibAvcodec: error creating scale context frame %i\n", s->framenum);
+ return 1;
+ }
+ if (!SwScale_Scale(scale_context, s->frame_output->data, s->frame_output->linesize, 0, s->frameheight, s->frame_output_scale->data, s->frame_output_scale->linesize))
+ Con_Printf("JamDecoder: LibAvcodec : error scaling frame\n", s->framenum);
+ SwScale_FreeContext(scale_context);
+#else
+ // make BGRA imagepixels from 8bit palettized frame
+ b = (unsigned char *)imagedata;
+ for(i = 0; i < s->framesize; i++)
+ {
+ // bgra
+ *b++ = s->frame_palette[s->frame[i]*3 + 2];
+ *b++ = s->frame_palette[s->frame[i]*3 + 1];
+ *b++ = s->frame_palette[s->frame[i]*3];
+ *b++ = 255;
+ }
+#endif
+ }
+ return 0;
}
--- /dev/null
+/*
+ Libavcodec integration for Darkplaces by Timofeyev Pavel
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to:
+
+ Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330
+ Boston, MA 02111-1307, USA
+
+*/
+
+// LordHavoc: for some reason this is being #include'd rather than treated as its own file...
+// LordHavoc: adapted to not require stdint.h as this is not available on MSVC++, using unsigned char instead of uint8_t and fs_offset_t instead of int64_t.
+
+// scaler type
+#define LIBAVW_SCALER_BILINEAR 0
+#define LIBAVW_SCALER_BICUBIC 1
+#define LIBAVW_SCALER_X 2
+#define LIBAVW_SCALER_POINT 3
+#define LIBAVW_SCALER_AREA 4
+#define LIBAVW_SCALER_BICUBLIN 5
+#define LIBAVW_SCALER_GAUSS 6
+#define LIBAVW_SCALER_SINC 7
+#define LIBAVW_SCALER_LANCZOS 8
+#define LIBAVW_SCALER_SPLINE 9
+// output format
+#define LIBAVW_PIXEL_FORMAT_BGR 0
+#define LIBAVW_PIXEL_FORMAT_BGRA 1
+// print levels
+#define LIBAVW_PRINT_WARNING 1
+#define LIBAVW_PRINT_ERROR 2
+#define LIBAVW_PRINT_FATAL 3
+#define LIBAVW_PRINT_PANIC 4
+// exported callback functions:
+typedef void avwCallbackPrint(int, const char *);
+typedef int avwCallbackIoRead(void *, unsigned char *, int);
+typedef fs_offset_t avwCallbackIoSeek(void *, fs_offset_t, int);
+typedef fs_offset_t avwCallbackIoSeekSize(void *);
+// exported functions:
+int (*qLibAvW_Init)(avwCallbackPrint *printfunction); // init library, returns error code
+const char *(*qLibAvW_ErrorString)(int errorcode); // get string for error code
+const char *(*qLibAvW_AvcVersion)(void); // get a string containing libavcodec version wrapper was built for
+float (*qLibAvW_Version)(void); // get wrapper version
+int (*qLibAvW_CreateStream)(void **stream); // create stream, returns error code
+void (*qLibAvW_RemoveStream)(void *stream); // flush and remove stream
+int (*qLibAvW_StreamGetVideoWidth)(void *stream); // get video parameters of stream
+int (*qLibAvW_StreamGetVideoHeight)(void *stream);
+double (*qLibAvW_StreamGetFramerate)(void *stream);
+int (*qLibAvW_StreamGetError)(void *stream); // get last function errorcode from stream
+// simple API to play video
+int (*qLibAvW_PlayVideo)(void *stream, void *file, avwCallbackIoRead *IoRead, avwCallbackIoSeek *IoSeek, avwCallbackIoSeekSize *IoSeekSize);
+int (*qLibAvW_PlaySeekNextFrame)(void *stream);
+int (*qLibAvW_PlayGetFrameImage)(void *stream, int pixel_format, void *imagedata, int imagewidth, int imageheight, int scaler);
+
+static dllfunction_t libavwfuncs[] =
+{
+ {"LibAvW_Init", (void **) &qLibAvW_Init },
+ {"LibAvW_ErrorString", (void **) &qLibAvW_ErrorString },
+ {"LibAvW_AvcVersion", (void **) &qLibAvW_AvcVersion },
+ {"LibAvW_Version", (void **) &qLibAvW_Version },
+ {"LibAvW_CreateStream", (void **) &qLibAvW_CreateStream },
+ {"LibAvW_RemoveStream", (void **) &qLibAvW_RemoveStream },
+ {"LibAvW_StreamGetVideoWidth", (void **) &qLibAvW_StreamGetVideoWidth },
+ {"LibAvW_StreamGetVideoHeight",(void **) &qLibAvW_StreamGetVideoHeight },
+ {"LibAvW_StreamGetFramerate", (void **) &qLibAvW_StreamGetFramerate },
+ {"LibAvW_StreamGetError", (void **) &qLibAvW_StreamGetError },
+ {"LibAvW_PlayVideo", (void **) &qLibAvW_PlayVideo },
+ {"LibAvW_PlaySeekNextFrame", (void **) &qLibAvW_PlaySeekNextFrame },
+ {"LibAvW_PlayGetFrameImage", (void **) &qLibAvW_PlayGetFrameImage },
+ {NULL, NULL}
+};
+
+const char* dllnames_libavw[] =
+{
+#if defined(WIN32)
+ "libavw.dll",
+#elif defined(MACOSX)
+ "libavw.dylib",
+#else
+ "libavw.so.1",
+ "libavw.so",
+#endif
+ NULL
+};
+
+static dllhandle_t libavw_dll = NULL;
+
+// DP videostream
+typedef struct libavwstream_s
+{
+ qfile_t *file;
+ double info_framerate;
+ unsigned int info_imagewidth;
+ unsigned int info_imageheight;
+ double info_aspectratio;
+ void *stream;
+
+ // channel the sound file is being played on
+ sfx_t *sfx;
+ int sndchan;
+ int sndstarted;
+}
+libavwstream_t;
+
+cvar_t cl_video_libavw_minwidth = {CVAR_SAVE, "cl_video_libavw_minwidth", "0", "if videos width is lesser than minimal, thay will be upscaled"};
+cvar_t cl_video_libavw_minheight = {CVAR_SAVE, "cl_video_libavw_minheight", "0", "if videos height is lesser than minimal, thay will be upscaled"};
+cvar_t cl_video_libavw_scaler = {CVAR_SAVE, "cl_video_libavw_scaler", "1", "selects a scaler for libavcode played videos. Scalers are: 0 - bilinear, 1 - bicubic, 2 - x, 3 - point, 4 - area, 5 - bicublin, 6 - gauss, 7 - sinc, 8 - lanczos, 9 - spline."};
+
+// video extensions
+const char* libavw_extensions[] =
+{
+ "ogv",
+ "avi",
+ "mpg",
+ "mp4",
+ "mkv",
+ "webm",
+ "bik",
+ "roq",
+ "flv",
+ "wmv",
+ "mpeg",
+ "mjpeg",
+ "mpeg4",
+ NULL
+};
+
+/*
+=================================================================
+
+ Video decoding
+ a features that is not supported yet and likely to be done
+ - streaming audio from videofiles
+ - streaming subtitles
+
+=================================================================
+*/
+
+unsigned int libavw_getwidth(void *stream);
+unsigned int libavw_getheight(void *stream);
+double libavw_getframerate(void *stream);
+double libavw_getaspectratio(void *stream);
+void libavw_close(void *stream);
+
+static int libavw_decodeframe(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
+{
+ int pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
+ int errorcode;
+
+ libavwstream_t *s = (libavwstream_t *)stream;
+
+ // start sound
+ if (!s->sndstarted)
+ {
+ if (s->sfx != NULL)
+ s->sndchan = S_StartSound(-1, 0, s->sfx, vec3_origin, 1.0f, 0);
+ s->sndstarted = 1;
+ }
+
+ // read frame
+ if (!qLibAvW_PlaySeekNextFrame(s->stream))
+ {
+ // got error or file end
+ errorcode = qLibAvW_StreamGetError(s->stream);
+ if (errorcode)
+ Con_Printf("LibAvW: %s\n", qLibAvW_ErrorString(errorcode));
+ return 1;
+ }
+
+ // decode into bgr texture
+ if (bytesperpixel == 4)
+ pixel_format = LIBAVW_PIXEL_FORMAT_BGRA;
+ else if (bytesperpixel == 3)
+ pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
+ else
+ {
+ Con_Printf("LibAvW: cannot determine pixel format for bpp %i\n", bytesperpixel);
+ return 1;
+ }
+ if (!qLibAvW_PlayGetFrameImage(s->stream, pixel_format, imagedata, s->info_imagewidth, s->info_imageheight, min(9, max(0, cl_video_libavw_scaler.integer))))
+ Con_Printf("LibAvW: %s\n", qLibAvW_ErrorString(qLibAvW_StreamGetError(s->stream)));
+ return 0;
+}
+
+// get stream info
+unsigned int libavw_getwidth(void *stream)
+{
+ return ((libavwstream_t *)stream)->info_imagewidth;
+}
+
+unsigned int libavw_getheight(void *stream)
+{
+ return ((libavwstream_t *)stream)->info_imageheight;
+}
+
+double libavw_getframerate(void *stream)
+{
+ return ((libavwstream_t *)stream)->info_framerate;
+}
+
+double libavw_getaspectratio(void *stream)
+{
+ return ((libavwstream_t *)stream)->info_aspectratio;
+}
+
+// close stream
+void libavw_close(void *stream)
+{
+ libavwstream_t *s = (libavwstream_t *)stream;
+
+ if (s->stream)
+ qLibAvW_RemoveStream(s->stream);
+ s->stream = NULL;
+ if (s->file)
+ FS_Close(s->file);
+ s->file = NULL;
+ if (s->sndchan >= 0)
+ S_StopChannel(s->sndchan, true, true);
+ s->sndchan = -1;
+}
+
+// IO wrapper
+static int LibAvW_FS_Read(void *opaque, unsigned char *buf, int buf_size)
+{
+ return FS_Read((qfile_t *)opaque, buf, buf_size);
+}
+static fs_offset_t LibAvW_FS_Seek(void *opaque, fs_offset_t pos, int whence)
+{
+ return (fs_offset_t)FS_Seek((qfile_t *)opaque, pos, whence);
+}
+static fs_offset_t LibAvW_FS_SeekSize(void *opaque)
+{
+ return (fs_offset_t)FS_FileSize((qfile_t *)opaque);
+}
+
+// open as DP video stream
+static void *LibAvW_OpenVideo(clvideo_t *video, char *filename, const char **errorstring)
+{
+ libavwstream_t *s;
+ char filebase[MAX_OSPATH], check[MAX_OSPATH];
+ unsigned int i;
+ int errorcode;
+ char *wavename;
+ size_t len;
+
+ if (!libavw_dll)
+ return NULL;
+
+ // allocate stream
+ s = (libavwstream_t *)Z_Malloc(sizeof(libavwstream_t));
+ if (s == NULL)
+ {
+ *errorstring = "unable to allocate memory for stream info structure";
+ return NULL;
+ }
+ memset(s, 0, sizeof(libavwstream_t));
+ s->sndchan = -1;
+
+ // open file
+ s->file = FS_OpenVirtualFile(filename, true);
+ if (!s->file)
+ {
+ FS_StripExtension(filename, filebase, sizeof(filebase));
+ // we tried .dpv, try another extensions
+ for (i = 0; libavw_extensions[i] != NULL; i++)
+ {
+ dpsnprintf(check, sizeof(check), "%s.%s", filebase, libavw_extensions[i]);
+ s->file = FS_OpenVirtualFile(check, true);
+ if (s->file)
+ break;
+ }
+ if (!s->file)
+ {
+ *errorstring = "unable to open videofile";
+ libavw_close(s);
+ Z_Free(s);
+ return NULL;
+ }
+ }
+
+ // allocate libavw stream
+ if ((errorcode = qLibAvW_CreateStream(&s->stream)))
+ {
+ *errorstring = qLibAvW_ErrorString(errorcode);
+ libavw_close(s);
+ Z_Free(s);
+ return NULL;
+ }
+
+ // open video for playing
+ if (!qLibAvW_PlayVideo(s->stream, s->file, &LibAvW_FS_Read, &LibAvW_FS_Seek, &LibAvW_FS_SeekSize))
+ {
+ *errorstring = qLibAvW_ErrorString(qLibAvW_StreamGetError(s->stream));
+ libavw_close(s);
+ Z_Free(s);
+ return NULL;
+ }
+
+ // all right, start codec
+ s->info_imagewidth = qLibAvW_StreamGetVideoWidth(s->stream);
+ s->info_imageheight = qLibAvW_StreamGetVideoHeight(s->stream);
+ s->info_framerate = qLibAvW_StreamGetFramerate(s->stream);
+ s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
+ video->close = libavw_close;
+ video->getwidth = libavw_getwidth;
+ video->getheight = libavw_getheight;
+ video->getframerate = libavw_getframerate;
+ video->decodeframe = libavw_decodeframe;
+ video->getaspectratio = libavw_getaspectratio;
+
+ // apply min-width, min-height, keep aspect rate
+ if (cl_video_libavw_minwidth.integer > 0)
+ s->info_imagewidth = max(s->info_imagewidth, (unsigned int)cl_video_libavw_minwidth.integer);
+ if (cl_video_libavw_minheight.integer > 0)
+ s->info_imageheight = max(s->info_imageheight, (unsigned int)cl_video_libavw_minheight.integer);
+
+ // provide sound in separate .wav
+ len = strlen(filename) + 10;
+ wavename = (char *)Z_Malloc(len);
+ if (wavename)
+ {
+ FS_StripExtension(filename, wavename, len-1);
+ strlcat(wavename, ".wav", len);
+ s->sfx = S_PrecacheSound(wavename, false, false);
+ s->sndchan = -1;
+ Z_Free(wavename);
+ }
+ return s;
+}
+
+static void libavw_message(int level, const char *message)
+{
+ if (level == LIBAVW_PRINT_WARNING)
+ Con_Printf("LibAvcodec warning: %s\n", message);
+ else if (level == LIBAVW_PRINT_ERROR)
+ Con_Printf("LibAvcodec error: %s\n", message);
+ else if (level == LIBAVW_PRINT_FATAL)
+ Con_Printf("LibAvcodec fatal error: %s\n", message);
+ else
+ Con_Printf("LibAvcodec panic: %s\n", message);
+}
+
+static qboolean LibAvW_OpenLibrary(void)
+{
+ int errorcode;
+
+ // COMMANDLINEOPTION: Video: -nolibavw disables libavcodec wrapper support
+ if (COM_CheckParm("-nolibavw"))
+ return false;
+
+ // load DLL's
+ Sys_LoadLibrary(dllnames_libavw, &libavw_dll, libavwfuncs);
+ if (!libavw_dll)
+ return false;
+
+ // initialize libav wrapper
+ if ((errorcode = qLibAvW_Init(&libavw_message)))
+ {
+ Con_Printf("LibAvW failed to initialize: %s\n", qLibAvW_ErrorString(errorcode));
+ Sys_UnloadLibrary(&libavw_dll);
+ }
+
+ Cvar_RegisterVariable(&cl_video_libavw_minwidth);
+ Cvar_RegisterVariable(&cl_video_libavw_minheight);
+ Cvar_RegisterVariable(&cl_video_libavw_scaler);
+
+ return true;
+}
+
+static void LibAvW_CloseLibrary(void)
+{
+ Sys_UnloadLibrary(&libavw_dll);
+}
+
r_meshbuffer_t *animcache_vertex3fbuffer;
r_vertexmesh_t *animcache_vertexmesh;
r_meshbuffer_t *animcache_vertexmeshbuffer;
+ // gpu-skinning shader needs transforms in a certain format
+ // if this is not NULL, the other animcache variables are NULL
+ float *animcache_skeletaltransform3x4;
// current lighting from map (updated ONLY by client code, not renderer)
vec3_t modellight_ambient;
double last_trace_visibility;
// user wavefunc parameters (from csqc)
- float userwavefunc_param[Q3WAVEFUNC_USER_COUNT];
+ vec_t userwavefunc_param[Q3WAVEFUNC_USER_COUNT];
}
entity_render_t;
typedef struct entity_persistent_s
{
- vec3_t trail_origin;
-
- // particle trail
- float trail_time;
+ vec3_t trail_origin; // previous position for particle trail spawning
+ vec3_t oldorigin; // lerp
+ vec3_t oldangles; // lerp
+ vec3_t neworigin; // lerp
+ vec3_t newangles; // lerp
+ vec_t lerpstarttime; // lerp
+ vec_t lerpdeltatime; // lerp
+ float muzzleflash; // muzzleflash intensity, fades over time
+ float trail_time; // residual error accumulation for particle trail spawning (to keep spacing across frames)
qboolean trail_allowed; // set to false by teleports, true by update code, prevents bad lerps
-
- // muzzleflash fading
- float muzzleflash;
-
- // interpolated movement
-
- // start time of move
- float lerpstarttime;
- // time difference from start to end of move
- float lerpdeltatime;
- // the move itself, start and end
- float oldorigin[3];
- float oldangles[3];
- float neworigin[3];
- float newangles[3];
}
entity_persistent_t;
int proquake_servermod; // 0 = not proquake, 1 = proquake
int proquake_serverversion; // actual proquake server version * 10 (3.40 = 34, etc)
int proquake_serverflags; // 0 (PQF_CHEATFREE not supported)
+
+ // don't write-then-read csprogs.dat (useful for demo playback)
+ unsigned char *caughtcsprogsdata;
+ fs_offset_t caughtcsprogsdatasize;
}
client_static_t;
// #1 void(vector ang) makevectors
static void VM_CL_makevectors (prvm_prog_t *prog)
{
+ vec3_t angles, forward, right, up;
VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
- AngleVectors (PRVM_G_VECTOR(OFS_PARM0), PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), angles);
+ AngleVectors(angles, forward, right, up);
+ VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+ VectorCopy(right, PRVM_clientglobalvector(v_right));
+ VectorCopy(up, PRVM_clientglobalvector(v_up));
}
// #2 void(entity e, vector o) setorigin
static void VM_CL_setorigin (prvm_prog_t *prog)
{
prvm_edict_t *e;
- float *org;
+ prvm_vec_t *org;
VM_SAFEPARMCOUNT(2, VM_CL_setorigin);
e = PRVM_G_EDICT(OFS_PARM0);
CL_LinkEdict(e);
}
-static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max)
+static void SetMinMaxSizePRVM (prvm_prog_t *prog, prvm_edict_t *e, prvm_vec_t *min, prvm_vec_t *max)
{
int i;
CL_LinkEdict (e);
}
+static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, const vec_t *min, const vec_t *max)
+{
+ prvm_vec3_t mins, maxs;
+ VectorCopy(min, mins);
+ VectorCopy(max, maxs);
+ SetMinMaxSizePRVM(prog, e, mins, maxs);
+}
+
// #3 void(entity e, string m) setmodel
static void VM_CL_setmodel (prvm_prog_t *prog)
{
if( mod ) {
// TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
- //SetMinMaxSize (e, mod->normalmins, mod->normalmaxs);
+ // LordHavoc: erm you broke it by commenting this out - setmodel must do setsize or else the qc can't find out the model size, and ssqc does this by necessity, consistency.
+ SetMinMaxSize (prog, e, mod->normalmins, mod->normalmaxs);
}
else
{
static void VM_CL_setsize (prvm_prog_t *prog)
{
prvm_edict_t *e;
- float *min, *max;
+ vec3_t mins, maxs;
VM_SAFEPARMCOUNT(3, VM_CL_setsize);
e = PRVM_G_EDICT(OFS_PARM0);
VM_Warning(prog, "setsize: can not modify free entity\n");
return;
}
- min = PRVM_G_VECTOR(OFS_PARM1);
- max = PRVM_G_VECTOR(OFS_PARM2);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
- SetMinMaxSize( prog, e, min, max );
+ SetMinMaxSize( prog, e, mins, maxs );
CL_LinkEdict(e);
}
// #16 void(vector v1, vector v2, float movetype, entity ignore) traceline
static void VM_CL_traceline (prvm_prog_t *prog)
{
- float *v1, *v2;
+ vec3_t v1, v2;
trace_t trace;
int move, svent;
prvm_edict_t *ent;
prog->xfunction->builtinsprofile += 30;
- v1 = PRVM_G_VECTOR(OFS_PARM0);
- v2 = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
move = (int)PRVM_G_FLOAT(OFS_PARM2);
ent = PRVM_G_EDICT(OFS_PARM3);
- if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
+ if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
// LordHavoc: added this for my own use, VERY useful, similar to traceline
static void VM_CL_tracebox (prvm_prog_t *prog)
{
- float *v1, *v2, *m1, *m2;
+ vec3_t v1, v2, m1, m2;
trace_t trace;
int move, svent;
prvm_edict_t *ent;
prog->xfunction->builtinsprofile += 30;
- v1 = PRVM_G_VECTOR(OFS_PARM0);
- m1 = PRVM_G_VECTOR(OFS_PARM1);
- m2 = PRVM_G_VECTOR(OFS_PARM2);
- v2 = PRVM_G_VECTOR(OFS_PARM3);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
move = (int)PRVM_G_FLOAT(OFS_PARM4);
ent = PRVM_G_EDICT(OFS_PARM5);
- if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
+ if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
{
int i;
float gravity;
- vec3_t move, end;
+ vec3_t start, end, mins, maxs, move;
vec3_t original_origin;
vec3_t original_velocity;
vec3_t original_angles;
VectorMA (PRVM_clientedictvector(tossent, angles), 0.05, PRVM_clientedictvector(tossent, avelocity), PRVM_clientedictvector(tossent, angles));
VectorScale (PRVM_clientedictvector(tossent, velocity), 0.05, move);
VectorAdd (PRVM_clientedictvector(tossent, origin), move, end);
- trace = CL_TraceBox(PRVM_clientedictvector(tossent, origin), PRVM_clientedictvector(tossent, mins), PRVM_clientedictvector(tossent, maxs), end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
+ VectorCopy(PRVM_clientedictvector(tossent, origin), start);
+ VectorCopy(PRVM_clientedictvector(tossent, mins), mins);
+ VectorCopy(PRVM_clientedictvector(tossent, maxs), maxs);
+ trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
VectorCopy (trace.endpos, PRVM_clientedictvector(tossent, origin));
if (trace.fraction < 1)
static void VM_CL_droptofloor (prvm_prog_t *prog)
{
prvm_edict_t *ent;
- vec3_t end;
+ vec3_t start, end, mins, maxs;
trace_t trace;
VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
return;
}
- VectorCopy (PRVM_clientedictvector(ent, origin), end);
+ VectorCopy(PRVM_clientedictvector(ent, origin), start);
+ VectorCopy(PRVM_clientedictvector(ent, mins), mins);
+ VectorCopy(PRVM_clientedictvector(ent, maxs), maxs);
+ VectorCopy(PRVM_clientedictvector(ent, origin), end);
end[2] -= 256;
- trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+ trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
if (trace.fraction != 1)
{
// #41 float(vector v) pointcontents
static void VM_CL_pointcontents (prvm_prog_t *prog)
{
+ vec3_t point;
VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
- PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
+ PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(point));
}
// #48 void(vector o, vector d, float color, float count) particle
static void VM_CL_particle (prvm_prog_t *prog)
{
- float *org, *dir;
+ vec3_t org, dir;
int count;
unsigned char color;
VM_SAFEPARMCOUNT(4, VM_CL_particle);
- org = PRVM_G_VECTOR(OFS_PARM0);
- dir = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
color = (int)PRVM_G_FLOAT(OFS_PARM2);
count = (int)PRVM_G_FLOAT(OFS_PARM3);
CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
// #74 void(vector pos, string samp, float vol, float atten) ambientsound
static void VM_CL_ambientsound (prvm_prog_t *prog)
{
- float *f;
+ vec3_t f;
sfx_t *s;
VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
s = S_FindName(PRVM_G_STRING(OFS_PARM0));
- f = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f);
S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
}
static void VM_CL_getlight (prvm_prog_t *prog)
{
vec3_t ambientcolor, diffusecolor, diffusenormal;
- vec_t *p;
+ vec3_t p;
VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight);
- p = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
VectorClear(ambientcolor);
VectorClear(diffusecolor);
VectorClear(diffusenormal);
static void VM_CL_R_SetView (prvm_prog_t *prog)
{
int c;
- float *f;
+ prvm_vec_t *f;
float k;
VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_R_SetView);
static void VM_CL_R_AddDynamicLight (prvm_prog_t *prog)
{
double t = Sys_DirtyTime();
- vec_t *org;
+ vec3_t org;
float radius = 300;
- vec_t *col;
+ vec3_t col;
int style = -1;
const char *cubemapname = NULL;
int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC;
if (r_refdef.scene.numlights >= MAX_DLIGHTS)
return;
- org = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
radius = PRVM_G_FLOAT(OFS_PARM1);
- col = PRVM_G_VECTOR(OFS_PARM2);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), col);
if (prog->argc >= 4)
{
style = (int)PRVM_G_FLOAT(OFS_PARM3);
//#310 vector (vector v) cs_unproject (EXT_CSQC)
static void VM_CL_unproject (prvm_prog_t *prog)
{
- float *f;
- vec3_t temp;
+ vec3_t f;
+ vec3_t temp;
+ vec3_t result;
VM_SAFEPARMCOUNT(1, VM_CL_unproject);
- f = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f);
VectorSet(temp,
f[2],
(-1.0 + 2.0 * (f[0] / vid_conwidth.integer)) * f[2] * -r_refdef.view.frustum_x,
(-1.0 + 2.0 * (f[1] / vid_conheight.integer)) * f[2] * -r_refdef.view.frustum_y);
if(v_flipped.integer)
temp[1] = -temp[1];
- Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+ Matrix4x4_Transform(&r_refdef.view.matrix, temp, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
}
//#311 vector (vector v) cs_project (EXT_CSQC)
static void VM_CL_project (prvm_prog_t *prog)
{
- float *f;
- vec3_t v;
+ vec3_t f;
+ vec3_t v;
matrix4x4_t m;
VM_SAFEPARMCOUNT(1, VM_CL_project);
- f = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f);
Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
Matrix4x4_Transform(&m, f, v);
if(v_flipped.integer)
static void VM_CL_trailparticles (prvm_prog_t *prog)
{
int i;
- float *start, *end;
+ vec3_t start, end, velocity;
prvm_edict_t *t;
VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
t = PRVM_G_EDICT(OFS_PARM0);
i = (int)PRVM_G_FLOAT(OFS_PARM1);
- start = PRVM_G_VECTOR(OFS_PARM2);
- end = PRVM_G_VECTOR(OFS_PARM3);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
+ VectorCopy(PRVM_clientedictvector(t, velocity), velocity);
if (i < 0)
return;
- CL_ParticleEffect(i, 1, start, end, PRVM_clientedictvector(t, velocity), PRVM_clientedictvector(t, velocity), NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
+ CL_ParticleEffect(i, 1, start, end, velocity, velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
}
//#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
{
int i;
float n;
- float *f, *v;
+ vec3_t f, v;
VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
i = (int)PRVM_G_FLOAT(OFS_PARM0);
- f = PRVM_G_VECTOR(OFS_PARM1);
- v = PRVM_G_VECTOR(OFS_PARM2);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), v);
n = PRVM_G_FLOAT(OFS_PARM3);
if (i < 0)
return;
{
int effectnum;
// prvm_edict_t *own;
- float *origin_from, *origin_to, *dir_from, *dir_to;
+ vec3_t origin_from, origin_to, dir_from, dir_to;
float count;
int flags;
float tintmins[4], tintmaxs[4];
effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
// own = PRVM_G_EDICT(OFS_PARM1); // TODO find use for this
- origin_from = PRVM_G_VECTOR(OFS_PARM2);
- origin_to = PRVM_G_VECTOR(OFS_PARM3);
- dir_from = PRVM_G_VECTOR(OFS_PARM4);
- dir_to = PRVM_G_VECTOR(OFS_PARM5);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin_from);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin_to );
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM4), dir_from );
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM5), dir_to );
count = PRVM_G_FLOAT(OFS_PARM6);
if(prog->argc >= 8)
flags = PRVM_G_FLOAT(OFS_PARM7);
{
vec3_t origin;
Matrix4x4_OriginFromMatrix(&e->render.matrix, origin);
- dpsnprintf(t, sizeof(t), "%.9g %.9g %.9g", origin[0], origin[1], origin[2]);
+ dpsnprintf(t, sizeof(t), VECTOR_LOSSLESS_FORMAT, origin[0], origin[1], origin[2]);
}
}
if(!t[0])
//#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
static void VM_CL_setlistener (prvm_prog_t *prog)
{
+ vec3_t origin, forward, left, up;
VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
- Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), origin);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), forward);
+ VectorNegate(PRVM_G_VECTOR(OFS_PARM2), left);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), up);
+ Matrix4x4_FromVectors(&cl.csqc_listenermatrix, forward, left, up, origin);
cl.csqc_usecsqclistener = true; //use csqc listener at this frame
}
const char *name;
unsigned char *data;
unsigned char *buf;
- int size;
+ unsigned short size;
int i;
cachepic_t *pic;
VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
name = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
- size = MSG_ReadShort(&cl_message);
+ size = (unsigned short) MSG_ReadShort(&cl_message);
// check if a texture of that name exists
// if yes, it is used and the data is discarded
renderflags = (int)PRVM_clientedictfloat(ent, renderflags);
if (renderflags & RF_USEAXIS)
{
- vec3_t left;
+ vec3_t forward, left, up, origin;
+ VectorCopy(PRVM_clientglobalvector(v_forward), forward);
VectorNegate(PRVM_clientglobalvector(v_right), left);
- Matrix4x4_FromVectors(&staticent->render.matrix, PRVM_clientglobalvector(v_forward), left, PRVM_clientglobalvector(v_up), PRVM_clientedictvector(ent, origin));
+ VectorCopy(PRVM_clientglobalvector(v_up), up);
+ VectorCopy(PRVM_clientedictvector(ent, origin), origin);
+ Matrix4x4_FromVectors(&staticent->render.matrix, forward, left, up, origin);
Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
}
else
VM_Warning(prog, "copyentity: can not modify free entity\n");
return;
}
- memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
+ memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
CL_LinkEdict(out);
}
// #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
static void VM_CL_effect (prvm_prog_t *prog)
{
+#if 1
+ Con_Printf("WARNING: VM_CL_effect not implemented\n"); // FIXME: this needs to take modelname not modelindex, the csqc defs has it as string and so it shall be
+#else
+ vec3_t org;
VM_SAFEPARMCOUNT(5, VM_CL_effect);
- CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ CL_Effect(org, (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+#endif
}
// #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
static void VM_CL_te_blood (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, vel, pos2;
VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
if (PRVM_G_FLOAT(OFS_PARM2) < 1)
return;
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
CL_FindNonSolidLocation(pos, pos2, 4);
- CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+ CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
}
// #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
static void VM_CL_te_bloodshower (prvm_prog_t *prog)
{
vec_t speed;
- vec3_t vel1, vel2;
+ vec3_t mincorner, maxcorner, vel1, vel2;
VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
return;
vel2[0] = speed;
vel2[1] = speed;
vel2[2] = speed;
- CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+ CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), mincorner, maxcorner, vel1, vel2, NULL, 0);
}
// #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
static void VM_CL_te_explosionrgb (prvm_prog_t *prog)
{
- float *pos;
+ vec3_t pos;
vec3_t pos2;
matrix4x4_t tempmatrix;
VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 10);
CL_ParticleExplosion(pos2);
Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
// #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
static void VM_CL_te_particlecube (prvm_prog_t *prog)
{
+ vec3_t mincorner, maxcorner, vel;
VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
- CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+ CL_ParticleCube(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
}
// #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
static void VM_CL_te_particlerain (prvm_prog_t *prog)
{
+ vec3_t mincorner, maxcorner, vel;
VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
- CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+ CL_ParticleRain(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
}
// #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
static void VM_CL_te_particlesnow (prvm_prog_t *prog)
{
+ vec3_t mincorner, maxcorner, vel;
VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
- CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+ CL_ParticleRain(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
}
// #411 void(vector org, vector vel, float howmany) te_spark
static void VM_CL_te_spark (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2, vel;
VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
CL_FindNonSolidLocation(pos, pos2, 4);
- CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+ CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
}
extern cvar_t cl_sound_ric_gunshot;
// #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
static void VM_CL_te_gunshotquad (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if(cl_sound_ric_gunshot.integer >= 2)
// #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
static void VM_CL_te_spikequad (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
// #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
static void VM_CL_te_superspikequad (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
// #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
static void VM_CL_te_explosionquad (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 10);
CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
// #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
static void VM_CL_te_smallflash (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 10);
CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
}
// #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
static void VM_CL_te_customflash (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
matrix4x4_t tempmatrix;
VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
CL_AllocLightFlash(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
// #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_gunshot (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3)
// #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_spike (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
// #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_superspike (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
int rnd;
VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
// #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_explosion (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 10);
CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
// #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_tarexplosion (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 10);
CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
// #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_wizspike (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
// #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_knightspike (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
// #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_lavasplash (prvm_prog_t *prog)
{
+ vec3_t pos;
VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
- CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+ CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
}
// #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_teleport (prvm_prog_t *prog)
{
+ vec3_t pos;
VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
- CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+ CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
}
// #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_explosion2 (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2, color;
+ vec3_t pos, pos2, color;
matrix4x4_t tempmatrix;
int colorStart, colorLength;
unsigned char *tempcolor;
VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
CL_FindNonSolidLocation(pos, pos2, 10);
// #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_lightning1 (prvm_prog_t *prog)
{
+ vec3_t start, end;
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
- CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+ CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt, true);
}
// #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_lightning2 (prvm_prog_t *prog)
{
+ vec3_t start, end;
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
- CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+ CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt2, true);
}
// #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_lightning3 (prvm_prog_t *prog)
{
+ vec3_t start, end;
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
- CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+ CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt3, false);
}
// #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
static void VM_CL_te_beam (prvm_prog_t *prog)
{
+ vec3_t start, end;
VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
- CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+ CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_beam, false);
}
// #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
static void VM_CL_te_plasmaburn (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2;
VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
CL_FindNonSolidLocation(pos, pos2, 4);
CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
}
// #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
static void VM_CL_te_flamejet (prvm_prog_t *prog)
{
- float *pos;
- vec3_t pos2;
+ vec3_t pos, pos2, vel;
VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
if (PRVM_G_FLOAT(OFS_PARM2) < 1)
return;
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
CL_FindNonSolidLocation(pos, pos2, 4);
- CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+ CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
}
&& model->animscenes)
{
VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
- VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, cl.time);
VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
}
int parentindex;
const char *tagname;
int returncode;
- vec3_t fo, le, up, trans;
+ vec3_t forward, left, up, origin;
const dp_model_t *model;
VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
e = PRVM_G_EDICT(OFS_PARM0);
tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex);
- Matrix4x4_ToVectors(&tag_matrix, PRVM_clientglobalvector(v_forward), le, PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
- VectorScale(le, -1, PRVM_clientglobalvector(v_right));
+ Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
+ VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+ VectorScale(left, -1, PRVM_clientglobalvector(v_right));
+ VectorCopy(up, PRVM_clientglobalvector(v_up));
+ VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
model = CL_GetModelFromEdict(e);
VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
- VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, cl.time);
VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
CL_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
- Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
+ Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
PRVM_clientglobalfloat(gettaginfo_parent) = parentindex;
PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
- VectorCopy(trans, PRVM_clientglobalvector(gettaginfo_offset));
- VectorCopy(fo, PRVM_clientglobalvector(gettaginfo_forward));
- VectorScale(le, -1, PRVM_clientglobalvector(gettaginfo_right));
+ VectorCopy(forward, PRVM_clientglobalvector(gettaginfo_forward));
+ VectorScale(left, -1, PRVM_clientglobalvector(gettaginfo_right));
VectorCopy(up, PRVM_clientglobalvector(gettaginfo_up));
+ VectorCopy(origin, PRVM_clientglobalvector(gettaginfo_offset));
switch(returncode)
{
qboolean verified;
vmparticletheme_t *themes;
int max_themes;
- // global addresses
- float *particle_type;
- float *particle_blendmode;
- float *particle_orientation;
- float *particle_color1;
- float *particle_color2;
- float *particle_tex;
- float *particle_size;
- float *particle_sizeincrease;
- float *particle_alpha;
- float *particle_alphafade;
- float *particle_time;
- float *particle_gravity;
- float *particle_bounce;
- float *particle_airfriction;
- float *particle_liquidfriction;
- float *particle_originjitter;
- float *particle_velocityjitter;
- float *particle_qualityreduction;
- float *particle_stretch;
- float *particle_staincolor1;
- float *particle_staincolor2;
- float *particle_stainalpha;
- float *particle_stainsize;
- float *particle_staintex;
- float *particle_delayspawn;
- float *particle_delaycollision;
- float *particle_angle;
- float *particle_spin;
}vmparticlespawner_t;
vmparticlespawner_t vmpartspawner;
vmpartspawner.max_themes = maxthemes;
vmpartspawner.initialized = true;
vmpartspawner.verified = true;
- // get field addresses for fast querying (we can do 1000 calls of spawnparticle in a frame)
- vmpartspawner.particle_type = &PRVM_clientglobalfloat(particle_type);
- vmpartspawner.particle_blendmode = &PRVM_clientglobalfloat(particle_blendmode);
- vmpartspawner.particle_orientation = &PRVM_clientglobalfloat(particle_orientation);
- vmpartspawner.particle_color1 = PRVM_clientglobalvector(particle_color1);
- vmpartspawner.particle_color2 = PRVM_clientglobalvector(particle_color2);
- vmpartspawner.particle_tex = &PRVM_clientglobalfloat(particle_tex);
- vmpartspawner.particle_size = &PRVM_clientglobalfloat(particle_size);
- vmpartspawner.particle_sizeincrease = &PRVM_clientglobalfloat(particle_sizeincrease);
- vmpartspawner.particle_alpha = &PRVM_clientglobalfloat(particle_alpha);
- vmpartspawner.particle_alphafade = &PRVM_clientglobalfloat(particle_alphafade);
- vmpartspawner.particle_time = &PRVM_clientglobalfloat(particle_time);
- vmpartspawner.particle_gravity = &PRVM_clientglobalfloat(particle_gravity);
- vmpartspawner.particle_bounce = &PRVM_clientglobalfloat(particle_bounce);
- vmpartspawner.particle_airfriction = &PRVM_clientglobalfloat(particle_airfriction);
- vmpartspawner.particle_liquidfriction = &PRVM_clientglobalfloat(particle_liquidfriction);
- vmpartspawner.particle_originjitter = &PRVM_clientglobalfloat(particle_originjitter);
- vmpartspawner.particle_velocityjitter = &PRVM_clientglobalfloat(particle_velocityjitter);
- vmpartspawner.particle_qualityreduction = &PRVM_clientglobalfloat(particle_qualityreduction);
- vmpartspawner.particle_stretch = &PRVM_clientglobalfloat(particle_stretch);
- vmpartspawner.particle_staincolor1 = PRVM_clientglobalvector(particle_staincolor1);
- vmpartspawner.particle_staincolor2 = PRVM_clientglobalvector(particle_staincolor2);
- vmpartspawner.particle_stainalpha = &PRVM_clientglobalfloat(particle_stainalpha);
- vmpartspawner.particle_stainsize = &PRVM_clientglobalfloat(particle_stainsize);
- vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex);
- vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex);
- vmpartspawner.particle_delayspawn = &PRVM_clientglobalfloat(particle_delayspawn);
- vmpartspawner.particle_delaycollision = &PRVM_clientglobalfloat(particle_delaycollision);
- vmpartspawner.particle_angle = &PRVM_clientglobalfloat(particle_angle);
- vmpartspawner.particle_spin = &PRVM_clientglobalfloat(particle_spin);
- #undef getglobal
- #undef getglobalvector
}
// reset particle theme to default values
}
// particle theme -> QC globals
-static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme)
-{
- *vmpartspawner.particle_type = theme->typeindex;
- *vmpartspawner.particle_blendmode = theme->blendmode;
- *vmpartspawner.particle_orientation = theme->orientation;
- vmpartspawner.particle_color1[0] = (theme->color1 >> 16) & 0xFF; // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375...
- vmpartspawner.particle_color1[1] = (theme->color1 >> 8) & 0xFF;
- vmpartspawner.particle_color1[2] = (theme->color1 >> 0) & 0xFF;
- vmpartspawner.particle_color2[0] = (theme->color2 >> 16) & 0xFF;
- vmpartspawner.particle_color2[1] = (theme->color2 >> 8) & 0xFF;
- vmpartspawner.particle_color2[2] = (theme->color2 >> 0) & 0xFF;
- *vmpartspawner.particle_tex = (float)theme->tex;
- *vmpartspawner.particle_size = theme->size;
- *vmpartspawner.particle_sizeincrease = theme->sizeincrease;
- *vmpartspawner.particle_alpha = theme->alpha/256;
- *vmpartspawner.particle_alphafade = theme->alphafade/256;
- *vmpartspawner.particle_time = theme->lifetime;
- *vmpartspawner.particle_gravity = theme->gravity;
- *vmpartspawner.particle_bounce = theme->bounce;
- *vmpartspawner.particle_airfriction = theme->airfriction;
- *vmpartspawner.particle_liquidfriction = theme->liquidfriction;
- *vmpartspawner.particle_originjitter = theme->originjitter;
- *vmpartspawner.particle_velocityjitter = theme->velocityjitter;
- *vmpartspawner.particle_qualityreduction = theme->qualityreduction;
- *vmpartspawner.particle_stretch = theme->stretch;
- vmpartspawner.particle_staincolor1[0] = ((int)theme->staincolor1 >> 16) & 0xFF;
- vmpartspawner.particle_staincolor1[1] = ((int)theme->staincolor1 >> 8) & 0xFF;
- vmpartspawner.particle_staincolor1[2] = ((int)theme->staincolor1 >> 0) & 0xFF;
- vmpartspawner.particle_staincolor2[0] = ((int)theme->staincolor2 >> 16) & 0xFF;
- vmpartspawner.particle_staincolor2[1] = ((int)theme->staincolor2 >> 8) & 0xFF;
- vmpartspawner.particle_staincolor2[2] = ((int)theme->staincolor2 >> 0) & 0xFF;
- *vmpartspawner.particle_staintex = (float)theme->staintex;
- *vmpartspawner.particle_stainalpha = (float)theme->stainalpha/256;
- *vmpartspawner.particle_stainsize = (float)theme->stainsize;
- *vmpartspawner.particle_delayspawn = theme->delayspawn;
- *vmpartspawner.particle_delaycollision = theme->delaycollision;
- *vmpartspawner.particle_angle = theme->angle;
- *vmpartspawner.particle_spin = theme->spin;
+static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme, prvm_prog_t *prog)
+{
+ PRVM_clientglobalfloat(particle_type) = theme->typeindex;
+ PRVM_clientglobalfloat(particle_blendmode) = theme->blendmode;
+ PRVM_clientglobalfloat(particle_orientation) = theme->orientation;
+ // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375...
+ VectorSet(PRVM_clientglobalvector(particle_color1), (theme->color1 >> 16) & 0xFF, (theme->color1 >> 8) & 0xFF, (theme->color1 >> 0) & 0xFF);
+ VectorSet(PRVM_clientglobalvector(particle_color2), (theme->color2 >> 16) & 0xFF, (theme->color2 >> 8) & 0xFF, (theme->color2 >> 0) & 0xFF);
+ PRVM_clientglobalfloat(particle_tex) = (prvm_vec_t)theme->tex;
+ PRVM_clientglobalfloat(particle_size) = theme->size;
+ PRVM_clientglobalfloat(particle_sizeincrease) = theme->sizeincrease;
+ PRVM_clientglobalfloat(particle_alpha) = theme->alpha/256;
+ PRVM_clientglobalfloat(particle_alphafade) = theme->alphafade/256;
+ PRVM_clientglobalfloat(particle_time) = theme->lifetime;
+ PRVM_clientglobalfloat(particle_gravity) = theme->gravity;
+ PRVM_clientglobalfloat(particle_bounce) = theme->bounce;
+ PRVM_clientglobalfloat(particle_airfriction) = theme->airfriction;
+ PRVM_clientglobalfloat(particle_liquidfriction) = theme->liquidfriction;
+ PRVM_clientglobalfloat(particle_originjitter) = theme->originjitter;
+ PRVM_clientglobalfloat(particle_velocityjitter) = theme->velocityjitter;
+ PRVM_clientglobalfloat(particle_qualityreduction) = theme->qualityreduction;
+ PRVM_clientglobalfloat(particle_stretch) = theme->stretch;
+ VectorSet(PRVM_clientglobalvector(particle_staincolor1), ((int)theme->staincolor1 >> 16) & 0xFF, ((int)theme->staincolor1 >> 8) & 0xFF, ((int)theme->staincolor1 >> 0) & 0xFF);
+ VectorSet(PRVM_clientglobalvector(particle_staincolor2), ((int)theme->staincolor2 >> 16) & 0xFF, ((int)theme->staincolor2 >> 8) & 0xFF, ((int)theme->staincolor2 >> 0) & 0xFF);
+ PRVM_clientglobalfloat(particle_staintex) = (prvm_vec_t)theme->staintex;
+ PRVM_clientglobalfloat(particle_stainalpha) = (prvm_vec_t)theme->stainalpha/256;
+ PRVM_clientglobalfloat(particle_stainsize) = (prvm_vec_t)theme->stainsize;
+ PRVM_clientglobalfloat(particle_delayspawn) = theme->delayspawn;
+ PRVM_clientglobalfloat(particle_delaycollision) = theme->delaycollision;
+ PRVM_clientglobalfloat(particle_angle) = theme->angle;
+ PRVM_clientglobalfloat(particle_spin) = theme->spin;
}
// QC globals -> particle theme
-static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme)
-{
- theme->typeindex = (unsigned short)*vmpartspawner.particle_type;
- theme->blendmode = (pblend_t)(int)*vmpartspawner.particle_blendmode;
- theme->orientation = (porientation_t)(int)*vmpartspawner.particle_orientation;
- theme->color1 = ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]);
- theme->color2 = ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]);
- theme->tex = (int)*vmpartspawner.particle_tex;
- theme->size = *vmpartspawner.particle_size;
- theme->sizeincrease = *vmpartspawner.particle_sizeincrease;
- theme->alpha = *vmpartspawner.particle_alpha*256;
- theme->alphafade = *vmpartspawner.particle_alphafade*256;
- theme->lifetime = *vmpartspawner.particle_time;
- theme->gravity = *vmpartspawner.particle_gravity;
- theme->bounce = *vmpartspawner.particle_bounce;
- theme->airfriction = *vmpartspawner.particle_airfriction;
- theme->liquidfriction = *vmpartspawner.particle_liquidfriction;
- theme->originjitter = *vmpartspawner.particle_originjitter;
- theme->velocityjitter = *vmpartspawner.particle_velocityjitter;
- theme->qualityreduction = (*vmpartspawner.particle_qualityreduction) ? true : false;
- theme->stretch = *vmpartspawner.particle_stretch;
- theme->staincolor1 = ((int)vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]);
- theme->staincolor2 = (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]);
- theme->staintex =(int)*vmpartspawner.particle_staintex;
- theme->stainalpha = *vmpartspawner.particle_stainalpha*256;
- theme->stainsize = *vmpartspawner.particle_stainsize;
- theme->delayspawn = *vmpartspawner.particle_delayspawn;
- theme->delaycollision = *vmpartspawner.particle_delaycollision;
- theme->angle = *vmpartspawner.particle_angle;
- theme->spin = *vmpartspawner.particle_spin;
+static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme, prvm_prog_t *prog)
+{
+ theme->typeindex = (unsigned short)PRVM_clientglobalfloat(particle_type);
+ theme->blendmode = (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode);
+ theme->orientation = (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation);
+ theme->color1 = ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]);
+ theme->color2 = ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]);
+ theme->tex = (int)PRVM_clientglobalfloat(particle_tex);
+ theme->size = PRVM_clientglobalfloat(particle_size);
+ theme->sizeincrease = PRVM_clientglobalfloat(particle_sizeincrease);
+ theme->alpha = PRVM_clientglobalfloat(particle_alpha)*256;
+ theme->alphafade = PRVM_clientglobalfloat(particle_alphafade)*256;
+ theme->lifetime = PRVM_clientglobalfloat(particle_time);
+ theme->gravity = PRVM_clientglobalfloat(particle_gravity);
+ theme->bounce = PRVM_clientglobalfloat(particle_bounce);
+ theme->airfriction = PRVM_clientglobalfloat(particle_airfriction);
+ theme->liquidfriction = PRVM_clientglobalfloat(particle_liquidfriction);
+ theme->originjitter = PRVM_clientglobalfloat(particle_originjitter);
+ theme->velocityjitter = PRVM_clientglobalfloat(particle_velocityjitter);
+ theme->qualityreduction = PRVM_clientglobalfloat(particle_qualityreduction) != 0 ? true : false;
+ theme->stretch = PRVM_clientglobalfloat(particle_stretch);
+ theme->staincolor1 = ((int)PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]);
+ theme->staincolor2 = (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]);
+ theme->staintex =(int)PRVM_clientglobalfloat(particle_staintex);
+ theme->stainalpha = PRVM_clientglobalfloat(particle_stainalpha)*256;
+ theme->stainsize = PRVM_clientglobalfloat(particle_stainsize);
+ theme->delayspawn = PRVM_clientglobalfloat(particle_delayspawn);
+ theme->delaycollision = PRVM_clientglobalfloat(particle_delaycollision);
+ theme->angle = PRVM_clientglobalfloat(particle_angle);
+ theme->spin = PRVM_clientglobalfloat(particle_spin);
}
// init particle spawner interface
VM_Warning(prog, "VM_CL_ResetParticle: particle spawner not initialized\n");
return;
}
- VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+ VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
}
// void(float themenum) particletheme
if (themenum < 0 || themenum >= vmpartspawner.max_themes)
{
VM_Warning(prog, "VM_CL_ParticleTheme: bad theme number %i\n", themenum);
- VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+ VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
return;
}
if (vmpartspawner.themes[themenum].initialized == false)
{
VM_Warning(prog, "VM_CL_ParticleTheme: theme #%i not exists\n", themenum);
- VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+ VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
return;
}
// load particle theme into globals
- VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum]);
+ VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum], prog);
}
// float() saveparticletheme
return;
}
vmpartspawner.themes[themenum].initialized = true;
- VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]);
+ VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog);
PRVM_G_FLOAT(OFS_RETURN) = themenum;
return;
}
return;
}
vmpartspawner.themes[themenum].initialized = true;
- VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]);
+ VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog);
}
// void(float themenum) freeparticletheme
if (vmpartspawner.themes[themenum].initialized == false)
{
VM_Warning(prog, "VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum);
- VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+ VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
return;
}
// free theme
// returns 0 if failed, 1 if succesful
static void VM_CL_SpawnParticle (prvm_prog_t *prog)
{
- float *org, *dir;
+ vec3_t org, dir;
vmparticletheme_t *theme;
particle_t *part;
int themenum;
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
- org = PRVM_G_VECTOR(OFS_PARM0);
- dir = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
if (prog->argc < 3) // global-set particle
{
- part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)(vmpartspawner.particle_color1[0]) << 16) + ((int)(vmpartspawner.particle_color1[1]) << 8) + ((int)(vmpartspawner.particle_color1[2])), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, (int)(vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]), (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+ part = CL_NewParticle(org,
+ (unsigned short)PRVM_clientglobalfloat(particle_type),
+ ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]),
+ ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]),
+ (int)PRVM_clientglobalfloat(particle_tex),
+ PRVM_clientglobalfloat(particle_size),
+ PRVM_clientglobalfloat(particle_sizeincrease),
+ PRVM_clientglobalfloat(particle_alpha)*256,
+ PRVM_clientglobalfloat(particle_alphafade)*256,
+ PRVM_clientglobalfloat(particle_gravity),
+ PRVM_clientglobalfloat(particle_bounce),
+ org[0],
+ org[1],
+ org[2],
+ dir[0],
+ dir[1],
+ dir[2],
+ PRVM_clientglobalfloat(particle_airfriction),
+ PRVM_clientglobalfloat(particle_liquidfriction),
+ PRVM_clientglobalfloat(particle_originjitter),
+ PRVM_clientglobalfloat(particle_velocityjitter),
+ (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false,
+ PRVM_clientglobalfloat(particle_time),
+ PRVM_clientglobalfloat(particle_stretch),
+ (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode),
+ (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation),
+ (int)(PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]),
+ (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]),
+ (int)PRVM_clientglobalfloat(particle_staintex),
+ PRVM_clientglobalfloat(particle_stainalpha)*256,
+ PRVM_clientglobalfloat(particle_stainsize),
+ PRVM_clientglobalfloat(particle_angle),
+ PRVM_clientglobalfloat(particle_spin),
+ NULL);
if (!part)
{
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
- if (*vmpartspawner.particle_delayspawn)
- part->delayedspawn = cl.time + *vmpartspawner.particle_delayspawn;
- //if (*vmpartspawner.particle_delaycollision)
- // part->delayedcollisions = cl.time + *vmpartspawner.particle_delaycollision;
+ if (PRVM_clientglobalfloat(particle_delayspawn))
+ part->delayedspawn = cl.time + PRVM_clientglobalfloat(particle_delayspawn);
+ //if (PRVM_clientglobalfloat(particle_delaycollision))
+ // part->delayedcollisions = cl.time + PRVM_clientglobalfloat(particle_delaycollision);
}
else // quick themed particle
{
return;
}
theme = &vmpartspawner.themes[themenum];
- part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL);
+ part = CL_NewParticle(org,
+ theme->typeindex,
+ theme->color1,
+ theme->color2,
+ theme->tex,
+ theme->size,
+ theme->sizeincrease,
+ theme->alpha,
+ theme->alphafade,
+ theme->gravity,
+ theme->bounce,
+ org[0],
+ org[1],
+ org[2],
+ dir[0],
+ dir[1],
+ dir[2],
+ theme->airfriction,
+ theme->liquidfriction,
+ theme->originjitter,
+ theme->velocityjitter,
+ theme->qualityreduction,
+ theme->lifetime,
+ theme->stretch,
+ theme->blendmode,
+ theme->orientation,
+ theme->staincolor1,
+ theme->staincolor2,
+ theme->staintex,
+ theme->stainalpha,
+ theme->stainsize,
+ theme->angle,
+ theme->spin,
+ NULL);
if (!part)
{
PRVM_G_FLOAT(OFS_RETURN) = 0;
// returns 0 if failed, 1 if success
static void VM_CL_SpawnParticleDelayed (prvm_prog_t *prog)
{
- float *org, *dir;
+ vec3_t org, dir;
vmparticletheme_t *theme;
particle_t *part;
int themenum;
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
- org = PRVM_G_VECTOR(OFS_PARM0);
- dir = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
if (prog->argc < 5) // global-set particle
- part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+ part = CL_NewParticle(org,
+ (unsigned short)PRVM_clientglobalfloat(particle_type),
+ ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]),
+ ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]),
+ (int)PRVM_clientglobalfloat(particle_tex),
+ PRVM_clientglobalfloat(particle_size),
+ PRVM_clientglobalfloat(particle_sizeincrease),
+ PRVM_clientglobalfloat(particle_alpha)*256,
+ PRVM_clientglobalfloat(particle_alphafade)*256,
+ PRVM_clientglobalfloat(particle_gravity),
+ PRVM_clientglobalfloat(particle_bounce),
+ org[0],
+ org[1],
+ org[2],
+ dir[0],
+ dir[1],
+ dir[2],
+ PRVM_clientglobalfloat(particle_airfriction),
+ PRVM_clientglobalfloat(particle_liquidfriction),
+ PRVM_clientglobalfloat(particle_originjitter),
+ PRVM_clientglobalfloat(particle_velocityjitter),
+ (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false,
+ PRVM_clientglobalfloat(particle_time),
+ PRVM_clientglobalfloat(particle_stretch),
+ (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode),
+ (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation),
+ ((int)PRVM_clientglobalvector(particle_staincolor1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor1)[2]),
+ ((int)PRVM_clientglobalvector(particle_staincolor2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor2)[2]),
+ (int)PRVM_clientglobalfloat(particle_staintex),
+ PRVM_clientglobalfloat(particle_stainalpha)*256,
+ PRVM_clientglobalfloat(particle_stainsize),
+ PRVM_clientglobalfloat(particle_angle),
+ PRVM_clientglobalfloat(particle_spin),
+ NULL);
else // themed particle
{
themenum = (int)PRVM_G_FLOAT(OFS_PARM4);
return;
}
theme = &vmpartspawner.themes[themenum];
- part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL);
+ part = CL_NewParticle(org,
+ theme->typeindex,
+ theme->color1,
+ theme->color2,
+ theme->tex,
+ theme->size,
+ theme->sizeincrease,
+ theme->alpha,
+ theme->alphafade,
+ theme->gravity,
+ theme->bounce,
+ org[0],
+ org[1],
+ org[2],
+ dir[0],
+ dir[1],
+ dir[2],
+ theme->airfriction,
+ theme->liquidfriction,
+ theme->originjitter,
+ theme->velocityjitter,
+ theme->qualityreduction,
+ theme->lifetime,
+ theme->stretch,
+ theme->blendmode,
+ theme->orientation,
+ theme->staincolor1,
+ theme->staincolor2,
+ theme->staintex,
+ theme->stainalpha,
+ theme->stainsize,
+ theme->angle,
+ theme->spin,
+ NULL);
}
if (!part)
{
static void VM_CL_GetEntity (prvm_prog_t *prog)
{
int entnum, fieldnum;
- float org[3], v1[3], v2[3];
+ vec3_t forward, left, up, org;
VM_SAFEPARMCOUNT(2, VM_CL_GetEntityVec);
entnum = PRVM_G_FLOAT(OFS_PARM0);
PRVM_G_FLOAT(OFS_RETURN) = cl.entities_active[entnum];
break;
case 1: // origin
- Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN));
+ Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, org);
+ VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN));
break;
case 2: // forward
- Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN), v1, v2, org);
+ Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+ VectorCopy(forward, PRVM_G_VECTOR(OFS_RETURN));
break;
case 3: // right
- Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, PRVM_G_VECTOR(OFS_RETURN), v2, org);
+ Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+ VectorNegate(left, PRVM_G_VECTOR(OFS_RETURN));
break;
case 4: // up
- Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, v2, PRVM_G_VECTOR(OFS_RETURN), org);
+ Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+ VectorCopy(up, PRVM_G_VECTOR(OFS_RETURN));
break;
case 5: // scale
PRVM_G_FLOAT(OFS_RETURN) = Matrix4x4_ScaleFromMatrix(&cl.entities[entnum].render.matrix);
break;
case 6: // origin + v_forward, v_right, v_up
- Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
+ Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+ VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+ VectorNegate(left, PRVM_clientglobalvector(v_right));
+ VectorCopy(up, PRVM_clientglobalvector(v_up));
+ VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN));
break;
case 7: // alpha
PRVM_G_FLOAT(OFS_RETURN) = cl.entities[entnum].render.alpha;
for (i = 0;i < polys->num_triangles;i++)
{
VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL);
}
/*polys->num_triangles = 0; // now done after rendering the scene,
prvm_prog_t *prog = CLVM_prog;
float dz;
vec3_t oldorg, neworg, end, traceendpos;
+ vec3_t mins, maxs, start;
trace_t trace;
int i, svent;
prvm_edict_t *enemy;
// try the move
+ VectorCopy(PRVM_clientedictvector(ent, mins), mins);
+ VectorCopy(PRVM_clientedictvector(ent, maxs), maxs);
VectorCopy (PRVM_clientedictvector(ent, origin), oldorg);
VectorAdd (PRVM_clientedictvector(ent, origin), move, neworg);
if (dz < 30)
neworg[2] += 8;
}
- trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+ VectorCopy(PRVM_clientedictvector(ent, origin), start);
+ trace = CL_TraceBox(start, mins, maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
CL_VM_SetTraceGlobals(prog, &trace, svent);
VectorCopy (neworg, end);
end[2] -= sv_stepheight.value*2;
- trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+ trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
CL_VM_SetTraceGlobals(prog, &trace, svent);
if (trace.startsolid)
{
neworg[2] -= sv_stepheight.value;
- trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+ trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
CL_VM_SetTraceGlobals(prog, &trace, svent);
if (trace.startsolid)
VectorAdd(PRVM_serveredictvector(viewee, origin), PRVM_serveredictvector(viewee, maxs), ma);
#if 1
- if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+ if(!cl.worldmodel || !cl.worldmodel->brush.GetPVS || !cl.worldmodel->brush.BoxTouchingPVS)
{
// no PVS support on this worldmodel... darn
PRVM_G_FLOAT(OFS_RETURN) = 3;
return;
}
- pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
+ pvs = cl.worldmodel->brush.GetPVS(cl.worldmodel, viewpos);
if(!pvs)
{
// viewpos isn't in any PVS... darn
PRVM_G_FLOAT(OFS_RETURN) = 2;
return;
}
- PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, mi, ma);
+ PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, pvs, mi, ma);
#else
// using fat PVS like FTEQW does (slow)
- if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+ if(!cl.worldmodel || !cl.worldmodel->brush.FatPVS || !cl.worldmodel->brush.BoxTouchingPVS)
{
// no PVS support on this worldmodel... darn
PRVM_G_FLOAT(OFS_RETURN) = 3;
return;
}
- fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
+ fatpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
if(!fatpvsbytes)
{
// viewpos isn't in any PVS... darn
PRVM_G_FLOAT(OFS_RETURN) = 2;
return;
}
- PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, mi, ma);
+ PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, fatpvs, mi, ma);
#endif
}
int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
dp_model_t *model = CL_GetModelByIndex(modelindex);
- float blendfrac;
int numblends;
int bonenum;
int blendindex;
framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
frameblend_t frameblend[MAX_FRAMEBLENDS];
- matrix4x4_t blendedmatrix;
+ matrix4x4_t bonematrix;
matrix4x4_t matrix;
PRVM_G_FLOAT(OFS_RETURN) = 0;
if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
lastbone = min(lastbone, model->num_bones - 1);
lastbone = min(lastbone, skeleton->model->num_bones - 1);
VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
- VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
- blendfrac = 1.0f - retainfrac;
+ VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, cl.time);
for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
- frameblend[numblends].lerp *= blendfrac;
+ ;
for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
{
- memset(&blendedmatrix, 0, sizeof(blendedmatrix));
- Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
+ memset(&bonematrix, 0, sizeof(bonematrix));
for (blendindex = 0;blendindex < numblends;blendindex++)
{
Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
- Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
+ Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
}
- skeleton->relativetransforms[bonenum] = blendedmatrix;
+ Matrix4x4_Normalize3(&bonematrix, &bonematrix);
+ Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
}
PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
}
*/
matrix4x4_t m;
vec3_t v = {0, 0, 0};
- vec3_t x, y, z;
+ vec3_t a, x, y, z;
VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves);
- AngleVectorsFLU(PRVM_G_VECTOR(OFS_PARM0), x, y, z);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), a);
+ AngleVectorsFLU(a, x, y, z);
Matrix4x4_FromVectors(&m, x, y, z, v);
CL_RotateMoves(&m);
}
VM_log, // #532
VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
-NULL, // #535
-NULL, // #536
-NULL, // #537
-NULL, // #538
+VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
NULL, // #539
VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
// hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
// hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
// hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
// rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
if (gamemode == GAME_ROGUE)
{
partial = Cmd_Argv (1);
len = strlen(partial);
+ ispattern = (strchr(partial, '*') || strchr(partial, '?'));
}
else
{
partial = NULL;
len = 0;
+ ispattern = false;
}
- ispattern = partial && (strchr(partial, '*') || strchr(partial, '?'));
-
count = 0;
for (cmd = cmd_functions; cmd; cmd = cmd->next)
{
#endif
cvar_t collision_debug_tracelineasbox = {0, "collision_debug_tracelineasbox", "0", "workaround for any bugs in Collision_TraceLineBrushFloat by using Collision_TraceBrushBrushFloat"};
cvar_t collision_cache = {0, "collision_cache", "1", "store results of collision traces for next frame to reuse if possible (optimization)"};
+//cvar_t collision_triangle_neighborsides = {0, "collision_triangle_neighborsides", "1", "override automatic side generation if triangle has neighbors with face planes that form a convex edge (perfect solution, but can not work for all edges)"};
+cvar_t collision_triangle_bevelsides = {0, "collision_triangle_bevelsides", "1", "generate sloped edge planes on triangles - if 0, see axialedgeplanes"};
+cvar_t collision_triangle_axialsides = {0, "collision_triangle_axialsides", "1", "generate axially-aligned edge planes on triangles - otherwise use perpendicular edge planes"};
mempool_t *collision_mempool;
#endif
Cvar_RegisterVariable(&collision_debug_tracelineasbox);
Cvar_RegisterVariable(&collision_cache);
+// Cvar_RegisterVariable(&collision_triangle_neighborsides);
+ Cvar_RegisterVariable(&collision_triangle_bevelsides);
+ Cvar_RegisterVariable(&collision_triangle_axialsides);
collision_mempool = Mem_AllocPool("collision cache", 0, NULL);
Collision_Cache_Init(collision_mempool);
}
-void Collision_CalcPlanesForPolygonBrushFloat(colbrushf_t *brush)
+void Collision_CalcPlanesForTriangleBrushFloat(colbrushf_t *brush)
{
int i;
- float edge0[3], edge1[3], edge2[3], normal[3], dist, bestdist;
- colpointf_t *p, *p2;
+ float edge0[3], edge1[3], edge2[3];
+ colpointf_t *p;
- // FIXME: these probably don't actually need to be normalized if the collision code does not care
- if (brush->numpoints == 3)
+ TriangleNormal(brush->points[0].v, brush->points[1].v, brush->points[2].v, brush->planes[0].normal);
+ if (DotProduct(brush->planes[0].normal, brush->planes[0].normal) < 0.0001f)
{
- // optimized triangle case
- TriangleNormal(brush->points[0].v, brush->points[1].v, brush->points[2].v, brush->planes[0].normal);
- if (DotProduct(brush->planes[0].normal, brush->planes[0].normal) < 0.0001f)
- {
- // there's no point in processing a degenerate triangle (GIGO - Garbage In, Garbage Out)
- brush->numplanes = 0;
- return;
- }
- else
- {
- brush->numplanes = 5;
- brush->numedgedirs = 3;
- VectorNormalize(brush->planes[0].normal);
- brush->planes[0].dist = DotProduct(brush->points->v, brush->planes[0].normal);
- VectorNegate(brush->planes[0].normal, brush->planes[1].normal);
- brush->planes[1].dist = -brush->planes[0].dist;
- VectorSubtract(brush->points[2].v, brush->points[0].v, edge0);
- VectorSubtract(brush->points[0].v, brush->points[1].v, edge1);
- VectorSubtract(brush->points[1].v, brush->points[2].v, edge2);
- VectorCopy(edge0, brush->edgedirs[0].v);
- VectorCopy(edge1, brush->edgedirs[1].v);
- VectorCopy(edge2, brush->edgedirs[2].v);
-#if 1
- {
- float projectionnormal[3], projectionedge0[3], projectionedge1[3], projectionedge2[3];
- int i, best;
- float dist, bestdist;
- bestdist = fabs(brush->planes[0].normal[0]);
- best = 0;
- for (i = 1;i < 3;i++)
- {
- dist = fabs(brush->planes[0].normal[i]);
- if (bestdist < dist)
- {
- bestdist = dist;
- best = i;
- }
- }
- VectorClear(projectionnormal);
- if (brush->planes[0].normal[best] < 0)
- projectionnormal[best] = -1;
- else
- projectionnormal[best] = 1;
- VectorCopy(edge0, projectionedge0);
- VectorCopy(edge1, projectionedge1);
- VectorCopy(edge2, projectionedge2);
- projectionedge0[best] = 0;
- projectionedge1[best] = 0;
- projectionedge2[best] = 0;
- CrossProduct(projectionedge0, projectionnormal, brush->planes[2].normal);
- CrossProduct(projectionedge1, projectionnormal, brush->planes[3].normal);
- CrossProduct(projectionedge2, projectionnormal, brush->planes[4].normal);
- }
-#else
- CrossProduct(edge0, brush->planes->normal, brush->planes[2].normal);
- CrossProduct(edge1, brush->planes->normal, brush->planes[3].normal);
- CrossProduct(edge2, brush->planes->normal, brush->planes[4].normal);
-#endif
- VectorNormalize(brush->planes[2].normal);
- VectorNormalize(brush->planes[3].normal);
- VectorNormalize(brush->planes[4].normal);
- brush->planes[2].dist = DotProduct(brush->points[2].v, brush->planes[2].normal);
- brush->planes[3].dist = DotProduct(brush->points[0].v, brush->planes[3].normal);
- brush->planes[4].dist = DotProduct(brush->points[1].v, brush->planes[4].normal);
-
- if (developer_extra.integer)
- {
- // validation code
-#if 0
- float temp[3];
-
- VectorSubtract(brush->points[0].v, brush->points[1].v, edge0);
- VectorSubtract(brush->points[2].v, brush->points[1].v, edge1);
- CrossProduct(edge0, edge1, normal);
- VectorNormalize(normal);
- VectorSubtract(normal, brush->planes[0].normal, temp);
- if (VectorLength(temp) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: TriangleNormal gave wrong answer (%f %f %f != correct answer %f %f %f)\n", brush->planes->normal[0], brush->planes->normal[1], brush->planes->normal[2], normal[0], normal[1], normal[2]);
- if (fabs(DotProduct(brush->planes[1].normal, brush->planes[0].normal) - -1.0f) > 0.01f || fabs(brush->planes[1].dist - -brush->planes[0].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 1 (%f %f %f %f) is not opposite plane 0 (%f %f %f %f)\n", brush->planes[1].normal[0], brush->planes[1].normal[1], brush->planes[1].normal[2], brush->planes[1].dist, brush->planes[0].normal[0], brush->planes[0].normal[1], brush->planes[0].normal[2], brush->planes[0].dist);
-#if 0
- if (fabs(DotProduct(brush->planes[2].normal, brush->planes[0].normal)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 2 (%f %f %f %f) is not perpendicular to plane 0 (%f %f %f %f)\n", brush->planes[2].normal[0], brush->planes[2].normal[1], brush->planes[2].normal[2], brush->planes[2].dist, brush->planes[0].normal[0], brush->planes[0].normal[1], brush->planes[0].normal[2], brush->planes[2].dist);
- if (fabs(DotProduct(brush->planes[3].normal, brush->planes[0].normal)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 3 (%f %f %f %f) is not perpendicular to plane 0 (%f %f %f %f)\n", brush->planes[3].normal[0], brush->planes[3].normal[1], brush->planes[3].normal[2], brush->planes[3].dist, brush->planes[0].normal[0], brush->planes[0].normal[1], brush->planes[0].normal[2], brush->planes[3].dist);
- if (fabs(DotProduct(brush->planes[4].normal, brush->planes[0].normal)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 4 (%f %f %f %f) is not perpendicular to plane 0 (%f %f %f %f)\n", brush->planes[4].normal[0], brush->planes[4].normal[1], brush->planes[4].normal[2], brush->planes[4].dist, brush->planes[0].normal[0], brush->planes[0].normal[1], brush->planes[0].normal[2], brush->planes[4].dist);
- if (fabs(DotProduct(brush->planes[2].normal, edge0)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 2 (%f %f %f %f) is not perpendicular to edge 0 (%f %f %f to %f %f %f)\n", brush->planes[2].normal[0], brush->planes[2].normal[1], brush->planes[2].normal[2], brush->planes[2].dist, brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2], brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2]);
- if (fabs(DotProduct(brush->planes[3].normal, edge1)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 3 (%f %f %f %f) is not perpendicular to edge 1 (%f %f %f to %f %f %f)\n", brush->planes[3].normal[0], brush->planes[3].normal[1], brush->planes[3].normal[2], brush->planes[3].dist, brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2], brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2]);
- if (fabs(DotProduct(brush->planes[4].normal, edge2)) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: plane 4 (%f %f %f %f) is not perpendicular to edge 2 (%f %f %f to %f %f %f)\n", brush->planes[4].normal[0], brush->planes[4].normal[1], brush->planes[4].normal[2], brush->planes[4].dist, brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2], brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2]);
-#endif
-#endif
- if (fabs(DotProduct(brush->points[0].v, brush->planes[0].normal) - brush->planes[0].dist) > 0.01f || fabs(DotProduct(brush->points[1].v, brush->planes[0].normal) - brush->planes[0].dist) > 0.01f || fabs(DotProduct(brush->points[2].v, brush->planes[0].normal) - brush->planes[0].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: edges (%f %f %f to %f %f %f to %f %f %f) off front plane 0 (%f %f %f %f)\n", brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2], brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2], brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2], brush->planes[0].normal[0], brush->planes[0].normal[1], brush->planes[0].normal[2], brush->planes[0].dist);
- if (fabs(DotProduct(brush->points[0].v, brush->planes[1].normal) - brush->planes[1].dist) > 0.01f || fabs(DotProduct(brush->points[1].v, brush->planes[1].normal) - brush->planes[1].dist) > 0.01f || fabs(DotProduct(brush->points[2].v, brush->planes[1].normal) - brush->planes[1].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: edges (%f %f %f to %f %f %f to %f %f %f) off back plane 1 (%f %f %f %f)\n", brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2], brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2], brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2], brush->planes[1].normal[0], brush->planes[1].normal[1], brush->planes[1].normal[2], brush->planes[1].dist);
- if (fabs(DotProduct(brush->points[2].v, brush->planes[2].normal) - brush->planes[2].dist) > 0.01f || fabs(DotProduct(brush->points[0].v, brush->planes[2].normal) - brush->planes[2].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: edge 0 (%f %f %f to %f %f %f) off front plane 2 (%f %f %f %f)\n", brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2], brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2], brush->planes[2].normal[0], brush->planes[2].normal[1], brush->planes[2].normal[2], brush->planes[2].dist);
- if (fabs(DotProduct(brush->points[0].v, brush->planes[3].normal) - brush->planes[3].dist) > 0.01f || fabs(DotProduct(brush->points[1].v, brush->planes[3].normal) - brush->planes[3].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: edge 0 (%f %f %f to %f %f %f) off front plane 2 (%f %f %f %f)\n", brush->points[0].v[0], brush->points[0].v[1], brush->points[0].v[2], brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2], brush->planes[3].normal[0], brush->planes[3].normal[1], brush->planes[3].normal[2], brush->planes[3].dist);
- if (fabs(DotProduct(brush->points[1].v, brush->planes[4].normal) - brush->planes[4].dist) > 0.01f || fabs(DotProduct(brush->points[2].v, brush->planes[4].normal) - brush->planes[4].dist) > 0.01f)
- Con_DPrintf("Collision_CalcPlanesForPolygonBrushFloat: edge 0 (%f %f %f to %f %f %f) off front plane 2 (%f %f %f %f)\n", brush->points[1].v[0], brush->points[1].v[1], brush->points[1].v[2], brush->points[2].v[0], brush->points[2].v[1], brush->points[2].v[2], brush->planes[4].normal[0], brush->planes[4].normal[1], brush->planes[4].normal[2], brush->planes[4].dist);
- }
- }
+ // there's no point in processing a degenerate triangle (GIGO - Garbage In, Garbage Out)
+ // note that some of these exist in q3bsp bspline patches
+ brush->numplanes = 0;
+ return;
}
- else
+
+ // there are 5 planes (front, back, sides) and 3 edges
+ brush->numplanes = 5;
+ brush->numedgedirs = 3;
+ VectorNormalize(brush->planes[0].normal);
+ brush->planes[0].dist = DotProduct(brush->points->v, brush->planes[0].normal);
+ VectorNegate(brush->planes[0].normal, brush->planes[1].normal);
+ brush->planes[1].dist = -brush->planes[0].dist;
+ // edge directions are easy to calculate
+ VectorSubtract(brush->points[2].v, brush->points[0].v, edge0);
+ VectorSubtract(brush->points[0].v, brush->points[1].v, edge1);
+ VectorSubtract(brush->points[1].v, brush->points[2].v, edge2);
+ VectorCopy(edge0, brush->edgedirs[0].v);
+ VectorCopy(edge1, brush->edgedirs[1].v);
+ VectorCopy(edge2, brush->edgedirs[2].v);
+ // now select an algorithm to generate the side planes
+ if (collision_triangle_bevelsides.integer)
+ {
+ // use 45 degree slopes at the edges of the triangle to make a sinking trace error turn into "riding up" the slope rather than getting stuck
+ CrossProduct(edge0, brush->planes->normal, brush->planes[2].normal);
+ CrossProduct(edge1, brush->planes->normal, brush->planes[3].normal);
+ CrossProduct(edge2, brush->planes->normal, brush->planes[4].normal);
+ VectorNormalize(brush->planes[2].normal);
+ VectorNormalize(brush->planes[3].normal);
+ VectorNormalize(brush->planes[4].normal);
+ VectorAdd(brush->planes[2].normal, brush->planes[0].normal, brush->planes[2].normal);
+ VectorAdd(brush->planes[3].normal, brush->planes[0].normal, brush->planes[3].normal);
+ VectorAdd(brush->planes[4].normal, brush->planes[0].normal, brush->planes[4].normal);
+ VectorNormalize(brush->planes[2].normal);
+ VectorNormalize(brush->planes[3].normal);
+ VectorNormalize(brush->planes[4].normal);
+ }
+ else if (collision_triangle_axialsides.integer)
{
- // choose best surface normal for polygon's plane
- bestdist = 0;
- for (i = 0, p = brush->points + 1;i < brush->numpoints - 2;i++, p++)
+ float projectionnormal[3], projectionedge0[3], projectionedge1[3], projectionedge2[3];
+ int i, best;
+ float dist, bestdist;
+ bestdist = fabs(brush->planes[0].normal[0]);
+ best = 0;
+ for (i = 1;i < 3;i++)
{
- VectorSubtract(p[-1].v, p[0].v, edge0);
- VectorSubtract(p[1].v, p[0].v, edge1);
- CrossProduct(edge0, edge1, normal);
- //TriangleNormal(p[-1].v, p[0].v, p[1].v, normal);
- dist = DotProduct(normal, normal);
- if (i == 0 || bestdist < dist)
+ dist = fabs(brush->planes[0].normal[i]);
+ if (bestdist < dist)
{
bestdist = dist;
- VectorCopy(normal, brush->planes->normal);
+ best = i;
}
}
- if (bestdist < 0.0001f)
- {
- // there's no point in processing a degenerate triangle (GIGO - Garbage In, Garbage Out)
- brush->numplanes = 0;
- return;
- }
+ VectorClear(projectionnormal);
+ if (brush->planes[0].normal[best] < 0)
+ projectionnormal[best] = -1;
else
- {
- brush->numplanes = brush->numpoints + 2;
- VectorNormalize(brush->planes->normal);
- brush->planes->dist = DotProduct(brush->points->v, brush->planes->normal);
-
- // negate plane to create other side
- VectorNegate(brush->planes[0].normal, brush->planes[1].normal);
- brush->planes[1].dist = -brush->planes[0].dist;
- for (i = 0, p = brush->points + (brush->numpoints - 1), p2 = brush->points;i < brush->numpoints;i++, p = p2, p2++)
- {
- VectorSubtract(p->v, p2->v, edge0);
- CrossProduct(edge0, brush->planes->normal, brush->planes[i + 2].normal);
- VectorNormalize(brush->planes[i + 2].normal);
- brush->planes[i + 2].dist = DotProduct(p->v, brush->planes[i + 2].normal);
- }
- }
+ projectionnormal[best] = 1;
+ VectorCopy(edge0, projectionedge0);
+ VectorCopy(edge1, projectionedge1);
+ VectorCopy(edge2, projectionedge2);
+ projectionedge0[best] = 0;
+ projectionedge1[best] = 0;
+ projectionedge2[best] = 0;
+ CrossProduct(projectionedge0, projectionnormal, brush->planes[2].normal);
+ CrossProduct(projectionedge1, projectionnormal, brush->planes[3].normal);
+ CrossProduct(projectionedge2, projectionnormal, brush->planes[4].normal);
+ VectorNormalize(brush->planes[2].normal);
+ VectorNormalize(brush->planes[3].normal);
+ VectorNormalize(brush->planes[4].normal);
+ }
+ else
+ {
+ CrossProduct(edge0, brush->planes->normal, brush->planes[2].normal);
+ CrossProduct(edge1, brush->planes->normal, brush->planes[3].normal);
+ CrossProduct(edge2, brush->planes->normal, brush->planes[4].normal);
+ VectorNormalize(brush->planes[2].normal);
+ VectorNormalize(brush->planes[3].normal);
+ VectorNormalize(brush->planes[4].normal);
}
+ brush->planes[2].dist = DotProduct(brush->points[2].v, brush->planes[2].normal);
+ brush->planes[3].dist = DotProduct(brush->points[0].v, brush->planes[3].normal);
+ brush->planes[4].dist = DotProduct(brush->points[1].v, brush->planes[4].normal);
if (developer_extra.integer)
{
VectorCopy(vertex3f + element3i[tri * 3 + 2] * 3, points[2].v);
Collision_SnapCopyPoints(brush.numpoints, points, points, COLLISION_SNAPSCALE, COLLISION_SNAP);
Collision_CalcEdgeDirsForPolygonBrushFloat(&brush);
- Collision_CalcPlanesForPolygonBrushFloat(&brush);
+ Collision_CalcPlanesForTriangleBrushFloat(&brush);
//Collision_PrintBrushAsQHull(&brush, "brush");
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, &brush, &brush);
}
{
for (i = 0;i < numtriangles;i++, element3i += 3)
{
- if (TriangleOverlapsBox(vertex3f + element3i[0]*3, vertex3f + element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
+ if (TriangleBBoxOverlapsBox(vertex3f + element3i[0]*3, vertex3f + element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
{
VectorCopy(vertex3f + element3i[0] * 3, points[0].v);
VectorCopy(vertex3f + element3i[1] * 3, points[1].v);
VectorCopy(vertex3f + element3i[2] * 3, points[2].v);
Collision_SnapCopyPoints(brush.numpoints, points, points, COLLISION_SNAPSCALE, COLLISION_SNAP);
Collision_CalcEdgeDirsForPolygonBrushFloat(&brush);
- Collision_CalcPlanesForPolygonBrushFloat(&brush);
+ Collision_CalcPlanesForTriangleBrushFloat(&brush);
//Collision_PrintBrushAsQHull(&brush, "brush");
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, &brush, &brush);
}
VectorCopy(vertex3f + element3i[2] * 3, points[2].v);
Collision_SnapCopyPoints(brush.numpoints, points, points, COLLISION_SNAPSCALE, COLLISION_SNAP);
Collision_CalcEdgeDirsForPolygonBrushFloat(&brush);
- Collision_CalcPlanesForPolygonBrushFloat(&brush);
+ Collision_CalcPlanesForTriangleBrushFloat(&brush);
//Collision_PrintBrushAsQHull(&brush, "brush");
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, &brush, &brush);
}
VectorCopy(v2, points[2].v);
Collision_SnapCopyPoints(brush.numpoints, points, points, COLLISION_SNAPSCALE, COLLISION_SNAP);
Collision_CalcEdgeDirsForPolygonBrushFloat(&brush);
- Collision_CalcPlanesForPolygonBrushFloat(&brush);
+ Collision_CalcPlanesForTriangleBrushFloat(&brush);
//Collision_PrintBrushAsQHull(&brush, "brush");
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, &brush, &brush);
}
// cliptrace->inopen = true;
if (trace->inwater)
cliptrace->inwater = true;
- if ((trace->realfraction <= cliptrace->realfraction) && (VectorLength2(trace->plane.normal) > 0))
+ if ((trace->realfraction < cliptrace->realfraction) && (VectorLength2(trace->plane.normal) > 0))
{
cliptrace->fraction = trace->fraction;
cliptrace->realfraction = trace->realfraction;
}
colboxbrushf_t;
-void Collision_CalcPlanesForPolygonBrushFloat(colbrushf_t *brush);
+void Collision_CalcPlanesForTriangleBrushFloat(colbrushf_t *brush);
colbrushf_t *Collision_AllocBrushFromPermanentPolygonFloat(mempool_t *mempool, int numpoints, float *points, int supercontents, int q3surfaceflags, const texture_t *texture);
colbrushf_t *Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalplanes, const colplanef_t *originalplanes, int supercontents, int q3surfaceflags, const texture_t *texture, int hasaabbplanes);
void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const colbrushf_t *thatbrush_start, const colbrushf_t *thatbrush_end);
MSG_WriteCoord32f (sb, f);
}
-void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
+void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
{
MSG_WriteCoord (sb, v[0], protocol);
MSG_WriteCoord (sb, v[1], protocol);
return MSG_ReadCoord32f(sb);
}
-void MSG_ReadVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
+void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
{
v[0] = MSG_ReadCoord(sb, protocol);
v[1] = MSG_ReadCoord(sb, protocol);
{
case 0: // end of string
result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
- isContinuation = false;
goto out;
case '\n': // end of line
result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
{ GAME_HIPNOTIC, GAME_NORMAL, "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon
{ GAME_ROGUE, GAME_NORMAL, "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity
{ GAME_NEHAHRA, GAME_NORMAL, "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game
+{ GAME_QUOTH, GAME_NORMAL, "quoth", "-quoth", "Darkplaces-Quoth", "id1", "quoth", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -quoth runs the Quoth mod for playing community maps made for it
{ GAME_NEXUIZ, GAME_NEXUIZ, "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" }, // COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
{ GAME_XONOTIC, GAME_XONOTIC, "xonotic", "-xonotic", "Xonotic", "data", NULL, "xonotic", "xonotic" }, // COMMANDLINEOPTION: Game: -xonotic runs the multiplayer game Xonotic
{ GAME_TRANSFUSION, GAME_TRANSFUSION, "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" }, // COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
{ GAME_BATTLEMECH, GAME_BATTLEMECH, "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" }, // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
{ GAME_ZYMOTIC, GAME_ZYMOTIC, "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" }, // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
{ GAME_SETHERAL, GAME_SETHERAL, "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" }, // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
-{ GAME_SOM, GAME_NORMAL, "sonofman", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" }, // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
{ GAME_TENEBRAE, GAME_NORMAL, "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
{ GAME_NEOTERIC, GAME_NORMAL, "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" }, // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
{ GAME_OPENQUARTZ, GAME_NORMAL, "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" }, // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c);
-void MSG_WriteFloat (sizebuf_t *sb, float f);
+void MSG_WriteFloat (sizebuf_t *sb, vec_t f);
void MSG_WriteString (sizebuf_t *sb, const char *s);
void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s);
-void MSG_WriteAngle8i (sizebuf_t *sb, float f);
-void MSG_WriteAngle16i (sizebuf_t *sb, float f);
-void MSG_WriteAngle32f (sizebuf_t *sb, float f);
-void MSG_WriteCoord13i (sizebuf_t *sb, float f);
-void MSG_WriteCoord16i (sizebuf_t *sb, float f);
-void MSG_WriteCoord32f (sizebuf_t *sb, float f);
-void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol);
-void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol);
-void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol);
+void MSG_WriteAngle8i (sizebuf_t *sb, vec_t f);
+void MSG_WriteAngle16i (sizebuf_t *sb, vec_t f);
+void MSG_WriteAngle32f (sizebuf_t *sb, vec_t f);
+void MSG_WriteCoord13i (sizebuf_t *sb, vec_t f);
+void MSG_WriteCoord16i (sizebuf_t *sb, vec_t f);
+void MSG_WriteCoord32f (sizebuf_t *sb, vec_t f);
+void MSG_WriteCoord (sizebuf_t *sb, vec_t f, protocolversion_t protocol);
+void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol);
+void MSG_WriteAngle (sizebuf_t *sb, vec_t f, protocolversion_t protocol);
void MSG_BeginReading (sizebuf_t *sb);
int MSG_ReadLittleShort (sizebuf_t *sb);
float MSG_ReadCoord16i (sizebuf_t *sb);
float MSG_ReadCoord32f (sizebuf_t *sb);
float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol);
-void MSG_ReadVector (sizebuf_t *sb, float *v, protocolversion_t protocol);
+void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol);
float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol);
//@}
//============================================================================
GAME_NORMAL,
GAME_HIPNOTIC,
GAME_ROGUE,
+ GAME_QUOTH,
GAME_NEHAHRA,
GAME_NEXUIZ,
GAME_XONOTIC,
GAME_BATTLEMECH,
GAME_ZYMOTIC,
GAME_SETHERAL,
- GAME_SOM,
GAME_TENEBRAE, // full of evil hackery
GAME_NEOTERIC,
GAME_OPENQUARTZ, //this game sucks
while(*p)
{
int ch = u8_getchar(p, &q);
- if(ch >= 0xE000 && ch <= 0xE0FF)
+ if(ch >= 0xE000 && ch <= 0xE0FF && ((unsigned char) qfont_table[ch - 0xE000]) >= 0x20)
{
*p = qfont_table[ch - 0xE000];
if(q > p+1)
int clientid = -1, serverid = -1, wantserverid = -1;
qboolean server_can_auth = true;
char wantserver_idfp[FP64_SIZE+1];
- int wantserver_aeslevel;
+ int wantserver_aeslevel = 0;
// if we have a stored host key for the server, assume serverid to already be selected!
// (the loop will refuse to overwrite this one then)
// Client prog handling
//[515]: omg !!! optimize it ! a lot of hacks here and there also :P
-#define CSQC_RETURNVAL prog->globals.generic[OFS_RETURN]
+#define CSQC_RETURNVAL prog->globals.fp[OFS_RETURN]
#define CSQC_BEGIN
#define CSQC_END
//[515]: set globals before calling R_UpdateView, WEIRD CRAP
static void CSQC_SetGlobals (void)
{
+ vec3_t pmove_org;
prvm_prog_t *prog = CLVM_prog;
CSQC_BEGIN
PRVM_clientglobalfloat(time) = cl.time;
// LordHavoc: Spike says not to do this, but without pmove_org the
// CSQC is useless as it can't alter the view origin without
// completely replacing it
- Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, PRVM_clientglobalvector(pmove_org));
+ Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, pmove_org);
+ VectorCopy(pmove_org, PRVM_clientglobalvector(pmove_org));
VectorCopy(cl.movement_velocity, PRVM_clientglobalvector(pmove_vel));
PRVM_clientglobalfloat(pmove_onground) = cl.onground;
PRVM_clientglobalfloat(pmove_inwater) = cl.inwater;
// set up the animation data
VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed);
- VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model, cl.time);
VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend);
if (PRVM_clientedictfloat(ed, shadertime)) // hack for csprogs.dat files that do not set shadertime, leaves the value at entity spawn time
entrender->shadertime = PRVM_clientedictfloat(ed, shadertime);
R_DecalSystem_Reset(&entrender->decalsystem);
memset(entrender, 0, sizeof(*entrender));
World_UnlinkEdict(ed);
- memset(ed->fields.vp, 0, prog->entityfields * 4);
+ memset(ed->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
VM_RemoveEdictSkeleton(prog, ed);
World_Physics_RemoveFromEntity(&cl.world, ed);
World_Physics_RemoveJointFromEntity(&cl.world, ed);
return;
// see if the requested csprogs.dat file matches the requested crc
- csprogsdatacrc = -1;
if (!cls.demoplayback || csqc_usedemoprogs.integer)
{
csprogsfn = va(vabuf, sizeof(vabuf), "dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc);
- csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
+ if(cls.caughtcsprogsdata && cls.caughtcsprogsdatasize == requiredsize && CRC_Block(cls.caughtcsprogsdata, (size_t)cls.caughtcsprogsdatasize) == requiredcrc)
+ {
+ Con_DPrintf("Using buffered \"%s\"\n", csprogsfn);
+ csprogsdata = cls.caughtcsprogsdata;
+ csprogsdatasize = cls.caughtcsprogsdatasize;
+ cls.caughtcsprogsdata = NULL;
+ cls.caughtcsprogsdatasize = 0;
+ }
+ else
+ {
+ Con_DPrintf("Not using buffered \"%s\" (buffered: %p, %d)\n", csprogsfn, cls.caughtcsprogsdata, (int) cls.caughtcsprogsdatasize);
+ csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
+ }
}
if (!csprogsdata)
{
prog->error_cmd = Host_Error;
prog->ExecuteProgram = CLVM_ExecuteProgram;
- PRVM_Prog_Load(prog, csprogsfn, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals);
+ PRVM_Prog_Load(prog, csprogsfn, csprogsdata, csprogsdatasize, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals);
if (!prog->loaded)
{
if (!(c->flags & CVAR_ALLOCATED))
{
Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it was registered after init!\n", c->name);
+ cp = &c->next;
continue;
}
// remove this cvar, it did not exist at init
{
partial = Cmd_Argv (1);
len = strlen(partial);
+ ispattern = (strchr(partial, '*') || strchr(partial, '?'));
}
else
{
partial = NULL;
len = 0;
+ ispattern = false;
}
- ispattern = partial && (strchr(partial, '*') || strchr(partial, '?'));
-
count = 0;
for (cvar = cvar_vars; cvar; cvar = cvar->next)
{
// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
//
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING = 1;
+float FIELD_FLOAT = 2;
+float FIELD_VECTOR = 3;
+float FIELD_ENTITY = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
+//DP_QC_ENTITYSTRING
+void(string s) loadfromdata = #529;
+void(string s) loadfromfile = #530;
+void(string s) callfunction = #605;
+void(float fh, entity e) writetofile = #606;
+float(string s) isfunction = #607;
+void(entity e, string s) parseentitydata = #608;
+
// assorted builtins
const float STAT_MOVEVARS_TICRATE = 240;
const float STAT_MOVEVARS_TIMESCALE = 241;
vector gettaginfo_forward;
vector gettaginfo_right;
vector gettaginfo_up;
+float checkpvs(vector viewpos, entity viewee) = #240;
// string autocvar__cl_name;
//NOTE: copying a string-typed autocvar to another variable/field, and then
//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar
-//globals is UNDEFINED. Accessing autocvar globals after cvar_set()ing that
-//cvar in the same frame is IMPLEMENTATION DEFINED (an implementation may
-//either yield the previous, or the current, value). Whether autocvar globals,
+//globals is UNDEFINED. Accessing autocvar globals after changing that cvar in
+//the same frame by any means other than cvar_set() from the same QC VM is
+//IMPLEMENTATION DEFINED (an implementation may either yield the previous, or
+//the current, value). Changing them via cvar_set() in the same QC VM
+//immediately must reflect on the autocvar globals. Whether autocvar globals,
//after restoring a savegame, have the cvar's current value, or the original
//value at time of saving, is UNDEFINED. Restoring a savegame however must not
//restore the cvar values themselves.
//cvars that start with pattern but not with antipattern will be stored into the buffer
void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
+//DP_QC_STRINGBUFFERS_EXT_WIP
+//idea: VorteX
+//darkplaces implementation: VorteX
+//constant definitions:
+const float MATCH_AUTO = 0;
+const float MATCH_WHOLE = 1;
+const float MATCH_LEFT = 2;
+const float MATCH_RIGHT = 3;
+const float MATCH_MIDDLE = 4;
+const float MATCH_PATTERN = 5;
+//builtin definitions:
+float(string filename, float bufhandle) buf_loadfile = #535; // append each line of file as new buffer string, return 1 if succesful
+float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile = #536; // writes buffer strings as lines, returns 1 if succesful
+float(float bufhandle, string match, float matchrule, float startpos, float step) bufstr_find = #537; // returns string index
+float(string s, string pattern, float matchrule) matchpattern = #538; // returns 0/1
+float(string s, string pattern, float matchrule, float pos) matchpatternofs = #538;
+//description:
+//provides a set of functions to manipulate with string buffers
+//pattern wildcards: * - any character (or no characters), ? - any 1 character
+//Warning: This extension is work-in-progress, it may be changed/revamped/removed at any time, dont use it if you dont want any trouble
+//wip note: UTF8 is not supported yet
+
//DP_QC_STRREPLACE
//idea: Sajt
//darkplaces implementation: Sajt
float(string url, float id, string content_type, string data) uri_post = #513;
float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513;
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING = 1;
+float FIELD_FLOAT = 2;
+float FIELD_VECTOR = 3;
+float FIELD_ENTITY = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
// assorted undocumented extensions
string(string, float) netaddress_resolve = #625;
string(string search, string replace, string subject) strreplace = #484;
d = depth;
size = 0;
mipmaps = 0;
- w = width;
- h = height;
- d = depth;
for (;;)
{
s = w * h * d * sides * 4;
int subx;
const unsigned int * RESTRICT ini = (const unsigned int *)in4ub;
unsigned char * RESTRICT pixelmask = span->pixelmask;
- unsigned char * RESTRICT pixel = (unsigned char *)dpsoftrast.fb_colorpixels[0];
unsigned int * RESTRICT pixeli = (unsigned int *)dpsoftrast.fb_colorpixels[0];
- if (!pixel)
+ if (!pixeli)
return;
- pixel += (span->y * dpsoftrast.fb_width + span->x) * 4;
pixeli += span->y * dpsoftrast.fb_width + span->x;
// handle alphatest now (this affects depth writes too)
if (thread->shader_permutation & SHADERPERMUTATION_ALPHAKILL)
{
for (x = startx;x < endx;x++)
{
- z = buffer_z[x];
+ // z = buffer_z[x];
diffusetex[0] = buffer_texture_colorbgra8[x*4+0];
diffusetex[1] = buffer_texture_colorbgra8[x*4+1];
diffusetex[2] = buffer_texture_colorbgra8[x*4+2];
unsigned char buffer_texture_shirtbgra8[DPSOFTRAST_DRAW_MAXSPANLENGTH*4];
unsigned char buffer_FragColorbgra8[DPSOFTRAST_DRAW_MAXSPANLENGTH*4];
int x, startx = span->startx, endx = span->endx;
- float Color_Ambient[4], Color_Diffuse[4], Color_Specular[4], Color_Glow[4], Color_Pants[4], Color_Shirt[4], LightColor[4];
+ float Color_Ambient[4], Color_Diffuse[4], Color_Specular[4], /*Color_Glow[4],*/ Color_Pants[4], Color_Shirt[4], LightColor[4];
float CubeVectordata[4];
float CubeVectorslope[4];
float LightVectordata[4];
float CubeVector[4];
float attenuation;
int d[4];
+#if 0
Color_Glow[2] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Glow*4+0];
Color_Glow[1] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Glow*4+1];
Color_Glow[0] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Glow*4+2];
Color_Glow[3] = 0.0f;
+#endif
Color_Ambient[2] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4+0];
Color_Ambient[1] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4+1];
Color_Ambient[0] = thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4+2];
static void DPSOFTRAST_PixelShader_Refraction(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
- float z;
+ //float z;
int x, startx = span->startx, endx = span->endx;
// texture reads
float iw;
unsigned char c[4];
- z = buffer_z[x];
+ //z = buffer_z[x];
// " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
iw = 1.0f / (ModelViewProjectionPositiondata[3] + ModelViewProjectionPositionslope[3]*x); // / z
static void DPSOFTRAST_PixelShader_Water(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
- float z;
+ // float z;
int x, startx = span->startx, endx = span->endx;
// texture reads
unsigned char c2[4];
float Fresnel;
- z = buffer_z[x];
+ // z = buffer_z[x];
// " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
iw = 1.0f / (ModelViewProjectionPositiondata[3] + ModelViewProjectionPositionslope[3]*x); // / z
int depthslope;
unsigned int d;
unsigned char *pixelmask;
- DPSOFTRAST_State_Triangle *triangle;
- triangle = &thread->triangles[span->triangle];
depthpixel = dpsoftrast.fb_depthpixels + span->y * dpsoftrast.fb_width + span->x;
startx = span->startx;
endx = span->endx;
SHADERPERMUTATION_TRIPPY = 1<<27, ///< use trippy vertex shader effect
SHADERPERMUTATION_DEPTHRGB = 1<<28, ///< read/write depth values in RGB color coded format for older hardware without depth samplers
SHADERPERMUTATION_ALPHAGEN_VERTEX = 1<<29, ///< alphaGen vertex
- SHADERPERMUTATION_COUNT = 30 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_SKELETAL = 1<<30, ///< (skeletal models) use skeletal matrices to deform vertices (gpu-skinning)
+ SHADERPERMUTATION_COUNT = 31 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
unsigned int info_imageBmask;
unsigned int info_imageBshift;
unsigned int info_imagesize;
+ double info_aspectratio;
// current video frame (needed because of delta compression)
int videoframenum;
s->info_imagewidth = hz_bitstream_read_short(s->framedatablocks);
s->info_imageheight = hz_bitstream_read_short(s->framedatablocks);
s->info_framerate = (double) hz_bitstream_read_int(s->framedatablocks) * (1.0 / 65536.0);
+ s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
if (s->info_framerate > 0.0)
{
video->getheight = dpvsimpledecode_getheight;
video->getframerate = dpvsimpledecode_getframerate;
video->decodeframe = dpvsimpledecode_video;
+ video->getaspectratio = dpvsimpledecode_getaspectratio;
return s;
}
return s->info_framerate;
}
+// return aspect ratio of the stream
+double dpvsimpledecode_getaspectratio(void *stream)
+{
+ dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
+ return s->info_aspectratio;
+}
+
static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
{
unsigned int a, x, y, width, height;
// returns the framerate of the stream
double dpvsimpledecode_getframerate(void *stream);
+// returns aspect ratio of the stream
+double dpvsimpledecode_getaspectratio(void *stream);
+
// decodes a video frame to the supplied output pixels
int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
if (nonblocking)
opt |= O_NONBLOCK;
+ if(COM_CheckParm("-readonly") && mod != O_RDONLY)
+ return -1;
+
#ifdef WIN32
# if _MSC_VER >= 1400
_sopen_s(&handle, filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
void FS_mkdir (const char *path)
{
+ if(COM_CheckParm("-readonly"))
+ return;
+
#if WIN32
_mkdir (path);
#else
{
Con_Printf("Failed to load face %i of %s. Falling back to face 0\n", _face, name);
_face = 0;
- status = qFT_New_Memory_Face(font_ft2lib, (FT_Bytes)data, datasize, 0, (FT_Face*)&font->face);
+ status = qFT_New_Memory_Face(font_ft2lib, (FT_Bytes)data, datasize, _face, (FT_Face*)&font->face);
}
font->data = data;
if (status)
if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
return false;
- x1 = y1 = x2 = y2 = 0;
-
// transform all corners that are infront of the nearclip plane
VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
plane4f[3] = r_refdef.view.frustum[4].dist;
qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
// GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
+#ifdef USE_GLES2
+ // FIXME: separate stencil attachment on GLES
+ if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+#else
if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+#endif
if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
+#ifndef USE_GLES2
if (colortexture4 && qglDrawBuffersARB)
{
qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
}
+#endif
status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
if (status != GL_FRAMEBUFFER_COMPLETE)
{
if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
+#ifndef USE_GLES2
if (colortexture4 && qglDrawBuffersARB)
{
qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
}
+#endif
status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
if (status != GL_FRAMEBUFFER_COMPLETE)
{
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
- qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
- qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
+ qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_SkeletalIndex");
+ qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_SkeletalWeight");
#ifndef USE_GLES2
if(vid.support.gl20shaders130)
qglBindFragDataLocation(programobject, 0, "dp_FragColor");
else
qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]);
}
- else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
+ else if (gl_state.units[j].pointer_texcoord_gltype == (int)(GL_SHORT | 0x80000000))
{
const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
if (gl_state.units[j].pointer_texcoord_components == 4)
else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
{
const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f), sb[2] * (1.0f / 127.0f), sb[3] * (1.0f / 127.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f), sb[2] * (1.0f / 127.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f));
+ }
+ else if (gl_state.units[j].pointer_texcoord_gltype == GL_UNSIGNED_BYTE)
+ {
+ const GLubyte *sb = (const GLubyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+ if (gl_state.units[j].pointer_texcoord_components == 4)
+ qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f), sb[2] * (1.0f / 255.0f), sb[3] * (1.0f / 255.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 3)
+ qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f), sb[2] * (1.0f / 255.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 2)
+ qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f));
+ else if (gl_state.units[j].pointer_texcoord_components == 1)
+ qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f));
+ }
+ else if (gl_state.units[j].pointer_texcoord_gltype == (int)(GL_UNSIGNED_BYTE | 0x80000000))
+ {
+ const GLubyte *sb = (const GLubyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
if (gl_state.units[j].pointer_texcoord_components == 4)
qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]);
else if (gl_state.units[j].pointer_texcoord_components == 3)
gl_state.pointer_vertex_offset = bufferoffset;
CHECKGLERROR
GL_BindVBO(bufferobject);
- qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+ // LordHavoc: special flag added to gltype for unnormalized types
+ qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
break;
case RENDERPATH_D3D9:
gl_state.pointer_color_offset = bufferoffset;
CHECKGLERROR
GL_BindVBO(bufferobject);
- qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+ // LordHavoc: special flag added to gltype for unnormalized types
+ qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
}
else
unit->pointer_texcoord_vertexbuffer = vertexbuffer;
unit->pointer_texcoord_offset = bufferoffset;
GL_BindVBO(bufferobject);
- qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+ // LordHavoc: special flag added to gltype for unnormalized types
+ qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
}
}
else
{0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
{0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
{0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
+ {0, (int)((size_t)&((r_vertexmesh_t *)0)->skeletalindex4ub ), D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6},
+ {0, (int)((size_t)&((r_vertexmesh_t *)0)->skeletalweight4ub ), D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7},
D3DDECL_END()
};
R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
}
else
{
R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
}
break;
case RENDERPATH_GL13:
R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
return;
}
break;
R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
}
else
{
R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
}
break;
case RENDERPATH_GL13:
R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
return;
}
break;
R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , vertexbuffer, (int)((unsigned char *)vertex->skeletalindex4ub - (unsigned char *)vertex));
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , vertexbuffer, (int)((unsigned char *)vertex->skeletalweight4ub - (unsigned char *)vertex));
}
else
{
R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , NULL, 0);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , NULL, 0);
}
break;
case RENDERPATH_GL13:
void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
// sets the color array pointer (GL_Color only works when this is NULL)
void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
-// sets the texcoord array pointer for an array unit
+// sets the texcoord array pointer for an array unit, if GL_UNSIGNED_BYTE | 0x80000000 is specified it will be an unnormalized type (integer values)
void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
// returns current texture bound to this identifier
int R_Mesh_TexBound(unsigned int unitnum, int id);
// show up the right size in the menu even if they were replaced with
// higher or lower resolution versions
dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", pic->name);
- if (!strncmp(pic->name, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
+ if ((!strncmp(pic->name, "gfx/", 4) || (gamemode == GAME_BLOODOMNICIDE && !strncmp(pic->name, "locale/", 6))) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
{
if (developer_loading.integer)
Con_Printf("loading lump \"%s\"\n", pic->name);
else
width_of = fnt->width_of;
- for (i = 0;((bytes_left = *maxlen - (text - text_start)) > 0) && *text;)
+ i = 0;
+ while (((bytes_left = *maxlen - (text - text_start)) > 0) && *text)
{
size_t i0 = i;
nextch = ch = u8_getnchar(text, &text, bytes_left);
y += r_textshadow.value * vid.height / vid_conheight.value;
}
*/
- for (i = 0;((bytes_left = maxlen - (text - text_start)) > 0) && *text;)
+ while (((bytes_left = maxlen - (text - text_start)) > 0) && *text)
{
nextch = ch = u8_getnchar(text, &text, bytes_left);
i = text - text_start;
//
r_refdef_t r_refdef;
-cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
-cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
+cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
+cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
+cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
+cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
+cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
+cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
+cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
-cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
+cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
+cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
+cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
+cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
+
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
-cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
+cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
{"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
{"#define USETRIPPY\n", " trippy"},
{"#define USEDEPTHRGB\n", " depthrgb"},
- {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
+ {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
+ {"#define USESKELETAL\n", " skeletal"}
};
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
int loc_ShadowMap_Parameters;
int loc_ShadowMap_TextureScale;
int loc_SpecularPower;
+ int loc_Skeletal_Transform12;
int loc_UserVec1;
int loc_UserVec2;
int loc_UserVec3;
SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
+ SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
+ SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
};
-#define SHADERSTATICPARMS_COUNT 11
+#define SHADERSTATICPARMS_COUNT 13
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
else if (r_shadow_shadowmappcf)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
+ if (r_celshading.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
+ if (r_celoutlines.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
}
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
}
/// information about each possible shader permutation
p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
+ p->loc_Skeletal_Transform12 = qglGetUniformLocation(p->program, "Skeletal_Transform12");
p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
{
if (debugshader)
{
-// vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
-// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
}
vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
if (vsbuffer)
{
- vsbinsize = vsbuffer->GetBufferSize();
+ vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
- memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
- vsbuffer->Release();
+ memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
+ ID3DXBuffer_Release(vsbuffer);
}
if (vslog)
{
- strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
+ strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
- vslog->Release();
+ ID3DXBuffer_Release(vslog);
}
}
if (fragstring && fragstring[0])
{
if (debugshader)
{
-// psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
-// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
}
psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
if (psbuffer)
{
- psbinsize = psbuffer->GetBufferSize();
+ psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
- memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
- psbuffer->Release();
+ memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
+ ID3DXBuffer_Release(psbuffer);
}
if (pslog)
{
- strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
+ strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
- pslog->Release();
+ ID3DXBuffer_Release(pslog);
}
}
Sys_UnloadLibrary(&d3dx9_dll);
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
}
-void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
+void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
{
unsigned int permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
if (depthrgb)
permutation |= SHADERPERMUTATION_DEPTHRGB;
+ if (skeletal)
+ permutation |= SHADERPERMUTATION_SKELETAL;
+
if (vid.allowalphatocoverage)
GL_AlphaToCoverage(false);
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
- RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
R_SetupShader_SetPermutationHLSL(mode, permutation);
Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
case RENDERPATH_GLES2:
if (!vid.useinterleavedarrays)
{
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
+ R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
+ R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
+ R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
}
else
{
- RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
}
+ // this has to be after RSurf_PrepareVerticesForBatch
+ if (rsurface.batchskeletaltransform3x4)
+ permutation |= SHADERPERMUTATION_SKELETAL;
R_SetupShader_SetPermutationGLSL(mode, permutation);
if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
if (mode == SHADERMODE_LIGHTSOURCE)
}
}
if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
+ if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
+ qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
CHECKGLERROR
break;
case RENDERPATH_GL11:
case RENDERPATH_GLES1:
break;
case RENDERPATH_SOFT:
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
R_SetupShader_SetPermutationSoft(mode, permutation);
{Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
textureflags &= ~TEXF_FORCE_RELOAD;
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
- textureflags &= ~TEXF_FORCE_RELOAD;
+ //textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
textureflags &= ~TEXF_FORCE_RELOAD;
Cvar_RegisterVariable(&r_shadows_throwdirection);
Cvar_RegisterVariable(&r_shadows_focus);
Cvar_RegisterVariable(&r_shadows_shadowmapscale);
+ Cvar_RegisterVariable(&r_shadows_shadowmapbias);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
+ Cvar_RegisterVariable(&r_celshading);
+ Cvar_RegisterVariable(&r_celoutlines);
Cvar_RegisterVariable(&r_water);
Cvar_RegisterVariable(&r_water_resolutionmultiplier);
Cvar_RegisterVariable(&r_bloom_resolution);
Cvar_RegisterVariable(&r_bloom_colorexponent);
Cvar_RegisterVariable(&r_bloom_colorsubtract);
+ Cvar_RegisterVariable(&r_bloom_scenebrightness);
Cvar_RegisterVariable(&r_hdr_scenebrightness);
Cvar_RegisterVariable(&r_hdr_glowintensity);
Cvar_RegisterVariable(&r_hdr_irisadaptation);
Cvar_RegisterVariable(&developer_texturelogging);
Cvar_RegisterVariable(&gl_lightmaps);
Cvar_RegisterVariable(&r_test);
+ Cvar_RegisterVariable(&r_batch_multidraw);
+ Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
+ Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
+ Cvar_RegisterVariable(&r_glsl_skeletal);
Cvar_RegisterVariable(&r_glsl_saturation);
Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
ent->animcache_vertexmesh = NULL;
ent->animcache_vertex3fbuffer = NULL;
ent->animcache_vertexmeshbuffer = NULL;
+ ent->animcache_skeletaltransform3x4 = NULL;
}
}
{
dp_model_t *model = ent->model;
int numvertices;
+
+ // cache skeletal animation data first (primarily for gpu-skinning)
+ if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
+ {
+ int i;
+ int blends;
+ const skeleton_t *skeleton = ent->skeleton;
+ const frameblend_t *frameblend = ent->frameblend;
+ float *boneposerelative;
+ float m[12];
+ static float bonepose[256][12];
+ ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
+ boneposerelative = ent->animcache_skeletaltransform3x4;
+ if (skeleton && !skeleton->relativetransforms)
+ skeleton = NULL;
+ // resolve hierarchy and make relative transforms (deforms) which the shader wants
+ if (skeleton)
+ {
+ for (i = 0;i < model->num_bones;i++)
+ {
+ Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
+ if (model->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
+ else
+ memcpy(bonepose[i], m, sizeof(m));
+
+ // create a relative deformation matrix to describe displacement
+ // from the base mesh, which is used by the actual weighting
+ R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
+ }
+ }
+ else
+ {
+ for (i = 0;i < model->num_bones;i++)
+ {
+ const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
+ float lerp = frameblend[0].lerp,
+ tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
+ rx = pose7s[3] * lerp,
+ ry = pose7s[4] * lerp,
+ rz = pose7s[5] * lerp,
+ rw = pose7s[6] * lerp,
+ dx = tx*rw + ty*rz - tz*ry,
+ dy = -tx*rz + ty*rw + tz*rx,
+ dz = tx*ry - ty*rx + tz*rw,
+ dw = -tx*rx - ty*ry - tz*rz,
+ scale, sx, sy, sz, sw;
+ for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
+ {
+ const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
+ float lerp = frameblend[blends].lerp,
+ tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
+ qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
+ if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
+ qx *= lerp;
+ qy *= lerp;
+ qz *= lerp;
+ qw *= lerp;
+ rx += qx;
+ ry += qy;
+ rz += qz;
+ rw += qw;
+ dx += tx*qw + ty*qz - tz*qy;
+ dy += -tx*qz + ty*qw + tz*qx;
+ dz += tx*qy - ty*qx + tz*qw;
+ dw += -tx*qx - ty*qy - tz*qz;
+ }
+ scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
+ sx = rx * scale;
+ sy = ry * scale;
+ sz = rz * scale;
+ sw = rw * scale;
+ m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
+ m[1] = 2*(sx*ry - sw*rz);
+ m[2] = 2*(sx*rz + sw*ry);
+ m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
+ m[4] = 2*(sx*ry + sw*rz);
+ m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
+ m[6] = 2*(sy*rz - sw*rx);
+ m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
+ m[8] = 2*(sx*rz - sw*ry);
+ m[9] = 2*(sy*rz + sw*rx);
+ m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
+ m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
+ if (i == r_skeletal_debugbone.integer)
+ m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
+ m[3] *= r_skeletal_debugtranslatex.value;
+ m[7] *= r_skeletal_debugtranslatey.value;
+ m[11] *= r_skeletal_debugtranslatez.value;
+ if (model->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
+ else
+ memcpy(bonepose[i], m, sizeof(m));
+ // create a relative deformation matrix to describe displacement
+ // from the base mesh, which is used by the actual weighting
+ R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
+ }
+ }
+ }
+
// see if it's already cached this frame
if (ent->animcache_vertex3f)
{
// see if this ent is worth caching
if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
return false;
+ // skip entity if the shader backend has a cheaper way
+ if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer && !r_showsurfaces.integer) // FIXME add r_showsurfaces support to GLSL skeletal!
+ {
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ return false;
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ case RENDERPATH_D3D9:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
+ case RENDERPATH_SOFT:
+ break;
+ }
+ }
// get some memory for this entity and generate mesh data
numvertices = model->surfmesh.num_vertices;
ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
int i;
int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
- qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
return;
int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
r_waterstate_waterplane_t *p;
vec3_t visorigin;
- qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
char vabuf[1024];
originalview = r_refdef.view;
int i;
int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
int viewwidth, viewheight;
- qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
textype_t textype = TEXTYPE_COLORBUFFER;
switch (vid.renderpath)
{
case RENDERPATH_GL20:
r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
- if (vid.support.ext_framebuffer_object)
+ if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
{
if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
unsigned int permutation;
float uservecs[4][4];
+ R_EntityMatrix(&identitymatrix);
+
switch (vid.renderpath)
{
case RENDERPATH_GL20:
R_Shadow_UpdateWorldLightSelection();
R_Bloom_StartFrame();
+
+ // apply bloom brightness offset
+ if(r_fb.bloomtexture[0])
+ r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
+
R_Water_StartFrame();
// now we probably have an fbo to render into
if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
continue;
VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
}
}
vec3_t org;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
else
R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
}
-void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
+void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
{
vec3_t right1, right2, diff, normal;
{
int i;
const entity_render_t *ent = rsurface.entity;
- dp_model_t *model = ent->model;
+ dp_model_t *model = ent->model; // when calling this, ent must not be NULL
q3shaderinfo_layer_tcmod_t *tcmod;
if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
t->update_lastrenderframe = r_textureframe;
t->update_lastrenderentity = (void *)ent;
- if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
+ if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
t->camera_entity = ent->entitynumber;
else
t->camera_entity = 0;
t->basetexture = r_texture_grey128;
t->pantstexture = r_texture_black;
t->shirttexture = r_texture_black;
- t->nmaptexture = r_texture_blanknormalmap;
+ if (gl_lightmaps.integer < 2)
+ t->nmaptexture = r_texture_blanknormalmap;
t->glosstexture = r_texture_black;
t->glowtexture = NULL;
t->fogtexture = NULL;
t->reflectmasktexture = NULL;
t->backgroundbasetexture = NULL;
- t->backgroundnmaptexture = r_texture_blanknormalmap;
+ if (gl_lightmaps.integer < 2)
+ t->backgroundnmaptexture = r_texture_blanknormalmap;
t->backgroundglosstexture = r_texture_black;
t->backgroundglowtexture = NULL;
t->specularscale = 0;
rsurface.ent_alttextures = false;
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
+ rsurface.entityskeletaltransform3x4 = NULL;
+ rsurface.entityskeletalnumtransforms = 0;
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
+ rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
+ rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
+ rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
+ rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
+ rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
+ rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
rsurface.modelelement3i = model->surfmesh.data_element3i;
rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.batchtexcoordlightmap2f = NULL;
rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchskeletalindex4ub = NULL;
+ rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalindex4ub_bufferoffset = 0;
+ rsurface.batchskeletalweight4ub = NULL;
+ rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalweight4ub_bufferoffset = 0;
rsurface.batchvertexmesh = NULL;
rsurface.batchvertexmeshbuffer = NULL;
rsurface.batchvertex3fbuffer = NULL;
rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
}
- if (model->surfmesh.isanimated && model->AnimateVertices)
+ // if the animcache code decided it should use the shader path, skip the deform step
+ rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
+ rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
+ if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
{
if (ent->animcache_vertex3f)
{
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
+ rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
+ rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
+ rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
+ rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
+ rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
+ rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
rsurface.modelelement3i = model->surfmesh.data_element3i;
rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.batchtexcoordlightmap2f = NULL;
rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchskeletalindex4ub = NULL;
+ rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalindex4ub_bufferoffset = 0;
+ rsurface.batchskeletalweight4ub = NULL;
+ rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalweight4ub_bufferoffset = 0;
rsurface.batchvertexmesh = NULL;
rsurface.batchvertexmeshbuffer = NULL;
rsurface.batchvertex3fbuffer = NULL;
rsurface.ent_alttextures = false;
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
+ rsurface.entityskeletaltransform3x4 = NULL;
+ rsurface.entityskeletalnumtransforms = 0;
if (wanttangents)
{
rsurface.modelvertex3f = (float *)vertex3f;
rsurface.modeltexcoordlightmap2f = NULL;
rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
+ rsurface.modelskeletalindex4ub = NULL;
+ rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
+ rsurface.modelskeletalindex4ub_bufferoffset = 0;
+ rsurface.modelskeletalweight4ub = NULL;
+ rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
+ rsurface.modelskeletalweight4ub_bufferoffset = 0;
rsurface.modelelement3i = (int *)element3i;
rsurface.modelelement3i_indexbuffer = NULL;
rsurface.modelelement3i_bufferoffset = 0;
rsurface.batchtexcoordlightmap2f = NULL;
rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchskeletalindex4ub = NULL;
+ rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalindex4ub_bufferoffset = 0;
+ rsurface.batchskeletalweight4ub = NULL;
+ rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalweight4ub_bufferoffset = 0;
rsurface.batchvertexmesh = NULL;
rsurface.batchvertexmeshbuffer = NULL;
rsurface.batchvertex3fbuffer = NULL;
float scale;
float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
float waveparms[4];
+ unsigned char *ub;
q3shaderinfo_deform_t *deform;
const msurface_t *surface, *firstsurface;
r_vertexmesh_t *vertexmesh;
// check if any dynamic vertex processing must occur
dynamicvertex = false;
+ // a cvar to force the dynamic vertex path to be taken, for debugging
+ if (r_batch_debugdynamicvertexpath.integer)
+ dynamicvertex = true;
+
// if there is a chance of animated vertex colors, it's a dynamic batch
if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
{
dynamicvertex = true;
- batchneed |= BATCHNEED_NOGAPS;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
}
break;
case Q3DEFORM_AUTOSPRITE:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
break;
case Q3DEFORM_AUTOSPRITE2:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
break;
case Q3DEFORM_NORMAL:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
break;
case Q3DEFORM_WAVE:
if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
break; // if wavefunc is a nop, ignore this transform
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
break;
case Q3DEFORM_BULGE:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
break;
case Q3DEFORM_MOVE:
if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
break; // if wavefunc is a nop, ignore this transform
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX;
needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
break;
}
break;
case Q3TCGEN_LIGHTMAP:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
break;
case Q3TCGEN_VECTOR:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX;
needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
break;
case Q3TCGEN_ENVIRONMENT:
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
break;
}
if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
{
dynamicvertex = true;
- batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
}
if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
{
dynamicvertex = true;
- batchneed |= BATCHNEED_NOGAPS;
needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
}
- if (dynamicvertex || gaps || rsurface.batchfirstvertex)
+ // when the model data has no vertex buffer (dynamic mesh), we need to
+ // eliminate gaps
+ if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
+ batchneed |= BATCHNEED_NOGAPS;
+
+ // the caller can specify BATCHNEED_NOGAPS to force a batch with
+ // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
+ // we ensure this by treating the vertex batch as dynamic...
+ if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
+ dynamicvertex = true;
+
+ if (dynamicvertex)
{
// when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
+ if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
}
- // when the model data has no vertex buffer (dynamic mesh), we need to
- // eliminate gaps
- if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
- batchneed |= BATCHNEED_NOGAPS;
-
// if needsupdate, we have to do a dynamic vertex batch for sure
if (needsupdate & batchneed)
dynamicvertex = true;
if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
dynamicvertex = true;
- // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
- // also some drivers strongly dislike firstvertex
- if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
- dynamicvertex = true;
+ // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
+ if (dynamicvertex && rsurface.entityskeletaltransform3x4)
+ batchneed |= BATCHNEED_ARRAY_SKELETAL;
rsurface.batchvertex3f = rsurface.modelvertex3f;
rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
+ rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
+ rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
+ rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
+ rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
+ rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
rsurface.batchvertexmesh = rsurface.modelvertexmesh;
rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
rsurface.batchelement3s = rsurface.modelelement3s;
rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
+ rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
+ rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
// if any dynamic vertex processing has to occur in software, we copy the
// entire surface list together before processing to rebase the vertices
// copy the surface list together to avoid wasting upload bandwidth on the
// vertices in the gaps.
//
- // if gaps exist and we have a static vertex buffer, we still have to
- // combine the index buffer ranges into one dynamic index buffer.
+ // if gaps exist and we have a static vertex buffer, we can choose whether
+ // to combine the index buffer ranges into one dynamic index buffer or
+ // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
//
- // in all cases we end up with data that can be drawn in one call.
+ // in many cases the batch is reduced to one draw call.
+
+ rsurface.batchmultidraw = false;
+ rsurface.batchmultidrawnumsurfaces = 0;
+ rsurface.batchmultidrawsurfacelist = NULL;
if (!dynamicvertex)
{
// otherwise use the original static buffer with an appropriate offset
if (gaps)
{
+ if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
+ {
+ rsurface.batchmultidraw = true;
+ rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
+ rsurface.batchmultidrawsurfacelist = texturesurfacelist;
+ return;
+ }
// build a new triangle elements array for this batch
rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
rsurface.batchfirsttriangle = 0;
// now copy the vertex data into a combined array and make an index array
// (this is what Quake3 does all the time)
- //if (gaps || rsurface.batchfirstvertex)
+ // we also apply any skeletal animation here that would have been done in
+ // the vertex shader, because most of the dynamic vertex animation cases
+ // need actual vertex positions and normals
+ //if (dynamicvertex)
{
rsurface.batchvertex3fbuffer = NULL;
rsurface.batchvertexmesh = NULL;
rsurface.batchtexcoordlightmap2f = NULL;
rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchskeletalindex4ub = NULL;
+ rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalindex4ub_bufferoffset = 0;
+ rsurface.batchskeletalweight4ub = NULL;
+ rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
+ rsurface.batchskeletalweight4ub_bufferoffset = 0;
rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
rsurface.batchelement3i_indexbuffer = NULL;
rsurface.batchelement3i_bufferoffset = 0;
rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+ if (batchneed & BATCHNEED_ARRAY_SKELETAL)
+ {
+ rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
+ rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
+ }
numvertices = 0;
numtriangles = 0;
for (i = 0;i < texturenumsurfaces;i++)
else
memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
}
+ if (batchneed & BATCHNEED_ARRAY_SKELETAL)
+ {
+ if (rsurface.modelskeletalindex4ub)
+ {
+ memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
+ memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
+ }
+ else
+ {
+ memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
+ memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
+ ub = rsurface.batchskeletalweight4ub + 4*numvertices;
+ for (j = 0;j < surfacenumvertices;j++)
+ ub[j*4] = 255;
+ }
+ }
}
RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
numvertices += surfacenumvertices;
rsurface.batchnumtriangles = batchnumtriangles;
}
+ // apply skeletal animation that would have been done in the vertex shader
+ if (rsurface.batchskeletaltransform3x4)
+ {
+ const unsigned char *si;
+ const unsigned char *sw;
+ const float *t[4];
+ const float *b = rsurface.batchskeletaltransform3x4;
+ float *vp, *vs, *vt, *vn;
+ float w[4];
+ float m[3][4], n[3][4];
+ float tp[3], ts[3], tt[3], tn[3];
+ si = rsurface.batchskeletalindex4ub;
+ sw = rsurface.batchskeletalweight4ub;
+ vp = rsurface.batchvertex3f;
+ vs = rsurface.batchsvector3f;
+ vt = rsurface.batchtvector3f;
+ vn = rsurface.batchnormal3f;
+ memset(m[0], 0, sizeof(m));
+ memset(n[0], 0, sizeof(n));
+ for (i = 0;i < batchnumvertices;i++)
+ {
+ t[0] = b + si[0]*12;
+ if (sw[0] == 255)
+ {
+ // common case - only one matrix
+ m[0][0] = t[0][ 0];
+ m[0][1] = t[0][ 1];
+ m[0][2] = t[0][ 2];
+ m[0][3] = t[0][ 3];
+ m[1][0] = t[0][ 4];
+ m[1][1] = t[0][ 5];
+ m[1][2] = t[0][ 6];
+ m[1][3] = t[0][ 7];
+ m[2][0] = t[0][ 8];
+ m[2][1] = t[0][ 9];
+ m[2][2] = t[0][10];
+ m[2][3] = t[0][11];
+ }
+ else if (sw[2] + sw[3])
+ {
+ // blend 4 matrices
+ t[1] = b + si[1]*12;
+ t[2] = b + si[2]*12;
+ t[3] = b + si[3]*12;
+ w[0] = sw[0] * (1.0f / 255.0f);
+ w[1] = sw[1] * (1.0f / 255.0f);
+ w[2] = sw[2] * (1.0f / 255.0f);
+ w[3] = sw[3] * (1.0f / 255.0f);
+ // blend the matrices
+ m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
+ m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
+ m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
+ m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
+ m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
+ m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
+ m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
+ m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
+ m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
+ m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
+ m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
+ m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
+ }
+ else
+ {
+ // blend 2 matrices
+ t[1] = b + si[1]*12;
+ w[0] = sw[0] * (1.0f / 255.0f);
+ w[1] = sw[1] * (1.0f / 255.0f);
+ // blend the matrices
+ m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
+ m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
+ m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
+ m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
+ m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
+ m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
+ m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
+ m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
+ m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
+ m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
+ m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
+ m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
+ }
+ si += 4;
+ sw += 4;
+ // modify the vertex
+ VectorCopy(vp, tp);
+ vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
+ vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
+ vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
+ vp += 3;
+ if (vn)
+ {
+ // the normal transformation matrix is a set of cross products...
+ CrossProduct(m[1], m[2], n[0]);
+ CrossProduct(m[2], m[0], n[1]);
+ CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
+ VectorCopy(vn, tn);
+ vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
+ vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
+ vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
+ VectorNormalize(vn);
+ vn += 3;
+ if (vs)
+ {
+ VectorCopy(vs, ts);
+ vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
+ vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
+ vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
+ VectorNormalize(vs);
+ vs += 3;
+ VectorCopy(vt, tt);
+ vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
+ vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
+ vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
+ VectorNormalize(vt);
+ vt += 3;
+ }
+ }
+ }
+ rsurface.batchskeletaltransform3x4 = NULL;
+ rsurface.batchskeletalnumtransforms = 0;
+ }
+
// q1bsp surfaces rendered in vertex color mode have to have colors
// calculated based on lightstyles
if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
+ if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
+ {
+ for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
+ {
+ Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
+ Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
+ }
+ }
}
}
}
}
#endif
- R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+ if (rsurface.batchmultidraw)
+ {
+ // issue multiple draws rather than copying index data
+ int numsurfaces = rsurface.batchmultidrawnumsurfaces;
+ const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
+ int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
+ for (i = 0;i < numsurfaces;)
+ {
+ // combine consecutive surfaces as one draw
+ for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
+ if (surfacelist[j] != surfacelist[k] + 1)
+ break;
+ firstvertex = surfacelist[i]->num_firstvertex;
+ endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
+ firsttriangle = surfacelist[i]->num_firsttriangle;
+ endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
+ R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+ i = j;
+ }
+ }
+ else
+ {
+ // there is only one consecutive run of index data (may have been combined)
+ R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+ }
}
static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
d = 0;
if(!prepared)
{
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
prepared = true;
if(rsurface.batchnumvertices == 0)
break;
rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
rsurface.passcolor4f_vertexbuffer = 0;
rsurface.passcolor4f_bufferoffset = 0;
- for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
f = RSurf_FogVertex(v);
c2[0] = c[0] * f;
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
- R_SetupShader_DepthOrShadow(false, false);
+ R_SetupShader_DepthOrShadow(false, false, false);
// depth-only (masking)
GL_ColorMask(0,0,0,0);
// just to make sure that braindead drivers don't draw
// anything despite that colormask...
GL_BlendFunc(GL_ZERO, GL_ONE);
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
if (rsurface.batchvertex3fbuffer)
R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
else
R_Mesh_TexBind(1, 0);
R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
// generate a color array for the fog pass
- R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch();
break;
default:
switch (layer->type)
{
case TEXTURELAYERTYPE_LITTEXTURE:
- if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
+ if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
{
// two-pass lit texture with 2x rgbscale
// first the lightmap pass
R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ else if (FAKELIGHT_ENABLED)
+ RSurf_DrawBatch_GL11_FakeLight(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
else
RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
}
R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
}
// generate a color array for the fog pass
- R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch();
break;
default:
{
RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
- for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
{
VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
{
RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
- for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
{
unsigned char c = (vi << 3) * (1.0f / 256.0f);
VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
// R_Mesh_ResetTextureState();
- R_SetupShader_DepthOrShadow(false, false);
}
RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
+ R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
if (rsurface.batchvertex3fbuffer)
R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
else
center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
}
- R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
}
if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
return;
RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
if (rsurface.batchvertex3fbuffer)
R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
else
R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
+ R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
RSurf_DrawBatch();
}
for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
{
VectorLerp(loc->mins, 0.5f, loc->maxs, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
}
}
else
frametime = 0;
decalsystem->lastupdatetime = r_refdef.scene.time;
- decal = decalsystem->decals;
numdecals = decalsystem->numdecals;
for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
RSurf_ActiveModelEntity(ent, false, false, false);
decalsystem->lastupdatetime = r_refdef.scene.time;
- decal = decalsystem->decals;
faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
{
int triangleindex;
int bihleafindex;
- qboolean cullbox = ent == r_refdef.scene.worldentity;
+ qboolean cullbox = false;
const q3mbrush_t *brush;
const bih_t *bih = &model->collision_bih;
const bih_leaf_t *bihleaf;
float vertex3f[3][3];
GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
- cullbox = false;
for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
{
if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
texture.offsetscale = 1;
texture.specularscalemod = 1;
texture.specularpowermod = 1;
+ texture.transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
surface.texture = &texture;
surface.num_triangles = numtriangles;
VectorAdd(center, portal->points[i].position, center);
f = ixtable[portal->numpoints];
VectorScale(center, f, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
}
}
}
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
// R_Mesh_ResetTextureState();
- R_SetupShader_DepthOrShadow(false, false);
if (ent == r_refdef.scene.worldentity)
R_DrawWorldSurfaces(false, false, true, false, false);
else
VectorCopy(v[0], v2[0]);
VectorCopy(v[1], v2[1]);
VectorCopy(v[2], v2[2]);
- if (insidebox || TriangleOverlapsBox(v2[0], v2[1], v2[2], info->lightmins, info->lightmaxs))
+ if (insidebox || TriangleBBoxOverlapsBox(v2[0], v2[1], v2[2], info->lightmins, info->lightmaxs))
SVBSP_AddPolygon(&r_svbsp, 3, v2[0], true, NULL, NULL, 0);
}
}
VectorCopy(v[0], v2[0]);
VectorCopy(v[1], v2[1]);
VectorCopy(v[2], v2[2]);
- if (!insidebox && !TriangleOverlapsBox(v2[0], v2[1], v2[2], info->lightmins, info->lightmaxs))
+ if (!insidebox && !TriangleBBoxOverlapsBox(v2[0], v2[1], v2[2], info->lightmins, info->lightmaxs))
continue;
if (svbspactive && !(SVBSP_AddPolygon(&r_svbsp, 3, v2[0], false, NULL, NULL, 0) & 2))
continue;
}
--modelsurfacelistindex;
GL_CullFace(rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE ? GL_NONE : r_refdef.view.cullface_back);
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, batchnumsurfaces, batchsurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, batchnumsurfaces, batchsurfacelist);
if (rsurface.batchvertex3fbuffer)
R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
else
center[1] += r_refdef.view.forward[1]*ent->transparent_offset;
center[2] += r_refdef.view.forward[2]*ent->transparent_offset;
}
- R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : ((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort), center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
continue;
}
#define DEBUGGL
#ifdef DEBUGGL
+#ifdef USE_GLES2
+#define CHECKGLERROR {if (gl_paranoid.integer){if (gl_printcheckerror.integer) Con_Printf("CHECKGLERROR at %s:%d\n", __FILE__, __LINE__);errornumber = glGetError();if (errornumber) GL_PrintError(errornumber, __FILE__, __LINE__);}}
+#else
#define CHECKGLERROR {if (gl_paranoid.integer){if (gl_printcheckerror.integer) Con_Printf("CHECKGLERROR at %s:%d\n", __FILE__, __LINE__);errornumber = qglGetError ? qglGetError() : 0;if (errornumber) GL_PrintError(errornumber, __FILE__, __LINE__);}}
+#endif
extern int errornumber;
void GL_PrintError(int errornumber, const char *filename, int linenumber);
#else
aborts the current host frame and goes on with the next one
================
*/
+void Host_AbortCurrentFrame(void) DP_FUNC_NORETURN;
void Host_AbortCurrentFrame(void)
{
// in case we were previously nice, make us mean again
Host_Init();
realtime = 0;
- dirtytime = Sys_DirtyTime();
for (;;)
{
if (setjmp(host_abortframe))
// Look for clients who have spawned
playing = false;
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
- if(host_client->spawned)
+ if(host_client->begun)
if(host_client->netconnection)
playing = true;
if(sv.time < 10)
SV_SendClientMessages();
if (sv.paused == 1 && realtime > sv.pausedstart && sv.pausedstart > 0) {
- prog->globals.generic[OFS_PARM0] = realtime - sv.pausedstart;
+ prog->globals.fp[OFS_PARM0] = realtime - sv.pausedstart;
PRVM_serverglobalfloat(time) = sv.time;
prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
}
if (cls.demopaused)
clframetime = 0;
}
+ else
+ {
+ // host_framerate overrides all else
+ if (host_framerate.value)
+ clframetime = host_framerate.value;
- // host_framerate overrides all else
- if (host_framerate.value)
- clframetime = host_framerate.value;
-
- if (cl.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
- clframetime = 0;
+ if (cl.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
+ clframetime = 0;
+ }
if (cls.timedemo)
clframetime = cl.realframetime = cl_timer;
if(locksession_run)
return;
locksession_run = true;
- if(locksession.integer != 0)
+ if(locksession.integer != 0 && !COM_CheckParm("-readonly"))
{
char vabuf[1024];
char *p = va(vabuf, sizeof(vabuf), "%slock%s", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string);
while (entnum >= prog->max_edicts)
PRVM_MEM_IncreaseEdicts(prog);
ent = PRVM_EDICT_NUM(entnum);
- memset(ent->fields.vp, 0, prog->entityfields * 4);
+ memset(ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
ent->priv.server->free = false;
if(developer_entityparsing.integer)
PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
- if (host_client->spawned)
+ if (host_client->begun)
SV_BroadcastPrintf("%s ^7changed name to %s\n", host_client->old_name, host_client->name);
strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
// send notification to all clients
PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
if (strcmp(host_client->old_skin, host_client->playerskin))
{
- //if (host_client->spawned)
+ //if (host_client->begun)
// SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin);
strlcpy(host_client->old_skin, host_client->playerskin, sizeof(host_client->old_skin));
/*// send notification to all clients
if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
{
Con_DPrint("Calling SV_ChangeTeam\n");
- prog->globals.generic[OFS_PARM0] = playercolor;
+ prog->globals.fp[OFS_PARM0] = playercolor;
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
*/
static void Host_PreSpawn_f (void)
{
- if (host_client->spawned)
+ if (host_client->prespawned)
{
- Con_Print("prespawn not valid -- already spawned\n");
+ Con_Print("prespawn not valid -- already prespawned\n");
return;
}
+ host_client->prespawned = true;
if (host_client->netconnection)
{
client_t *client;
int stats[MAX_CL_STATS];
+ if (!host_client->prespawned)
+ {
+ Con_Print("Spawn not valid -- not yet prespawned\n");
+ return;
+ }
if (host_client->spawned)
{
Con_Print("Spawn not valid -- already spawned\n");
return;
}
+ host_client->spawned = true;
// reset name change timer again because they might want to change name
// again in the first 5 seconds after connecting
*/
static void Host_Begin_f (void)
{
- host_client->spawned = true;
+ if (!host_client->spawned)
+ {
+ Con_Print("Begin not valid -- not yet spawned\n");
+ return;
+ }
+ if (host_client->begun)
+ {
+ Con_Print("Begin not valid -- already begun\n");
+ return;
+ }
+ host_client->begun = true;
// LordHavoc: note: this code also exists in SV_DropClient
if (sv.loadgame)
case '8':
case '9':
// MED 01/04/97 added hipnotic give stuff
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
if (t[0] == '6')
{
lhnetsocket_t *mysocket;
char peer_address[64];
+ if (Cmd_Argc() == 1)
+ {
+ Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+ return;
+ }
+
if (!rcon_password.string || !rcon_password.string[0] || rcon_secure.integer > 0)
{
Con_Printf ("You must set rcon_password before issuing an pqrcon command, and rcon_secure must be 0.\n");
lhnetsocket_t *mysocket;
char vabuf[1024];
+ if (Cmd_Argc() == 1)
+ {
+ Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+ return;
+ }
+
if (!rcon_password.string || !rcon_password.string[0])
{
Con_Printf ("You must set rcon_password before issuing an rcon command.\n");
row_inci = 0;
}
- x = 0;
- y = 0;
pix_inc = 1;
if ((targa_header.image_type & ~8) == 2)
pix_inc = (targa_header.pixel_size + 7) / 8;
}
png = (void *)qpng_create_write_struct(
- (qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 : PNG_LIBPNG_VER_STRING_14, // nasty hack to support both libpng12 and libpng14
+ (qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 :
+ (qpng_access_version_number() / 100 == 104) ? PNG_LIBPNG_VER_STRING_14 :
+ PNG_LIBPNG_VER_STRING_15, // nasty hack... whatever
0, PNG_error_fn, PNG_warning_fn
);
if(!png)
if(key_line[1]) // empty?
if(strcmp(key_line, "]quit")) // putting these into the history just sucks
if(strncmp(key_line, "]quit ", 6)) // putting these into the history just sucks
+ if(strcmp(key_line, "]rcon_password")) // putting these into the history just sucks
+ if(strncmp(key_line, "]rcon_password ", 15)) // putting these into the history just sucks
ConBuffer_AddLine(&history, key_line + 1, strlen(key_line) - 1, 0);
Con_Printf("%s\n", key_line); // don't mark empty lines as history
history_line = -1;
lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
SOCKLEN_T namelen;
int bindresult;
+
+#if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
+ // we got reports of massive lags when this protocol was chosen as transport
+ // so better turn it off
+ {
+ int rfc1149only = 0;
+ int rfc1149enabled = 0;
+ if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
+ Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
+ if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
+ Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
+ }
+#endif
+
#ifdef SUPPORTIPV6
if (address->addresstype == LHNETADDRESSTYPE_INET6)
{
OBJ_SND_COMMON=snd_main.o snd_mem.o snd_mix.o snd_ogg.o snd_wav.o snd_modplug.o
# statically loading d0_blind_id
-LIB_CRYPTO=`[ -n "$(DP_CRYPTO_STATIC_LIBDIR)" ] && echo \ $(DP_CRYPTO_STATIC_LIBDIR)/libd0_blind_id.a\ $(DP_CRYPTO_STATIC_LIBDIR)/libgmp.a`
+LIB_CRYPTO=`[ -n "$(DP_CRYPTO_STATIC_LIBDIR)" ] && echo \ $(DP_CRYPTO_STATIC_LIBDIR)/libd0_blind_id.a`
+LIB_GMP=`[ -n "$(DP_CRYPTO_STATIC_LIBDIR)" ] && { [ -n "$(DP_GMP_STATIC_LIBDIR)" ] && echo \ $(DP_GMP_STATIC_LIBDIR)/libgmp.a || echo \ -lgmp; }`
CFLAGS_CRYPTO=`[ -n "$(DP_CRYPTO_STATIC_LIBDIR)" ] && echo \ -I$(DP_CRYPTO_STATIC_LIBDIR)/../include\ -DCRYPTO_STATIC`
LIB_CRYPTO_RIJNDAEL=`[ -n "$(DP_CRYPTO_RIJNDAEL_STATIC_LIBDIR)" ] && echo \ $(DP_CRYPTO_RIJNDAEL_STATIC_LIBDIR)/libd0_rijndael.a`
CFLAGS_CRYPTO_RIJNDAEL=`[ -n "$(DP_CRYPTO_RIJNDAEL_STATIC_LIBDIR)" ] && echo \ -I$(DP_CRYPTO_RIJNDAEL_STATIC_LIBDIR)/../include\ -DCRYPTO_RIJNDAEL_STATIC`
OBJ_GLX= builddate.c sys_linux.o vid_glx.o thread_pthread.o keysym2ucs.o $(OBJ_SOUND) $(OBJ_CD) $(OBJ_COMMON)
-LDFLAGS_UNIXCOMMON=-lm $(LIB_ODE) $(LIB_JPEG) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL)
+LDFLAGS_UNIXCOMMON=-lm $(LIB_ODE) $(LIB_JPEG) $(LIB_CRYPTO) $(LIB_GMP) $(LIB_CRYPTO_RIJNDAEL)
LDFLAGS_UNIXCL=-L$(UNIX_X11LIBPATH) -lX11 -lXpm -lXext -lXxf86vm -pthread $(LIB_SOUND)
LDFLAGS_UNIXCL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl -lmodplug
LDFLAGS_UNIXSV_PRELOAD=-lz -ljpeg -lpng -lcurl
# Link
# see LDFLAGS_WINCOMMON in makefile
-LDFLAGS_WINCL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) -mwindows -lwinmm -luser32 -lgdi32 -ldxguid -ldinput -lcomctl32 -lws2_32 $(LDFLAGS_D3D) $(LIB_JPEG)
-LDFLAGS_WINSV=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) -mconsole -lwinmm -lws2_32 $(LIB_JPEG)
-LDFLAGS_WINSDL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) $(SDLCONFIG_LIBS) $(LIB_SND_MODPLUG) -lwinmm -lws2_32 $(LIB_JPEG)
+LDFLAGS_WINCL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_GMP) $(LIB_CRYPTO_RIJNDAEL) -mwindows -lwinmm -luser32 -lgdi32 -ldxguid -ldinput -lcomctl32 -lws2_32 $(LDFLAGS_D3D) $(LIB_JPEG)
+LDFLAGS_WINSV=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_GMP) $(LIB_CRYPTO_RIJNDAEL) -mconsole -lwinmm -lws2_32 $(LIB_JPEG)
+LDFLAGS_WINSDL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_GMP) $(LIB_CRYPTO_RIJNDAEL) $(SDLCONFIG_LIBS) $(LIB_SND_MODPLUG) -lwinmm -lws2_32 $(LIB_JPEG)
EXE_WINCL=darkplaces.exe
EXE_WINSV=darkplaces-dedicated.exe
EXE_WINSDL=darkplaces-sdl.exe
, in->m[3][0], in->m[3][1], in->m[3][2], in->m[3][3]);
}
-int Math_atov(const char *s, vec3_t out)
+int Math_atov(const char *s, prvm_vec3_t out)
{
int i;
VectorClear(out);
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
-typedef float vec_t;
-typedef vec_t vec2_t[2];
-typedef vec_t vec3_t[3];
-typedef vec_t vec4_t[4];
-typedef vec_t vec5_t[5];
-typedef vec_t vec6_t[6];
-typedef vec_t vec7_t[7];
-typedef vec_t vec8_t[8];
struct mplane_s;
extern vec3_t vec3_origin;
-#define nanmask (255<<23)
-#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
+#define float_nanmask (0x7F800000)
+#define double_nanmask (0x7FF8000000000000)
+#define FLOAT_IS_NAN(x) (((*(int *)&x)&float_nanmask)==float_nanmask)
+#define DOUBLE_IS_NAN(x) (((*(long long *)&x)&double_nanmask)==double_nanmask)
+
+#ifdef VEC_64
+#define VEC_IS_NAN(x) DOUBLE_IS_NAN(x)
+#else
+#define VEC_IS_NAN(x) FLOAT_IS_NAN(x)
+#endif
+
+#ifdef PRVM_64
+#define PRVM_IS_NAN(x) DOUBLE_IS_NAN(x)
+#else
+#define PRVM_IS_NAN(x) FLOAT_IS_NAN(x)
+#endif
#define bound(min,num,max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
#define Vector2Compare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1]))
#define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
#define Vector2Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]))
-#define Vector2Set(a,b,c,d,e) ((a)[0]=(b),(a)[1]=(c))
+#define Vector2Set(a,b,c) ((a)[0]=(b),(a)[1]=(c))
#define Vector2Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale))
#define Vector2Normalize2(v,dest) {float ilength = (float) sqrt(DotProduct2((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;}
#define VectorReflect(a,r,b,c) do{double d;d = DotProduct((a), (b)) * -(1.0 + (r));VectorMA((a), (d), (b), (c));}while(0)
#define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2])
#define BoxInsideBox(a,b,c,d) ((a)[0] >= (c)[0] && (b)[0] <= (d)[0] && (a)[1] >= (c)[1] && (b)[1] <= (d)[1] && (a)[2] >= (c)[2] && (b)[2] <= (d)[2])
-#define TriangleOverlapsBox(a,b,c,d,e) (min((a)[0], min((b)[0], (c)[0])) < (e)[0] && max((a)[0], max((b)[0], (c)[0])) > (d)[0] && min((a)[1], min((b)[1], (c)[1])) < (e)[1] && max((a)[1], max((b)[1], (c)[1])) > (d)[1] && min((a)[2], min((b)[2], (c)[2])) < (e)[2] && max((a)[2], max((b)[2], (c)[2])) > (d)[2])
+#define TriangleBBoxOverlapsBox(a,b,c,d,e) (min((a)[0], min((b)[0], (c)[0])) < (e)[0] && max((a)[0], max((b)[0], (c)[0])) > (d)[0] && min((a)[1], min((b)[1], (c)[1])) < (e)[1] && max((a)[1], max((b)[1], (c)[1])) > (d)[1] && min((a)[2], min((b)[2], (c)[2])) < (e)[2] && max((a)[2], max((b)[2], (c)[2])) > (d)[2])
#define TriangleNormal(a,b,c,n) ( \
(n)[0] = ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]), \
struct matrix4x4_s;
/// print a matrix to the console
void Matrix4x4_Print(const struct matrix4x4_s *in);
-int Math_atov(const char *s, vec3_t out);
+int Math_atov(const char *s, prvm_vec3_t out);
void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f);
typedef struct matrix4x4_s
{
- float m[4][4];
+ vec_t m[4][4];
}
matrix4x4_t;
void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale);
// converts a matrix4x4 to a set of 3D vectors for the 3 axial directions, and the translate
-void Matrix4x4_ToVectors(const matrix4x4_t *in, float vx[3], float vy[3], float vz[3], float t[3]);
+void Matrix4x4_ToVectors(const matrix4x4_t *in, vec_t vx[3], vec_t vy[3], vec_t vz[3], vec_t t[3]);
// creates a matrix4x4 from a set of 3D vectors for axial directions, and translate
-void Matrix4x4_FromVectors(matrix4x4_t *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
+void Matrix4x4_FromVectors(matrix4x4_t *out, const vec_t vx[3], const vec_t vy[3], const vec_t vz[3], const vec_t t[3]);
// converts a matrix4x4 to a double[16] array in the OpenGL orientation
void Matrix4x4_ToArrayDoubleGL(const matrix4x4_t *in, double out[16]);
void Matrix4x4_Blend (matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2, double blend);
// transforms a 3D vector through a matrix4x4
-void Matrix4x4_Transform (const matrix4x4_t *in, const float v[3], float out[3]);
+void Matrix4x4_Transform (const matrix4x4_t *in, const vec_t v[3], vec_t out[3]);
// transforms a 4D vector through a matrix4x4
// (warning: if you don't know why you would need this, you don't need it)
// (warning: the 4th component of the vector should be 1.0)
-void Matrix4x4_Transform4 (const matrix4x4_t *in, const float v[4], float out[4]);
+void Matrix4x4_Transform4 (const matrix4x4_t *in, const vec_t v[4], vec_t out[4]);
// reverse transforms a 3D vector through a matrix4x4, at least for *simple*
// cases (rotation and translation *ONLY*), this attempts to undo the results
// of Transform
-//void Matrix4x4_SimpleUntransform (const matrix4x4_t *in, const float v[3], float out[3]);
+//void Matrix4x4_SimpleUntransform (const matrix4x4_t *in, const vec_t v[3], vec_t out[3]);
// transforms a direction vector through the rotation part of a matrix
-void Matrix4x4_Transform3x3 (const matrix4x4_t *in, const float v[3], float out[3]);
+void Matrix4x4_Transform3x3 (const matrix4x4_t *in, const vec_t v[3], vec_t out[3]);
// transforms a positive distance plane (A*x+B*y+C*z-D=0) through a rotation or translation matrix
-void Matrix4x4_TransformPositivePlane (const matrix4x4_t *in, float x, float y, float z, float d, float *o);
+void Matrix4x4_TransformPositivePlane (const matrix4x4_t *in, vec_t x, vec_t y, vec_t z, vec_t d, vec_t *o);
// transforms a standard plane (A*x+B*y+C*z+D=0) through a rotation or translation matrix
-void Matrix4x4_TransformStandardPlane (const matrix4x4_t *in, float x, float y, float z, float d, float *o);
+void Matrix4x4_TransformStandardPlane (const matrix4x4_t *in, vec_t x, vec_t y, vec_t z, vec_t d, vec_t *o);
// ease of use functions
// immediately applies a Translate to the matrix
void Matrix4x4_ConcatScale3 (matrix4x4_t *out, double x, double y, double z);
// extracts origin vector (translate) from matrix
-void Matrix4x4_OriginFromMatrix (const matrix4x4_t *in, float *out);
+void Matrix4x4_OriginFromMatrix (const matrix4x4_t *in, vec_t *out);
// extracts scaling factor from matrix (only works for uniform scaling)
double Matrix4x4_ScaleFromMatrix (const matrix4x4_t *in);
M_Menu_Options_Graphics_f ();
break;
case 22: // Lighting: Flares
- Cbuf_AddText("r_coronas 1;gl_flashblend 1;r_shadow_gloss 0;r_shadow_realtime_dlight 0;r_shadow_realtime_dlight_shadows 0;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 0;r_hdr 0");
+ Cbuf_AddText("r_coronas 1;gl_flashblend 1;r_shadow_gloss 0;r_shadow_realtime_dlight 0;r_shadow_realtime_dlight_shadows 0;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 0");
break;
case 23: // Lighting: Normal
- Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 0;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 0;r_hdr 0");
+ Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 0;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 0");
break;
case 24: // Lighting: High
- Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 1;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 1;r_hdr 0");
+ Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 1;r_shadow_realtime_world 0;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 1");
break;
case 25: // Lighting: Full
- Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 1;r_shadow_realtime_world 1;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 1;r_hdr 0");
+ Cbuf_AddText("r_coronas 1;gl_flashblend 0;r_shadow_gloss 1;r_shadow_realtime_dlight 1;r_shadow_realtime_dlight_shadows 1;r_shadow_realtime_world 1;r_shadow_realtime_world_lightmaps 0;r_shadow_realtime_world_shadows 1;r_bloom 1");
break;
case 26:
M_Menu_ModList_f ();
case GAME_NORMAL:
case GAME_HIPNOTIC:
case GAME_ROGUE:
+ case GAME_QUOTH:
case GAME_NEHAHRA:
case GAME_DEFEATINDETAIL2:
if (request-- == 0) return M_QuitMessage("Are you gonna quit","this game just like","everything else?",NULL,NULL,NULL,NULL,NULL);
{GAME_NORMAL, &sharewarequakegame, ®isteredquakegame},
{GAME_HIPNOTIC, &hipnoticgame, &hipnoticgame},
{GAME_ROGUE, &roguegame, &roguegame},
+ {GAME_QUOTH, &sharewarequakegame, ®isteredquakegame},
{GAME_NEHAHRA, &nehahragame, &nehahragame},
{GAME_TRANSFUSION, &transfusiongame, &transfusiongame},
{GAME_GOODVSBAD2, &goodvsbad2game, &goodvsbad2game},
prvm_prog_t *prog = MVM_prog;
// pass key
- prog->globals.generic[OFS_PARM0] = (float) key;
- prog->globals.generic[OFS_PARM1] = (float) ascii;
+ prog->globals.fp[OFS_PARM0] = (prvm_vec_t) key;
+ prog->globals.fp[OFS_PARM1] = (prvm_vec_t) ascii;
if (downevent)
prog->ExecuteProgram(prog, PRVM_menufunction(m_keydown),"m_keydown(float key, float ascii) required");
else if (PRVM_menufunction(m_keyup))
{
prvm_prog_t *prog = MVM_prog;
- prog->globals.generic[OFS_PARM0] = (float) mode;
+ prog->globals.fp[OFS_PARM0] = (prvm_vec_t) mode;
prog->ExecuteProgram(prog, PRVM_menufunction(m_toggle),"m_toggle(float mode) required");
}
// allocate the mempools
prog->progs_mempool = Mem_AllocPool(M_PROG_FILENAME, 0, NULL);
- PRVM_Prog_Load(prog, M_PROG_FILENAME, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals);
+ PRVM_Prog_Load(prog, M_PROG_FILENAME, NULL, 0, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals);
// note: OP_STATE is not supported by menu qc, we don't even try to detect
// it here
int surfacenumber;
const rtlight_t *rtlight;
float dist;
- meshqueue_sortcategory_t category;
+ dptransparentsortcategory_t category;
}
meshqueue_t;
mqt_viewmaxdist = 0;
}
-void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
meshqueue_t *mq;
if (mqt_count >= mqt_total || !mqt_array)
switch(mqt->category)
{
default:
- case MESHQUEUE_SORT_HUD:
+ case TRANSPARENTSORT_HUD:
hashindex = 0;
break;
- case MESHQUEUE_SORT_DISTANCE:
+ case TRANSPARENTSORT_DISTANCE:
// this could use a reduced range if we need more categories
hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
break;
- case MESHQUEUE_SORT_SKY:
+ case TRANSPARENTSORT_SKY:
hashindex = maxhashindex;
break;
}
// VorteX: seems this value is hardcoded in other several defines as it's changing makes mess
#define MESHQUEUE_TRANSPARENT_BATCHSIZE 256
-typedef enum meshqueue_sortcategory_e
-{
- MESHQUEUE_SORT_SKY,
- MESHQUEUE_SORT_DISTANCE,
- MESHQUEUE_SORT_HUD,
-}
-meshqueue_sortcategory_t;
-
void R_MeshQueue_BeginScene(void);
-void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
void R_MeshQueue_RenderTransparent(void);
#endif
// read frames
for (i = 0;i < groupframes;i++)
{
- pinframe = (daliasframe_t *)datapointer;
datapointer += sizeof(daliasframe_t);
Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
datapointer += sizeof(trivertx_t) * inverts;
texture->supercontents = SUPERCONTENTS_SOLID;
if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
texture->supercontents |= SUPERCONTENTS_OPAQUE;
+ texture->transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
}
void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
if (!loadmodel->surfmesh.isanimated)
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
+ loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->surfmesh.num_blends = 0;
loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
// store the weight as the primary weight on this vertex
loadmodel->surfmesh.blends[j] = boneindex;
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex;
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0;
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0;
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0;
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = 255;
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0;
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0;
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0;
}
Z_Free(bonepose);
// normals and tangents are calculated after elements are loaded
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
+ loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
data += sizeof(dpmbonevert_t);
}
loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0];
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
+ loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
}
// since dpm models do not have named sections, reuse their shader name as the section name
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// do most allocations as one merged chunk
- size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
+ size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
+ loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
}
}
loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
+ loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0];
+ loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
+ loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
+ loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
+ loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
+ loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
}
if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
meshtriangles = header.num_triangles;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
{
loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
}
+ if (vblendindexes && vblendweights)
+ {
+ loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
+ loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
+ }
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
if(mod_alias_force_animated.string[0])
- loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
biggestorigin = 0;
memcpy(weights.index, vblendindexes + i*4, 4);
memcpy(weights.influence, vblendweights + i*4, 4);
loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
+ loadmodel->surfmesh.data_skeletalindex4ub[i*4 ] = weights.index[0];
+ loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
+ loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
+ loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
+ loadmodel->surfmesh.data_skeletalweight4ub[i*4 ] = weights.influence[0];
+ loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1];
+ loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2];
+ loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3];
}
}
cvar_t mod_q3shader_default_polygonfactor = {0, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
cvar_t mod_q3shader_default_polygonoffset = {0, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
cvar_t mod_q3shader_force_addalpha = {0, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"};
+cvar_t mod_q3shader_force_terrain_alphaflag = {0, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"};
+
cvar_t mod_q1bsp_polygoncollisions = {0, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"};
cvar_t mod_collision_bih = {0, "mod_collision_bih", "1", "enables use of generated Bounding Interval Hierarchy tree instead of compiled bsp tree in collision code"};
cvar_t mod_recalculatenodeboxes = {0, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"};
Cvar_RegisterVariable(&mod_q3shader_default_polygonfactor);
Cvar_RegisterVariable(&mod_q3shader_default_polygonoffset);
Cvar_RegisterVariable(&mod_q3shader_force_addalpha);
+ Cvar_RegisterVariable(&mod_q3shader_force_terrain_alphaflag);
Cvar_RegisterVariable(&mod_q1bsp_polygoncollisions);
Cvar_RegisterVariable(&mod_collision_bih);
Cvar_RegisterVariable(&mod_recalculatenodeboxes);
// check for impact on this node
if (node->numsurfaces)
{
- int i, dsi, dti, lmwidth, lmheight;
+ unsigned int i;
+ int dsi, dti, lmwidth, lmheight;
float ds, dt;
msurface_t *surface;
unsigned char *lightmap;
static const texture_t *Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode(RecursiveHullCheckTraceInfo_t *t, const dp_model_t *model, const mnode_t *node, double mid[3])
{
- int i;
+ unsigned int i;
int j;
int k;
const msurface_t *surface;
tx->offsetbias = 0;
tx->specularscalemod = 1;
tx->specularpowermod = 1;
+ tx->transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
}
if (!sb->cursize)
out->v[0] = (unsigned short)MSG_ReadLittleShort(sb);
out->v[1] = (unsigned short)MSG_ReadLittleShort(sb);
}
- if (out->v[0] >= loadmodel->brushq1.numvertexes || out->v[1] >= loadmodel->brushq1.numvertexes)
+ if ((int)out->v[0] >= loadmodel->brushq1.numvertexes || (int)out->v[1] >= loadmodel->brushq1.numvertexes)
{
Con_Printf("Mod_Q1BSP_LoadEdges: %s has invalid vertex indices in edge %i (vertices %i %i >= numvertices %i)\n", loadmodel->name, i, out->v[0], out->v[1], loadmodel->brushq1.numvertexes);
if(!loadmodel->brushq1.numvertexes)
// TODO: calculate node bounding boxes during recursion and calculate a maximum plane size accordingly to improve precision (as most maps do not need 1 billion unit plane polygons)
PolygonD_QuadForPlane(nodeportal->points, nodeportal->plane.normal[0], nodeportal->plane.normal[1], nodeportal->plane.normal[2], nodeportal->plane.dist, 1024.0*1024.0*1024.0);
nodeportal->numpoints = 4;
- side = 0; // shut up compiler warning
+ // side = 0; // shut up compiler warning -> should be no longer needed, Host_Error is declared noreturn now
for (portal = (portal_t *)node->portals;portal;portal = portal->next[side])
{
clipplane = portal->plane;
side = 1;
}
else
+ {
Host_Error("Mod_Q1BSP_RecursiveNodePortals: mislinked portal");
+ side = 0; // hush warning
+ }
for (i = 0;i < nodeportal->numpoints*3;i++)
frontpoints[i] = nodeportal->points[i];
else if (portal->nodes[1] == node)
side = 1;
else
+ {
Host_Error("Mod_Q1BSP_RecursiveNodePortals: mislinked portal");
+ side = 0; // hush warning
+ }
nextportal = portal->next[side];
if (!portal->numpoints)
continue;
typedef struct medge_s
{
- unsigned short v[2];
+ unsigned int v[2];
}
medge_t;
struct mnode_s *children[2];
// q1bsp specific
- unsigned short firstsurface;
- unsigned short numsurfaces;
+ unsigned int firstsurface;
+ unsigned int numsurfaces;
}
mnode_t;
nummodels = Mem_ExpandableArray_IndexRange(&models);
if (!name[0])
- Host_Error ("Mod_ForName: NULL name");
+ Host_Error ("Mod_ForName: empty name");
// search the currently loaded models
for (i = 0;i < nummodels;i++)
extern cvar_t mod_q3shader_default_polygonoffset;
extern cvar_t mod_q3shader_default_polygonfactor;
extern cvar_t mod_q3shader_force_addalpha;
+extern cvar_t mod_q3shader_force_terrain_alphaflag;
void Mod_LoadQ3Shaders(void)
{
int j;
while (COM_ParseToken_QuakeC(&text, false))
{
memset (&shader, 0, sizeof(shader));
+ shader.name[0] = 0;
+ shader.surfaceparms = 0;
+ shader.surfaceflags = 0;
+ shader.textureflags = 0;
+ shader.numlayers = 0;
+ shader.lighting = false;
+ shader.vertexalpha = false;
+ shader.textureblendalpha = false;
+ shader.primarylayer = 0;
+ shader.backgroundlayer = 0;
+ shader.skyboxname[0] = 0;
+ shader.deforms[0].deform = Q3DEFORM_NONE;
+ shader.dpnortlight = false;
+ shader.dpshadow = false;
+ shader.dpnoshadow = false;
+ shader.dpmeshcollisions = false;
+ shader.dpshaderkill = false;
+ shader.dpreflectcube[0] = 0;
shader.reflectmin = 0;
shader.reflectmax = 1;
shader.refractfactor = 1;
shader.reflectfactor = 1;
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
+ shader.r_water_waterscroll[0] = 0;
+ shader.r_water_waterscroll[1] = 0;
shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
shader.offsetscale = mod_q3shader_default_offsetmapping_scale.value;
shader.offsetbias = mod_q3shader_default_offsetmapping_bias.value;
- shader.specularscalemod = 1;
- shader.specularpowermod = 1;
shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value;
shader.biaspolygonfactor = mod_q3shader_default_polygonfactor.value;
+ shader.transparentsort = TRANSPARENTSORT_DISTANCE;
+ shader.specularscalemod = 1;
+ shader.specularpowermod = 1;
+ shader.rtlightambient = 0;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
strlcpy(shader.name, com_token, sizeof(shader.name));
if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
{
// multilayer terrain shader or similar
shader.textureblendalpha = true;
+ if (mod_q3shader_force_terrain_alphaflag.integer)
+ shader.layers[0].texflags |= TEXF_ALPHA;
}
}
if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE)
layer->blendfunc[0] = GL_SRC_ALPHA;
}
-
+
layer->texflags = 0;
if (layer->alphatest)
layer->texflags |= TEXF_ALPHA;
shader.biaspolygonoffset = 0;
}
}
+ else if (!strcasecmp(parameter[0], "dptransparentsort") && numparameters >= 2)
+ {
+ shader.textureflags |= Q3TEXTUREFLAG_TRANSPARENTSORT;
+ if (!strcasecmp(parameter[1], "sky"))
+ shader.transparentsort = TRANSPARENTSORT_SKY;
+ else if (!strcasecmp(parameter[1], "distance"))
+ shader.transparentsort = TRANSPARENTSORT_DISTANCE;
+ else if (!strcasecmp(parameter[1], "hud"))
+ shader.transparentsort = TRANSPARENTSORT_HUD;
+ else
+ Con_DPrintf("%s parsing warning: unknown dptransparentsort category \"%s\", or not enough arguments\n", search->filenames[fileindex], parameter[1]);
+ }
else if (!strcasecmp(parameter[0], "dprefract") && numparameters >= 5)
{
shader.textureflags |= Q3TEXTUREFLAG_REFRACTION;
texture->specularscalemod = 1;
texture->specularpowermod = 1;
texture->rtlightambient = 0;
- // WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE
- // HERE, AND Q1BSP LOADING
+ texture->transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
// JUST GREP FOR "specularscalemod = 1".
if (shader)
texture->basematerialflags |= MATERIALFLAG_CAMERA;
texture->customblendfunc[0] = GL_ONE;
texture->customblendfunc[1] = GL_ZERO;
+ texture->transparentsort = shader->transparentsort;
if (shader->numlayers > 0)
{
texture->customblendfunc[0] = shader->layers[0].blendfunc[0];
Vector2Copy(loadmodel->surfmesh.data_texcoordtexture2f + 2*vertexindex, vertexmesh->texcoordtexture2f);
if (loadmodel->surfmesh.data_texcoordlightmap2f)
Vector2Scale(loadmodel->surfmesh.data_texcoordlightmap2f + 2*vertexindex, 1.0f, vertexmesh->texcoordlightmap2f);
+ if (loadmodel->surfmesh.data_skeletalindex4ub)
+ Vector4Copy(loadmodel->surfmesh.data_skeletalindex4ub + 4*vertexindex, vertexmesh->skeletalindex4ub);
+ if (loadmodel->surfmesh.data_skeletalweight4ub)
+ Vector4Copy(loadmodel->surfmesh.data_skeletalweight4ub + 4*vertexindex, vertexmesh->skeletalweight4ub);
}
}
loadmodel->surfmesh.vbooffset_texcoordtexture2f = size;if (loadmodel->surfmesh.data_texcoordtexture2f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
loadmodel->surfmesh.vbooffset_texcoordlightmap2f = size;if (loadmodel->surfmesh.data_texcoordlightmap2f) size += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
loadmodel->surfmesh.vbooffset_lightmapcolor4f = size;if (loadmodel->surfmesh.data_lightmapcolor4f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
+ loadmodel->surfmesh.vbooffset_skeletalindex4ub = size;if (loadmodel->surfmesh.data_skeletalindex4ub ) size += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
+ loadmodel->surfmesh.vbooffset_skeletalweight4ub = size;if (loadmodel->surfmesh.data_skeletalweight4ub ) size += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
mem = (unsigned char *)Mem_Alloc(tempmempool, size);
if (loadmodel->surfmesh.data_vertex3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_vertex3f , loadmodel->surfmesh.data_vertex3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
if (loadmodel->surfmesh.data_svector3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_svector3f , loadmodel->surfmesh.data_svector3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
if (loadmodel->surfmesh.data_texcoordtexture2f ) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordtexture2f , loadmodel->surfmesh.data_texcoordtexture2f , loadmodel->surfmesh.num_vertices * sizeof(float[2]));
if (loadmodel->surfmesh.data_texcoordlightmap2f) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordlightmap2f, loadmodel->surfmesh.data_texcoordlightmap2f, loadmodel->surfmesh.num_vertices * sizeof(float[2]));
if (loadmodel->surfmesh.data_lightmapcolor4f ) memcpy(mem + loadmodel->surfmesh.vbooffset_lightmapcolor4f , loadmodel->surfmesh.data_lightmapcolor4f , loadmodel->surfmesh.num_vertices * sizeof(float[4]));
+ if (loadmodel->surfmesh.data_skeletalindex4ub ) memcpy(mem + loadmodel->surfmesh.vbooffset_skeletalindex4ub , loadmodel->surfmesh.data_skeletalindex4ub , loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]));
+ if (loadmodel->surfmesh.data_skeletalweight4ub ) memcpy(mem + loadmodel->surfmesh.vbooffset_skeletalweight4ub , loadmodel->surfmesh.data_skeletalweight4ub , loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]));
loadmodel->surfmesh.vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, loadmodel->name, false, false, false);
Mem_Free(mem);
}
FS_StripExtension(inname, basename, sizeof(basename));
mod = Mod_ForName(inname, false, true, inname[0] == '*' ? cl.model_name[1] : NULL);
+ if (!mod)
+ {
+ Con_Print("No such model\n");
+ return;
+ }
if (mod->brush.submodel)
{
// if we're decompiling a submodel, be sure to give it a proper name based on its parent
dpsnprintf(basename, sizeof(basename), "%s/%s", outname, mod->name);
outname[0] = 0;
}
- if (!mod)
- {
- Con_Print("No such model\n");
- return;
- }
if (!mod->surfmesh.num_triangles)
{
Con_Print("Empty model (or sprite)\n");
for (surfaceindex = 0;surfaceindex < model->num_surfaces;surfaceindex++)
{
surface = model->data_surfaces + surfaceindex;
- e = model->surfmesh.data_element3i + surface->num_firsttriangle*3;
if (!surface->num_triangles)
continue;
lightmapindex = mod_generatelightmaps_lightmaptriangles[surface->num_firsttriangle].lightmapindex;
typedef struct r_vertexmesh_s
{
- // 80 bytes
+ // 88 bytes
float vertex3f[3];
float color4f[4];
float texcoordtexture2f[2];
float svector3f[3];
float tvector3f[3];
float normal3f[3];
+ unsigned char skeletalindex4ub[4];
+ unsigned char skeletalweight4ub[4];
}
r_vertexmesh_t;
float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture
float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture
float *data_lightmapcolor4f;
+ unsigned char *data_skeletalindex4ub;
+ unsigned char *data_skeletalweight4ub;
int *data_lightmapoffsets; // index into surface's lightmap samples for vertex lighting
// vertex buffer object (stores geometry in video memory)
r_meshbuffer_t *vbo_vertexbuffer;
size_t vbooffset_texcoordtexture2f;
size_t vbooffset_texcoordlightmap2f;
size_t vbooffset_lightmapcolor4f;
+ size_t vbooffset_skeletalindex4ub;
+ size_t vbooffset_skeletalweight4ub;
// morph blending, these are zero if model is skeletal or static
int num_morphframes;
struct md3vertex_s *data_morphmd3vertex;
#define Q3TEXTUREFLAG_REFLECTION 512
#define Q3TEXTUREFLAG_WATERSHADER 1024
#define Q3TEXTUREFLAG_CAMERA 2048
+#define Q3TEXTUREFLAG_TRANSPARENTSORT 4096
#define Q3PATHLENGTH 64
#define TEXTURE_MAXFRAMES 64
OFFSETMAPPING_RELIEF // relief
}dpoffsetmapping_technique_t;
+typedef enum dptransparentsort_category_e
+{
+ TRANSPARENTSORT_SKY,
+ TRANSPARENTSORT_DISTANCE,
+ TRANSPARENTSORT_HUD,
+}dptransparentsortcategory_t;
typedef struct q3shaderinfo_s
{
// polygonoffset (only used if Q3TEXTUREFLAG_POLYGONOFFSET)
float biaspolygonoffset, biaspolygonfactor;
+ // transparent sort category
+ dptransparentsortcategory_t transparentsort;
+
// gloss
float specularscalemod;
float specularpowermod;
- // rtlightning ambient addition
+ // rtlighting ambient addition
float rtlightambient;
#define Q3SHADERINFO_COMPARE_END rtlightambient
}
float offsetscale;
float offsetbias;
+ // transparent sort category
+ dptransparentsortcategory_t transparentsort;
+
// gloss
float specularscalemod;
float specularpowermod;
int (*FindBoxClusters)(struct model_s *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist);
void (*LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal);
void (*FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius);
- mleaf_t *(*PointInLeaf)(struct model_s *model, const float *p);
+ mleaf_t *(*PointInLeaf)(struct model_s *model, const vec3_t p);
// these are actually only found on brushq1, but NULL is handled gracefully
void (*AmbientSoundLevelsForPoint)(struct model_s *model, const vec3_t p, unsigned char *out, int outsize);
void (*RoundUpToHullSize)(struct model_s *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs);
texture->supercontents = SUPERCONTENTS_SOLID;
if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
texture->supercontents |= SUPERCONTENTS_OPAQUE;
+ texture->transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
}
extern cvar_t gl_texturecompression_sprites;
"DP_QC_STRFTIME "
"DP_QC_STRINGBUFFERS "
"DP_QC_STRINGBUFFERS_CVARLIST "
+"DP_QC_STRINGBUFFERS_EXT_WIP "
"DP_QC_STRINGCOLORFUNCTIONS "
"DP_QC_STRING_CASE_FUNCTIONS "
"DP_QC_STRREPLACE "
VM_SAFEPARMCOUNT(2,VM_M_copyentity);
in = PRVM_G_EDICT(OFS_PARM0);
out = PRVM_G_EDICT(OFS_PARM1);
- memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
+ memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
}
//#66 vector() getmousepos (EXT_CSQC)
VM_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name )
VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
-NULL, // #496
-NULL, // #497
-NULL, // #498
-NULL, // #499
-NULL, // #500
+VM_numentityfields, // #496 float() numentityfields = #496; (QP_QC_ENTITYDATA)
+VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
+VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
+VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
+VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
NULL, // #501
NULL, // #502
VM_whichpack, // #503 string(string) whichpack = #503;
VM_log, // #532
VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
-NULL, // #535
-NULL, // #536
-NULL, // #537
-NULL, // #538
+VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
NULL, // #539
NULL, // #540
NULL, // #541
return true;
}
}
- if (client->spawned)
+ if (client->begun)
{
// client crashed and is coming back,
// keep their stuff intact
// if client is already spawned, re-send the
// serverinfo message as they'll need it to play
- if (client->spawned)
+ if (client->begun)
SV_SendServerinfo(client);
return true;
}
}
if (host_client)
{
- if ((ret = NetConn_ReceivedMessage(host_client->netconnection, data, length, sv.protocol, host_client->spawned ? net_messagetimeout.value : net_connecttimeout.value)) == 2)
+ if ((ret = NetConn_ReceivedMessage(host_client->netconnection, data, length, sv.protocol, host_client->begun ? net_messagetimeout.value : net_connecttimeout.value)) == 2)
{
SV_ReadClientMessage();
return ret;
VectorCopy(vertex3f + elements[1] * 3, v + 3);
VectorCopy(vertex3f + elements[2] * 3, v + 6);
if (PointInfrontOfTriangle(info->eye, v + 0, v + 3, v + 6)
- && (insidebox || TriangleOverlapsBox(v, v + 3, v + 6, info->boxmins, info->boxmaxs))
+ && (insidebox || TriangleBBoxOverlapsBox(v, v + 3, v + 6, info->boxmins, info->boxmaxs))
&& (!info->exact || Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, v, 3, &portaltemppoints2[0][0], 256) > 0))
{
addedtris = true;
typedef union prvm_eval_s
{
- string_t string;
- float _float;
- float vector[3];
- func_t function;
- int ivector[3];
- int _int;
- int edict;
+ prvm_int_t string;
+ prvm_vec_t _float;
+ prvm_vec_t vector[3];
+ prvm_int_t function;
+ prvm_int_t ivector[3];
+ prvm_int_t _int;
+ prvm_int_t edict;
} prvm_eval_t;
typedef struct prvm_required_field_s
union
{
prvm_edict_private_t *required;
- vec_t *vp;
+ prvm_vec_t *fp;
+ prvm_int_t *ip;
// FIXME: this server pointer really means world, not server
// (it is used by both server qc and client qc, but not menu qc)
edict_engineprivate_t *server;
// QuakeC fields (stored in dynamically resized array)
union
{
- vec_t *vp;
+ prvm_vec_t *fp;
+ prvm_int_t *ip;
// entvars_t *server;
// cl_entvars_t *client;
} fields;
#define PRVM_menufunction(funcname) (prog->funcoffsets.funcname)
#if 1
-#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) (fieldoffset < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))
+#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((fieldoffset) < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((ed)->fields.fp + (fieldoffset)))
#define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->_float)
#define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->vector)
#define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->string)
#define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->edict)
#define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->function)
-#define PRVM_GLOBALFIELDVALUE(fieldoffset) (fieldoffset < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))
+#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((fieldoffset) < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)(prog->globals.fp + (fieldoffset)))
#define PRVM_GLOBALFIELDFLOAT(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->_float)
#define PRVM_GLOBALFIELDVECTOR(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->vector)
#define PRVM_GLOBALFIELDSTRING(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->string)
#define PRVM_GLOBALFIELDEDICT(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->edict)
#define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->function)
#else
-#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))
-#define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->_float)
-#define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->vector)
-#define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->string)
-#define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->edict)
-#define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->function)
-#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))
-#define PRVM_GLOBALFIELDFLOAT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->_float)
-#define PRVM_GLOBALFIELDVECTOR(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->vector)
-#define PRVM_GLOBALFIELDSTRING(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->string)
-#define PRVM_GLOBALFIELDEDICT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->edict)
-#define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->function)
+#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((prvm_eval_t *)(ed->fields.fp + fieldoffset))
+#define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->_float)
+#define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->vector)
+#define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->string)
+#define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->edict)
+#define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->function)
+#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((prvm_eval_t *)(prog->globals.fp + fieldoffset))
+#define PRVM_GLOBALFIELDFLOAT(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->_float)
+#define PRVM_GLOBALFIELDVECTOR(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->vector)
+#define PRVM_GLOBALFIELDSTRING(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->string)
+#define PRVM_GLOBALFIELDEDICT(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->edict)
+#define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->function)
#endif
//============================================================================
// stringbuffer flags
#define STRINGBUFFER_SAVED 1 // saved in savegames
-
typedef struct prvm_stringbuffer_s
{
int max_strings;
double *statement_profile; // only incremented if prvm_statementprofiling is on
union {
- vec_t *generic;
+ prvm_vec_t *fp;
+ prvm_int_t *ip;
// globalvars_t *server;
// cl_globalvars_t *client;
} globals;
int argc;
int trace;
+ int break_statement;
+ int break_stack_index;
+ int watch_global;
+ etype_t watch_global_type;
+ prvm_eval_t watch_global_value;
+ int watch_edict;
+ int watch_field;
+ etype_t watch_field_type;
+ prvm_eval_t watch_edictfield_value;
+
mfunction_t *xfunction;
int xstatement;
prvm_stack_t stack[PRVM_MAX_STACK_DEPTH+1];
int depth;
- int localstack[PRVM_LOCALSTACK_SIZE];
+ prvm_int_t localstack[PRVM_LOCALSTACK_SIZE];
int localstack_used;
unsigned short filecrc;
int reserved_edicts; // [INIT]
prvm_edict_t *edicts;
- vec_t *edictsfields;
- void *edictprivate;
+ prvm_vec_t *edictsfields;
+ void *edictprivate;
// size of the engine private struct
int edictprivate_size; // [INIT]
void PRVM_CallProfile_f (void);
void PRVM_PrintFunction_f (void);
-void PRVM_PrintState(prvm_prog_t *prog);
+void PRVM_PrintState(prvm_prog_t *prog, int stack_index);
void PRVM_Crash(prvm_prog_t *prog);
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize);
const char *PRVM_AllocationOrigin(prvm_prog_t *prog);
//============================================================================
-#define PRVM_G_FLOAT(o) (prog->globals.generic[o])
-#define PRVM_G_INT(o) (*(int *)&prog->globals.generic[o])
-#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(*(int *)&prog->globals.generic[o]))
+#define PRVM_G_FLOAT(o) (prog->globals.fp[o])
+#define PRVM_G_INT(o) (prog->globals.ip[o])
+#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(prog->globals.ip[o]))
#define PRVM_G_EDICTNUM(o) PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(o))
-#define PRVM_G_VECTOR(o) (&prog->globals.generic[o])
-#define PRVM_G_STRING(o) (PRVM_GetString(prog, *(string_t *)&prog->globals.generic[o]))
-//#define PRVM_G_FUNCTION(prog, o) (*(func_t *)&prog->globals.generic[o])
+#define PRVM_G_VECTOR(o) (&prog->globals.fp[o])
+#define PRVM_G_STRING(o) (PRVM_GetString(prog, prog->globals.ip[o]))
+//#define PRVM_G_FUNCTION(prog, o) (prog->globals.ip[o])
// FIXME: make these go away?
-#define PRVM_E_FLOAT(e,o) (((float*)e->fields.vp)[o])
-#define PRVM_E_INT(e,o) (((int*)e->fields.vp)[o])
-//#define PRVM_E_VECTOR(e,o) (&((float*)e->fields.vp)[o])
-#define PRVM_E_STRING(e,o) (PRVM_GetString(prog, *(string_t *)&((float*)e->fields.vp)[o]))
+#define PRVM_E_FLOAT(e,o) (e->fields.fp[o])
+#define PRVM_E_INT(e,o) (e->fields.ip[o])
+//#define PRVM_E_VECTOR(e,o) (&(e->fields.fp[o]))
+#define PRVM_E_STRING(e,o) (PRVM_GetString(prog, e->fields.ip[o]))
extern int prvm_type_size[8]; // for consistency : I think a goal of this sub-project is to
// make the new vm mostly independent from the old one, thus if it's necessary, I copy everything
Set up the fields marked with [INIT] in the prog struct
Load a program with LoadProgs
*/
-// Load expects to be called right after Init
+// Load expects to be called right after Reset
void PRVM_Prog_Init(prvm_prog_t *prog);
-void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global);
+void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data, fs_offset_t size, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global);
void PRVM_Prog_Reset(prvm_prog_t *prog);
void PRVM_StackTrace(prvm_prog_t *prog);
+void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text);
+void PRVM_Watchpoint(prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n);
void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) DP_FUNC_PRINTF(2);
void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed);
-void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model);
+void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model, double curtime);
void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend);
void VM_RemoveEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed);
newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
newsnap = d->snapshot + newsnapindex;
memset(newsnap, 0, sizeof(*newsnap));
- oldsnapindex = -1;
oldsnap = NULL;
if (delta)
{
if(prvm_backtraceforwarnings.integer && recursive != realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set
{
recursive = realtime;
- PRVM_PrintState(prog);
+ PRVM_PrintState(prog, 0);
recursive = -1;
}
}
// LordHavoc: quite tempting to break apart this function to reuse the
// duplicated code, but I suspect it is better for performance
// this way
-void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model)
+void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model, double curtime)
{
int sub2, numframes, f, i, k;
int isfirstframegroup = true;
if (scene->framecount > 1)
{
// this code path is only used on .zym models and torches
- sublerp = scene->framerate * (cl.time - g->start);
+ sublerp = scene->framerate * (curtime - g->start);
f = (int) floor(sublerp);
sublerp -= f;
sub2 = f + 1;
*/
void VM_normalize(prvm_prog_t *prog)
{
- float *value1;
+ prvm_vec_t *value1;
vec3_t newvalue;
double f;
*/
void VM_vectoyaw(prvm_prog_t *prog)
{
- float *value1;
- float yaw;
+ prvm_vec_t *value1;
+ prvm_vec_t yaw;
VM_SAFEPARMCOUNT(1,VM_vectoyaw);
*/
void VM_vectoangles(prvm_prog_t *prog)
{
+ vec3_t result, forward, up;
VM_SAFEPARMCOUNTRANGE(1, 2,VM_vectoangles);
- AnglesFromVectors(PRVM_G_VECTOR(OFS_RETURN), PRVM_G_VECTOR(OFS_PARM0), prog->argc >= 2 ? PRVM_G_VECTOR(OFS_PARM1) : NULL, true);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), forward);
+ if (prog->argc >= 2)
+ {
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), up);
+ AnglesFromVectors(result, forward, up, true);
+ }
+ else
+ AnglesFromVectors(result, forward, NULL, true);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
}
/*
void VM_ftos(prvm_prog_t *prog)
{
- float v;
+ prvm_vec_t v;
char s[128];
VM_SAFEPARMCOUNT(1, VM_ftos);
v = PRVM_G_FLOAT(OFS_PARM0);
- if ((float)((int)v) == v)
- dpsnprintf(s, sizeof(s), "%i", (int)v);
+ if ((prvm_vec_t)((prvm_int_t)v) == v)
+ dpsnprintf(s, sizeof(s), "%.0f", v);
else
dpsnprintf(s, sizeof(s), "%f", v);
PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
void VM_fabs(prvm_prog_t *prog)
{
- float v;
+ prvm_vec_t v;
VM_SAFEPARMCOUNT(1,VM_fabs);
========================
VM_itof
-float itof(intt ent)
+float itof(int ent)
========================
*/
void VM_itof(prvm_prog_t *prog)
*/
void VM_ftoe(prvm_prog_t *prog)
{
- int ent;
+ prvm_int_t ent;
VM_SAFEPARMCOUNT(1, VM_ftoe);
- ent = (int)PRVM_G_FLOAT(OFS_PARM0);
+ ent = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM0);
if (ent < 0 || ent >= prog->max_edicts || PRVM_PROG_TO_EDICT(ent)->priv.required->free)
ent = 0; // return world instead of a free or invalid entity
// LordHavoc: search for flags in float fields
void VM_findflags(prvm_prog_t *prog)
{
- int e;
- int f;
- int s;
+ prvm_int_t e;
+ prvm_int_t f;
+ prvm_int_t s;
prvm_edict_t *ed;
VM_SAFEPARMCOUNT(3, VM_findflags);
e = PRVM_G_EDICTNUM(OFS_PARM0);
f = PRVM_G_INT(OFS_PARM1);
- s = (int)PRVM_G_FLOAT(OFS_PARM2);
+ s = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM2);
for (e++ ; e < prog->num_edicts ; e++)
{
continue;
if (!PRVM_E_FLOAT(ed,f))
continue;
- if ((int)PRVM_E_FLOAT(ed,f) & s)
+ if ((prvm_int_t)PRVM_E_FLOAT(ed,f) & s)
{
VM_RETURN_EDICT(ed);
return;
// LordHavoc: chained search for flags in float fields
void VM_findchainflags(prvm_prog_t *prog)
{
- int i;
- int f;
- int s;
+ prvm_int_t i;
+ prvm_int_t f;
+ prvm_int_t s;
prvm_edict_t *ent, *chain;
int chainfield;
chain = (prvm_edict_t *)prog->edicts;
f = PRVM_G_INT(OFS_PARM0);
- s = (int)PRVM_G_FLOAT(OFS_PARM1);
+ s = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM1);
ent = PRVM_NEXT_EDICT(prog->edicts);
for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
continue;
if (!PRVM_E_FLOAT(ent,f))
continue;
- if (!((int)PRVM_E_FLOAT(ent,f) & s))
+ if (!((prvm_int_t)PRVM_E_FLOAT(ent,f) & s))
continue;
PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
*/
void VM_rint(prvm_prog_t *prog)
{
- float f;
+ prvm_vec_t f;
VM_SAFEPARMCOUNT(1,VM_rint);
f = PRVM_G_FLOAT(OFS_PARM0);
{
ddef_t *d;
int i = (int)PRVM_G_FLOAT(OFS_PARM0);
-
+
if (i < 0 || i >= prog->numfielddefs)
{
- VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+ VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
return;
}
-
+
d = &prog->fielddefs[i];
PRVM_G_INT(OFS_RETURN) = d->s_name; // presuming that s_name points to a string already
}
}
d = &prog->fielddefs[i];
- PRVM_G_FLOAT(OFS_RETURN) = (float)d->type;
+ PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t)d->type;
}
// KrimZon - DP_QC_ENTITYDATA
// put the data into a string
ddef_t *d;
int type, j;
- int *v;
+ prvm_eval_t *val;
prvm_edict_t * ent;
int i = (int)PRVM_G_FLOAT(OFS_PARM0);
char valuebuf[MAX_INPUTLINE];
VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
return;
}
- v = (int *)((char *)ent->fields.vp + d->ofs*4);
+ val = (prvm_eval_t *)(ent->fields.fp + d->ofs);
// if it's 0 or blank, return an empty string
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<prvm_type_size[type] ; j++)
- if (v[j])
+ if (val->ivector[j])
break;
if (j == prvm_type_size[type])
{
return;
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf)));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf)));
}
// KrimZon - DP_QC_ENTITYDATA
if(prog->argc == 0)
{
- PRVM_G_FLOAT(OFS_RETURN) = (float) realtime;
+ PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t) realtime;
}
else
{
entchannel = CHAN_USER2ENGINE(entchannel);
if (!IS_CHAN(entchannel))
VM_Warning(prog, "VM_getsoundtime: %s: bad channel %i\n", prog->name, entchannel);
- PRVM_G_FLOAT(OFS_RETURN) = (float)S_GetEntChannelPosition(entnum, entchannel);
+ PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t)S_GetEntChannelPosition(entnum, entchannel);
}
/*
*/
void VM_modulo(prvm_prog_t *prog)
{
- int val, m;
+ prvm_int_t val, m;
VM_SAFEPARMCOUNT(2,VM_module);
- val = (int) PRVM_G_FLOAT(OFS_PARM0);
- m = (int) PRVM_G_FLOAT(OFS_PARM1);
+ val = (prvm_int_t) PRVM_G_FLOAT(OFS_PARM0);
+ m = (prvm_int_t) PRVM_G_FLOAT(OFS_PARM1);
- PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
+ PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t) (val % m);
}
static void VM_Search_Init(prvm_prog_t *prog)
*/
void VM_drawcharacter(prvm_prog_t *prog)
{
- float *pos,*scale,*rgb;
+ prvm_vec_t *pos,*scale,*rgb;
char character;
int flag;
float sx, sy;
*/
void VM_drawstring(prvm_prog_t *prog)
{
- float *pos,*scale,*rgb;
+ prvm_vec_t *pos,*scale,*rgb;
const char *string;
int flag = 0;
float sx, sy;
*/
void VM_drawcolorcodedstring(prvm_prog_t *prog)
{
- float *pos, *scale;
+ prvm_vec_t *pos, *scale;
const char *string;
int flag;
vec3_t rgb;
void VM_stringwidth(prvm_prog_t *prog)
{
const char *string;
- float *szv;
+ vec2_t szv;
float mult; // sz is intended font size so we can later add freetype support, mult is font size multiplier in pixels per character cell
int colors;
float sx, sy;
getdrawfontscale(prog, &sx, &sy);
if(prog->argc == 3)
{
- szv = PRVM_G_VECTOR(OFS_PARM2);
+ Vector2Copy(PRVM_G_VECTOR(OFS_PARM2), szv);
mult = 1;
}
else
{
// we want the width for 8x8 font size, divided by 8
- static float defsize[] = {8, 8};
- szv = defsize;
+ Vector2Set(szv, 8, 8);
mult = 0.125;
// to make sure snapping is turned off, ALWAYS use a nontrivial scale in this case
if(sx >= 0.9 && sx <= 1.1)
void VM_drawpic(prvm_prog_t *prog)
{
const char *picname;
- float *size, *pos, *rgb;
+ prvm_vec_t *size, *pos, *rgb;
int flag = 0;
VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic);
void VM_drawrotpic(prvm_prog_t *prog)
{
const char *picname;
- float *size, *pos, *org, *rgb;
+ prvm_vec_t *size, *pos, *org, *rgb;
int flag;
VM_SAFEPARMCOUNT(8,VM_drawrotpic);
void VM_drawsubpic(prvm_prog_t *prog)
{
const char *picname;
- float *size, *pos, *rgb, *srcPos, *srcSize, alpha;
+ prvm_vec_t *size, *pos, *rgb, *srcPos, *srcSize, alpha;
int flag;
VM_SAFEPARMCOUNT(8,VM_drawsubpic);
*/
void VM_drawfill(prvm_prog_t *prog)
{
- float *size, *pos, *rgb;
+ prvm_vec_t *size, *pos, *rgb;
int flag;
VM_SAFEPARMCOUNT(5,VM_drawfill);
*/
void VM_makevectors (prvm_prog_t *prog)
{
+ vec3_t angles, forward, right, up;
VM_SAFEPARMCOUNT(1, VM_makevectors);
- AngleVectors(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward), PRVM_gameglobalvector(v_right), PRVM_gameglobalvector(v_up));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), angles);
+ AngleVectors(angles, forward, right, up);
+ VectorCopy(forward, PRVM_gameglobalvector(v_forward));
+ VectorCopy(right, PRVM_gameglobalvector(v_right));
+ VectorCopy(up, PRVM_gameglobalvector(v_up));
}
/*
*/
void VM_vectorvectors (prvm_prog_t *prog)
{
+ vec3_t forward, right, up;
VM_SAFEPARMCOUNT(1, VM_vectorvectors);
- VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward));
- VectorVectors(PRVM_gameglobalvector(v_forward), PRVM_gameglobalvector(v_right), PRVM_gameglobalvector(v_up));
+ VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), forward);
+ VectorVectors(forward, right, up);
+ VectorCopy(forward, PRVM_gameglobalvector(v_forward));
+ VectorCopy(right, PRVM_gameglobalvector(v_right));
+ VectorCopy(up, PRVM_gameglobalvector(v_up));
}
/*
*/
void VM_drawline (prvm_prog_t *prog)
{
- float *c1, *c2, *rgb;
+ prvm_vec_t *c1, *c2, *rgb;
float alpha, width;
unsigned char flags;
// float(float number, float quantity) bitshift (EXT_BITSHIFT)
void VM_bitshift (prvm_prog_t *prog)
{
- int n1, n2;
+ prvm_int_t n1, n2;
VM_SAFEPARMCOUNT(2, VM_bitshift);
- n1 = (int)fabs((float)((int)PRVM_G_FLOAT(OFS_PARM0)));
- n2 = (int)PRVM_G_FLOAT(OFS_PARM1);
+ n1 = (prvm_int_t)fabs((prvm_vec_t)((prvm_int_t)PRVM_G_FLOAT(OFS_PARM0)));
+ n2 = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM1);
if(!n1)
PRVM_G_FLOAT(OFS_RETURN) = n1;
else
}
}
- PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
+ PRVM_G_FLOAT( OFS_RETURN ) = (prvm_vec_t) (count / 2);
}
/*
int i;
VM_SAFEPARMCOUNTRANGE(0, 2, VM_buf_create);
-
+
// VorteX: optional parm1 (buffer format) is unfinished, to keep intact with future databuffers extension must be set to "string"
if(prog->argc >= 1 && strcmp(PRVM_G_STRING(OFS_PARM0), "string"))
{
BufStr_Shrink(prog, stringbuffer);
}
+/*
+========================
+VM_buf_loadfile
+load a file into string buffer, return 0 or 1
+float buf_loadfile(string filename, float bufhandle) = #535;
+========================
+*/
+void VM_buf_loadfile(prvm_prog_t *prog)
+{
+ size_t alloclen;
+ prvm_stringbuffer_t *stringbuffer;
+ char string[VM_STRINGTEMP_LENGTH];
+ int filenum, strindex, c, end;
+ const char *filename;
+ char vabuf[1024];
+ VM_SAFEPARMCOUNT(2, VM_buf_loadfile);
+ // get file
+ filename = PRVM_G_STRING(OFS_PARM0);
+ for (filenum = 0;filenum < PRVM_MAX_OPENFILES;filenum++)
+ if (prog->openfiles[filenum] == NULL)
+ break;
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false);
+ if (prog->openfiles[filenum] == NULL)
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false);
+ if (prog->openfiles[filenum] == NULL)
+ {
+ if (developer_extra.integer)
+ VM_Warning(prog, "VM_buf_loadfile: failed to open file %s in %s\n", filename, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+ // get string buffer
+ stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1));
+ if(!stringbuffer)
+ {
+ VM_Warning(prog, "VM_buf_loadfile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+ // read file (append to the end of buffer)
+ strindex = stringbuffer->num_strings;
+ while(1)
+ {
+ // read line
+ end = 0;
+ for (;;)
+ {
+ c = FS_Getc(prog->openfiles[filenum]);
+ if (c == '\r' || c == '\n' || c < 0)
+ break;
+ if (end < VM_STRINGTEMP_LENGTH - 1)
+ string[end++] = c;
+ }
+ string[end] = 0;
+ // remove \n following \r
+ if (c == '\r')
+ {
+ c = FS_Getc(prog->openfiles[filenum]);
+ if (c != '\n')
+ FS_UnGetc(prog->openfiles[filenum], (unsigned char)c);
+ }
+ // add and continue
+ if (c >= 0 || end)
+ {
+ BufStr_Expand(prog, stringbuffer, strindex);
+ stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
+ alloclen = strlen(string) + 1;
+ stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
+ memcpy(stringbuffer->strings[strindex], string, alloclen);
+ strindex = stringbuffer->num_strings;
+ }
+ else
+ break;
+ }
+
+ // close file
+ FS_Close(prog->openfiles[filenum]);
+ prog->openfiles[filenum] = NULL;
+ if (prog->openfiles_origin[filenum])
+ PRVM_Free((char *)prog->openfiles_origin[filenum]);
+ PRVM_G_FLOAT(OFS_RETURN) = 1;
+}
+
+/*
+========================
+VM_buf_writefile
+writes stringbuffer to a file, returns 0 or 1
+float buf_writefile(float filehandle, float bufhandle, [, float startpos, float numstrings]) = #468;
+========================
+*/
+
+void VM_buf_writefile(prvm_prog_t *prog)
+{
+ int filenum, strindex, strnum, strlength;
+ prvm_stringbuffer_t *stringbuffer;
+ VM_SAFEPARMCOUNTRANGE(2, 4, VM_buf_writefile);
+
+ // get file
+ filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
+ if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
+ {
+ VM_Warning(prog, "VM_buf_writefile: invalid file handle %i used in %s\n", filenum, prog->name);
+ return;
+ }
+ if (prog->openfiles[filenum] == NULL)
+ {
+ VM_Warning(prog, "VM_buf_writefile: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
+ return;
+ }
+
+ // get string buffer
+ stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1));
+ if(!stringbuffer)
+ {
+ VM_Warning(prog, "VM_buf_writefile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // get start and end parms
+ if (prog->argc > 3)
+ {
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM2);
+ strnum = (int)PRVM_G_FLOAT(OFS_PARM3);
+ }
+ else if (prog->argc > 2)
+ {
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM2);
+ strnum = stringbuffer->num_strings - strindex;
+ }
+ else
+ {
+ strindex = 0;
+ strnum = stringbuffer->num_strings;
+ }
+ if (strindex < 0 || strindex >= stringbuffer->num_strings)
+ {
+ VM_Warning(prog, "VM_buf_writefile: wrong start string index %i used in %s\n", strindex, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+ if (strnum < 0)
+ {
+ VM_Warning(prog, "VM_buf_writefile: wrong strings count %i used in %s\n", strnum, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // write
+ while(strindex < stringbuffer->num_strings && strnum)
+ {
+ if (stringbuffer->strings[strindex])
+ {
+ if ((strlength = strlen(stringbuffer->strings[strindex])))
+ FS_Write(prog->openfiles[filenum], stringbuffer->strings[strindex], strlength);
+ FS_Write(prog->openfiles[filenum], "\n", 1);
+ }
+ strindex++;
+ strnum--;
+ }
+
+ PRVM_G_FLOAT(OFS_RETURN) = 1;
+}
+
+#define MATCH_AUTO 0
+#define MATCH_WHOLE 1
+#define MATCH_LEFT 2
+#define MATCH_RIGHT 3
+#define MATCH_MIDDLE 4
+#define MATCH_PATTERN 5
+
+static const char *detect_match_rule(char *pattern, int *matchrule)
+{
+ char *ppos, *qpos;
+ int patternlength;
+
+ patternlength = strlen(pattern);
+ ppos = strchr(pattern, '*');
+ qpos = strchr(pattern, '?');
+ // has ? - pattern
+ if (qpos)
+ {
+ *matchrule = MATCH_PATTERN;
+ return pattern;
+ }
+ // has * - left, mid, right or pattern
+ if (ppos)
+ {
+ // starts with * - may be right/mid or pattern
+ if ((ppos - pattern) == 0)
+ {
+ ppos = strchr(pattern+1, '*');
+ // *something
+ if (!ppos)
+ {
+ *matchrule = MATCH_RIGHT;
+ return pattern+1;
+ }
+ // *something*
+ if ((ppos - pattern) == patternlength)
+ {
+ *matchrule = MATCH_MIDDLE;
+ *ppos = 0;
+ return pattern+1;
+ }
+ // *som*thing
+ *matchrule = MATCH_PATTERN;
+ return pattern;
+ }
+ // end with * - left
+ if ((ppos - pattern) == patternlength)
+ {
+ *matchrule = MATCH_LEFT;
+ *ppos = 0;
+ return pattern;
+ }
+ // som*thing
+ *matchrule = MATCH_PATTERN;
+ return pattern;
+ }
+ // have no wildcards - whole string
+ *matchrule = MATCH_WHOLE;
+ return pattern;
+}
+
+// todo: support UTF8
+static qboolean match_rule(const char *string, int max_string, const char *pattern, int patternlength, int rule)
+{
+ const char *mid;
+
+ if (rule == 1)
+ return !strncmp(string, pattern, max_string) ? true : false;
+ if (rule == 2)
+ return !strncmp(string, pattern, patternlength) ? true : false;
+ if (rule == 3)
+ {
+ mid = strstr(string, pattern);
+ return mid && !*(mid+patternlength);
+ }
+ if (rule == 4)
+ return strstr(string, pattern) ? true : false;
+ // pattern
+ return matchpattern_with_separator(string, pattern, false, "", false) ? true : false;
+}
+
+/*
+========================
+VM_bufstr_find
+find an index of bufstring matching rule
+float bufstr_find(float bufhandle, string match, float matchrule, float startpos, float step) = #468;
+========================
+*/
+
+void VM_bufstr_find(prvm_prog_t *prog)
+{
+ prvm_stringbuffer_t *stringbuffer;
+ char string[VM_STRINGTEMP_LENGTH];
+ int matchrule, matchlen, i, step;
+ const char *match;
+
+ VM_SAFEPARMCOUNTRANGE(3, 5, VM_bufstr_find);
+
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+
+ // get string buffer
+ stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
+ if(!stringbuffer)
+ {
+ VM_Warning(prog, "VM_bufstr_find: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
+ return;
+ }
+
+ // get pattern/rule
+ matchrule = (int)PRVM_G_FLOAT(OFS_PARM2);
+ if (matchrule < 0 && matchrule > 5)
+ {
+ VM_Warning(prog, "VM_bufstr_find: invalid match rule %i in %s\n", matchrule, prog->name);
+ return;
+ }
+ if (matchrule)
+ match = PRVM_G_STRING(OFS_PARM1);
+ else
+ {
+ strlcpy(string, PRVM_G_STRING(OFS_PARM1), sizeof(string));
+ match = detect_match_rule(string, &matchrule);
+ }
+ matchlen = strlen(match);
+
+ // find
+ i = (prog->argc > 3) ? (int)PRVM_G_FLOAT(OFS_PARM3) : 0;
+ step = (prog->argc > 4) ? (int)PRVM_G_FLOAT(OFS_PARM4) : 1;
+ while(i < stringbuffer->num_strings)
+ {
+ if (stringbuffer->strings[i] && match_rule(stringbuffer->strings[i], VM_STRINGTEMP_LENGTH, match, matchlen, matchrule))
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = i;
+ break;
+ }
+ i += step;
+ }
+}
+
+/*
+========================
+VM_matchpattern
+float matchpattern(string s, string pattern, float matchrule, float startpos) = #468;
+========================
+*/
+void VM_matchpattern(prvm_prog_t *prog)
+{
+ const char *s, *match;
+ char string[VM_STRINGTEMP_LENGTH];
+ int matchrule, l;
+
+ VM_SAFEPARMCOUNTRANGE(2, 4, VM_matchpattern);
+
+ s = PRVM_G_STRING(OFS_PARM0);
+
+ // get pattern/rule
+ matchrule = (int)PRVM_G_FLOAT(OFS_PARM2);
+ if (matchrule < 0 && matchrule > 5)
+ {
+ VM_Warning(prog, "VM_bufstr_find: invalid match rule %i in %s\n", matchrule, prog->name);
+ return;
+ }
+ if (matchrule)
+ match = PRVM_G_STRING(OFS_PARM1);
+ else
+ {
+ strlcpy(string, PRVM_G_STRING(OFS_PARM1), sizeof(string));
+ match = detect_match_rule(string, &matchrule);
+ }
+
+ // offset
+ l = strlen(match);
+ if (prog->argc > 3)
+ s += max(0, min((unsigned int)PRVM_G_FLOAT(OFS_PARM3), strlen(s)-1));
+
+ // match
+ PRVM_G_FLOAT(OFS_RETURN) = match_rule(s, VM_STRINGTEMP_LENGTH, match, l, matchrule);
+}
+
+/*
+========================
+VM_buf_cvarlist
+========================
+*/
void VM_buf_cvarlist(prvm_prog_t *prog)
{
double starttime;
float id;
char buffer[MAX_INPUTLINE];
+ char posttype[128];
unsigned char *postdata; // free when uri_to_prog_t is freed
size_t postlen;
char *sigdata; // free when uri_to_prog_t is freed
handle->sigdata[handle->siglen] = 0;
}
out1:
- ret = Curl_Begin_ToMemory_POST(url, handle->sigdata, 0, posttype, handle->postdata, handle->postlen, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle);
+ strlcpy(handle->posttype, posttype, sizeof(handle->posttype));
+ ret = Curl_Begin_ToMemory_POST(url, handle->sigdata, 0, handle->posttype, handle->postdata, handle->postlen, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle);
}
else
{
const char *s, *s0;
char outbuf[MAX_INPUTLINE];
char *o = outbuf, *end = outbuf + sizeof(outbuf), *err;
+ const char *p;
int argpos = 1;
int width, precision, thisarg, flags;
char formatbuf[16];
char *f;
int isfloat;
- static int dummyivec[3] = {0, 0, 0};
- static float dummyvec[3] = {0, 0, 0};
+ static prvm_int_t dummyivec[3] = {0, 0, 0};
+ static prvm_vec_t dummyvec[3] = {0, 0, 0};
char vabuf[1024];
#define PRINTF_ALTERNATE 1
#define GETARG_FLOAT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
#define GETARG_VECTOR(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyvec)
#define GETARG_INT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_INT(OFS_PARM0 + 3 * (a))) : 0)
-#define GETARG_INTVECTOR(a) (((a)>=1 && (a)<prog->argc) ? ((int*) PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec)
+#define GETARG_INTVECTOR(a) (((a)>=1 && (a)<prog->argc) ? ((prvm_int_t*) PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec)
#define GETARG_STRING(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_STRING(OFS_PARM0 + 3 * (a))) : "")
for(;;)
*f++ = '.';
*f++ = '*';
}
+ if(*s == 'd' || *s == 'i' || *s == 'o' || *s == 'u' || *s == 'x' || *s == 'X')
+ {
+ // make it use a good integer type
+ for(p = INT_LOSSLESS_FORMAT_SIZE; *p; )
+ *f++ = *p++;
+ }
*f++ = *s;
*f++ = 0;
{
case 'd': case 'i':
if(precision < 0) // not set
- o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
+ o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_INT(thisarg))));
else
- o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_INT(thisarg))));
break;
case 'o': case 'u': case 'x': case 'X':
if(precision < 0) // not set
- o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
+ o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_INT(thisarg))));
else
- o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_INT(thisarg))));
break;
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
if(precision < 0) // not set
memset(&animatemodel_cache, 0, sizeof(animatemodel_cache));
need |= (animatemodel_cache.model != model);
VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed);
- VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model, PRVM_serverglobalfloat(time));
need |= (memcmp(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0;
skeletonindex = (int)PRVM_gameedictfloat(ed, skeletonindex) - 1;
if (!(skeletonindex >= 0 && skeletonindex < MAX_EDICTS && (skeleton = prog->skeletons[skeletonindex]) && skeleton->model->num_bones == ed->priv.server->skeleton.model->num_bones))
dp_model_t *model;
msurface_t *surface;
int pointnum;
+ vec3_t result;
VM_SAFEPARMCOUNT(3, VM_getsurfacepoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
if (pointnum < 0 || pointnum >= surface->num_vertices)
return;
animatemodel(prog, model, ed);
- applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
}
//PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
// float SPA_POSITION = 0;
msurface_t *surface;
int pointnum;
int attributetype;
+ vec3_t result;
VM_SAFEPARMCOUNT(4, VM_getsurfacepoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
switch( attributetype ) {
// float SPA_POSITION = 0;
case 0:
- applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_S_AXIS = 1;
case 1:
- applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_T_AXIS = 2;
case 2:
- applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_R_AXIS = 3; // same as SPA_NORMAL
case 3:
- applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_TEXCOORDS0 = 4;
case 4: {
- float *ret = PRVM_G_VECTOR(OFS_RETURN);
float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
- ret[0] = texcoord[0];
- ret[1] = texcoord[1];
- ret[2] = 0.0f;
+ result[0] = texcoord[0];
+ result[1] = texcoord[1];
+ result[2] = 0.0f;
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
}
// float SPA_LIGHTMAP0_TEXCOORDS = 5;
case 5: {
- float *ret = PRVM_G_VECTOR(OFS_RETURN);
float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
- ret[0] = texcoord[0];
- ret[1] = texcoord[1];
- ret[2] = 0.0f;
+ result[0] = texcoord[0];
+ result[1] = texcoord[1];
+ result[2] = 0.0f;
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
break;
}
// float SPA_LIGHTMAP0_COLOR = 6;
dp_model_t *model;
msurface_t *surface;
vec3_t normal;
+ vec3_t result;
VM_SAFEPARMCOUNT(2, VM_getsurfacenormal);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
// well for curved surfaces or arbitrary meshes
animatemodel(prog, model, PRVM_G_EDICT(OFS_PARM0));
TriangleNormal((animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex), (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 3, (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
- applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), PRVM_G_VECTOR(OFS_RETURN));
- VectorNormalize(PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), result);
+ VectorNormalize(result);
+ VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
}
//PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
void VM_getsurfacetexture(prvm_prog_t *prog)
prvm_edict_t *ed;
dp_model_t *model;
msurface_t *surface;
- vec_t *point;
+ vec3_t point;
VM_SAFEPARMCOUNT(2, VM_getsurfacenearpoint);
PRVM_G_FLOAT(OFS_RETURN) = -1;
ed = PRVM_G_EDICT(OFS_PARM0);
- point = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), point);
if (!ed || ed->priv.server->free)
return;
prvm_edict_t *ed;
dp_model_t *model;
msurface_t *surface;
- vec3_t p, out;
+ vec3_t p, out, inp;
VM_SAFEPARMCOUNT(3, VM_te_getsurfaceclippedpoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
animatemodel(prog, model, ed);
- applytransform_inverted(prog, PRVM_G_VECTOR(OFS_PARM2), ed, p);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), inp);
+ applytransform_inverted(prog, inp, ed, p);
clippointtosurface(prog, ed, model, surface, p, out);
VectorAdd(out, PRVM_serveredictvector(ed, origin), PRVM_G_VECTOR(OFS_RETURN));
}
#define VM_SAFEPARMCOUNT(p,f)
#endif
-#define VM_RETURN_EDICT(e) (((int *)prog->globals.generic)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
+#define VM_RETURN_EDICT(e) (prog->globals.ip[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
#define VM_STRINGTEMP_LENGTH MAX_INPUTLINE
void VM_bufstr_add (prvm_prog_t *prog);
void VM_bufstr_free (prvm_prog_t *prog);
+void VM_buf_loadfile(prvm_prog_t *prog);
+void VM_buf_writefile(prvm_prog_t *prog);
+void VM_bufstr_find(prvm_prog_t *prog);
+void VM_matchpattern(prvm_prog_t *prog);
+
void VM_changeyaw (prvm_prog_t *prog);
void VM_changepitch (prvm_prog_t *prog);
cvar_t prvm_leaktest = {0, "prvm_leaktest", "0", "try to detect memory leaks in strings or entities"};
cvar_t prvm_leaktest_ignore_classnames = {0, "prvm_leaktest_ignore_classnames", "", "classnames of entities to NOT leak check because they are found by find(world, classname, ...) but are actually spawned by QC code (NOT map entities)"};
cvar_t prvm_errordump = {0, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"};
+cvar_t prvm_breakpointdump = {0, "prvm_breakpointdump", "0", "write a savegame on breakpoint to breakpoint-server.dmp"};
cvar_t prvm_reuseedicts_startuptime = {0, "prvm_reuseedicts_startuptime", "2", "allows immediate re-use of freed entity slots during start of new level (value in seconds)"};
cvar_t prvm_reuseedicts_neverinsameframe = {0, "prvm_reuseedicts_neverinsameframe", "1", "never allows re-use of freed entity slots during same frame"};
// alloc edict fields
prog->entityfieldsarea = prog->entityfields * prog->max_edicts;
- prog->edictsfields = (vec_t *)Mem_Alloc(prog->progs_mempool, prog->entityfieldsarea * sizeof(vec_t));
+ prog->edictsfields = (prvm_vec_t *)Mem_Alloc(prog->progs_mempool, prog->entityfieldsarea * sizeof(prvm_vec_t));
// set edict pointers
for(i = 0; i < prog->max_edicts; i++)
{
prog->edicts[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edictprivate + i * prog->edictprivate_size);
- prog->edicts[i].fields.vp = prog->edictsfields + i * prog->entityfields;
+ prog->edicts[i].fields.fp = prog->edictsfields + i * prog->entityfields;
}
}
prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
prog->entityfieldsarea = prog->entityfields * prog->max_edicts;
- prog->edictsfields = (vec_t*)Mem_Realloc(prog->progs_mempool, (void *)prog->edictsfields, prog->entityfieldsarea * sizeof(vec_t));
+ prog->edictsfields = (prvm_vec_t*)Mem_Realloc(prog->progs_mempool, (void *)prog->edictsfields, prog->entityfieldsarea * sizeof(prvm_vec_t));
prog->edictprivate = (void *)Mem_Realloc(prog->progs_mempool, (void *)prog->edictprivate, prog->max_edicts * prog->edictprivate_size);
//set e and v pointers
for(i = 0; i < prog->max_edicts; i++)
{
prog->edicts[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edictprivate + i * prog->edictprivate_size);
- prog->edicts[i].fields.vp = prog->edictsfields + i * prog->entityfields;
+ prog->edicts[i].fields.fp = prog->edictsfields + i * prog->entityfields;
}
prog->end_increase_edicts(prog);
*/
void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e)
{
- memset(e->fields.vp, 0, prog->entityfields * 4);
+ memset(e->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
e->priv.required->free = false;
// AK: Let the init_edict function determine if something needs to be initialized
break;
case ev_float:
// LordHavoc: changed from %5.1f to %10.4f
- dpsnprintf (line, linelength, "%10.4f", val->_float);
+ dpsnprintf (line, linelength, FLOAT_LOSSLESS_FORMAT, val->_float);
break;
case ev_vector:
// LordHavoc: changed from %5.1f to %10.4f
- dpsnprintf (line, linelength, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
+ dpsnprintf (line, linelength, "'" VECTOR_LOSSLESS_FORMAT "'", val->vector[0], val->vector[1], val->vector[2]);
break;
case ev_pointer:
dpsnprintf (line, linelength, "pointer");
line[i] = '\0';
break;
case ev_entity:
- dpsnprintf (line, linelength, "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
+ dpsnprintf (line, linelength, "%i", val->edict);
break;
case ev_function:
f = prog->functions + val->function;
dpsnprintf (line, linelength, "void");
break;
case ev_float:
- dpsnprintf (line, linelength, "%.9g", val->_float);
+ dpsnprintf (line, linelength, FLOAT_LOSSLESS_FORMAT, val->_float);
break;
case ev_vector:
- dpsnprintf (line, linelength, "%.9g %.9g %.9g", val->vector[0], val->vector[1], val->vector[2]);
+ dpsnprintf (line, linelength, VECTOR_LOSSLESS_FORMAT, val->vector[0], val->vector[1], val->vector[2]);
break;
default:
dpsnprintf (line, linelength, "bad type %i", type);
char *s;
//size_t i;
ddef_t *def;
- void *val;
+ prvm_eval_t *val;
char valuebuf[MAX_INPUTLINE];
- val = (void *)&prog->globals.generic[ofs];
+ val = (prvm_eval_t *)&prog->globals.fp[ofs];
def = PRVM_ED_GlobalAtOfs(prog, ofs);
if (!def)
dpsnprintf (line, linelength, "GLOBAL%i", ofs);
else
{
- s = PRVM_ValueString (prog, (etype_t)def->type, (prvm_eval_t *)val, valuebuf, sizeof(valuebuf));
+ s = PRVM_ValueString (prog, (etype_t)def->type, val, valuebuf, sizeof(valuebuf));
dpsnprintf (line, linelength, "%s (=%s)", PRVM_GetString(prog, def->s_name), s);
}
{
size_t l;
ddef_t *d;
- int *v;
+ prvm_eval_t *val;
int i, j;
const char *name;
int type;
// Didn't match; skip
continue;
- v = (int *)(ed->fields.vp + d->ofs);
+ val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<prvm_type_size[type] ; j++)
- if (v[j])
+ if (val->ivector[j])
break;
if (j == prvm_type_size[type])
continue;
strlcat(tempstring, " ", sizeof(tempstring));
strlcat(tempstring, " ", sizeof(tempstring));
- name = PRVM_ValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf));
+ name = PRVM_ValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf));
if (strlen(name) > sizeof(tempstring2)-4)
{
memcpy (tempstring2, name, sizeof(tempstring2)-4);
void PRVM_ED_Write (prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
{
ddef_t *d;
- int *v;
+ prvm_eval_t *val;
int i, j;
const char *name;
int type;
if(strlen(name) > 1 && name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars, and ALSO other _? vars as some mods expect them to be never saved (TODO: a gameplayfix for using the "more precise" condition above?)
- v = (int *)(ed->fields.vp + d->ofs);
+ val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<prvm_type_size[type] ; j++)
- if (v[j])
+ if (val->ivector[j])
break;
if (j == prvm_type_size[type])
continue;
FS_Printf(f,"\"%s\" ",name);
prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_Write, ent=%d, name=%s", i, name);
- FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf)));
+ FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf)));
prog->statestring = NULL;
}
prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_WriteGlobals, name=%s", name);
FS_Printf(f,"\"%s\" ", name);
- FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)type, (prvm_eval_t *)&prog->globals.generic[def->ofs], valuebuf, sizeof(valuebuf)));
+ FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)type, (prvm_eval_t *)&prog->globals.fp[def->ofs], valuebuf, sizeof(valuebuf)));
prog->statestring = NULL;
}
FS_Print(f,"}\n");
mfunction_t *func;
if (ent)
- val = (prvm_eval_t *)(ent->fields.vp + key->ofs);
+ val = (prvm_eval_t *)(ent->fields.fp + key->ofs);
else
- val = (prvm_eval_t *)(prog->globals.generic + key->ofs);
+ val = (prvm_eval_t *)(prog->globals.fp + key->ofs);
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
PRVM_MEM_IncreaseEdicts(prog);
// if IncreaseEdicts was called the base pointer needs to be updated
if (ent)
- val = (prvm_eval_t *)(ent->fields.vp + key->ofs);
+ val = (prvm_eval_t *)(ent->fields.fp + key->ofs);
val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM((int)i));
break;
goto fail;
}
- v = (prvm_eval_t *)(ed->fields.vp + key->ofs);
+ v = (prvm_eval_t *)(ed->fields.fp + key->ofs);
s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
if(Cmd_Argc() == 5)
{
goto fail;
}
- v = (prvm_eval_t *) &prog->globals.generic[key->ofs];
+ v = (prvm_eval_t *) &prog->globals.fp[key->ofs];
s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
if(Cmd_Argc() == 4)
{
// clear it
if (ent != prog->edicts) // hack
- memset (ent->fields.vp, 0, prog->entityfields * 4);
+ memset (ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
data = PRVM_ED_ParseEdict (prog, data, ent);
parsed++;
void PRVM_LeakTest(prvm_prog_t *prog);
void PRVM_Prog_Reset(prvm_prog_t *prog)
{
- PRVM_LeakTest(prog);
- prog->reset_cmd(prog);
- Mem_FreePool(&prog->progs_mempool);
- if(prog->po)
- PRVM_PO_Destroy((po_t *) prog->po);
+ if (prog->loaded)
+ {
+ PRVM_LeakTest(prog);
+ prog->reset_cmd(prog);
+ Mem_FreePool(&prog->progs_mempool);
+ if(prog->po)
+ PRVM_PO_Destroy((po_t *) prog->po);
+ }
memset(prog,0,sizeof(prvm_prog_t));
+ prog->break_statement = -1;
+ prog->watch_global_type = ev_void;
+ prog->watch_field_type = ev_void;
}
/*
PRVM_LoadProgs
===============
*/
-void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global)
+static void PRVM_UpdateBreakpoints(prvm_prog_t *prog);
+void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * data, fs_offset_t size, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global)
{
int i;
dprograms_t *dprograms;
dstatement_t *instatements;
ddef_t *infielddefs;
ddef_t *inglobaldefs;
- float *inglobals;
+ int *inglobals;
dfunction_t *infunctions;
char *instrings;
fs_offset_t filesize;
int a;
int b;
int c;
+ union
+ {
+ unsigned int i;
+ float f;
+ }
+ u;
+ unsigned int d;
char vabuf[1024];
if (prog->loaded)
Host_LockSession(); // all progs can use the session cvar
Crypto_LoadKeys(); // all progs might use the keys at init time
- dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize);
+ if (data)
+ {
+ dprograms = (dprograms_t *) data;
+ filesize = size;
+ }
+ else
+ dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize);
if (dprograms == NULL || filesize < (fs_offset_t)sizeof(dprograms_t))
prog->error_cmd("PRVM_LoadProgs: couldn't load %s for %s", filename, prog->name);
// TODO bounds check header fields (e.g. numstatements), they must never go behind end of file
prog->progs_numfunctions = LittleLong(dprograms->numfunctions);
instrings = (char *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_strings));
prog->progs_numstrings = LittleLong(dprograms->numstrings);
- inglobals = (float *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globals));
+ inglobals = (int *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globals));
prog->progs_numglobals = LittleLong(dprograms->numglobals);
prog->progs_entityfields = LittleLong(dprograms->entityfields);
prog->numglobals = prog->progs_numglobals;
prog->entityfields = prog->progs_entityfields;
- if (LittleLong(dprograms->ofs_strings) + prog->progs_numstrings >= (int)filesize)
+ if (LittleLong(dprograms->ofs_strings) + prog->progs_numstrings > (int)filesize)
prog->error_cmd("%s: %s strings go past end of file", prog->name, filename);
prog->strings = (char *)Mem_Alloc(prog->progs_mempool, prog->progs_numstrings);
memcpy(prog->strings, instrings, prog->progs_numstrings);
// we need to expand the globaldefs and fielddefs to include engine defs
prog->globaldefs = (ddef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobaldefs + numrequiredglobals) * sizeof(ddef_t));
- prog->globals.generic = (float *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobals + requiredglobalspace) * sizeof(float));
+ prog->globals.fp = (prvm_vec_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobals + requiredglobalspace + 2) * sizeof(prvm_vec_t));
+ // + 2 is because of an otherwise occurring overrun in RETURN instruction
+ // when trying to return the last or second-last global
+ // (RETURN always returns a vector, there is no RETURN_F instruction)
prog->fielddefs = (ddef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numfielddefs + numrequiredfields) * sizeof(ddef_t));
// we need to convert the statements to our memory format
prog->statements = (mstatement_t *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(mstatement_t));
#define remapfield(index) (index)
// copy globals
+ // FIXME: LordHavoc: this uses a crude way to identify integer constants, rather than checking for matching globaldefs and checking their type
for (i = 0;i < prog->progs_numglobals;i++)
- ((int *)prog->globals.generic)[remapglobal(i)] = LittleLong(((int *)inglobals)[i]);
+ {
+ u.i = LittleLong(inglobals[i]);
+ // most globals are 0, we only need to deal with the ones that are not
+ if (u.i)
+ {
+ d = u.i & 0xFF800000;
+ if ((d == 0xFF800000) || (d == 0))
+ {
+ // Looks like an integer (expand to int64)
+ prog->globals.ip[remapglobal(i)] = u.i;
+ }
+ else
+ {
+ // Looks like a float (expand to double)
+ prog->globals.fp[remapglobal(i)] = u.f;
+ }
+ }
+ }
// LordHavoc: TODO: support 32bit progs statement formats
// copy, remap globals in statements, bounds check
}
// we're done with the file now
- Mem_Free(dprograms);
+ if(!data)
+ Mem_Free(dprograms);
dprograms = NULL;
// check required functions
prog->loaded = TRUE;
+ PRVM_UpdateBreakpoints(prog);
+
// set flags & ddef_ts in prog
prog->flag = 0;
const char *name;
prvm_edict_t *ed;
ddef_t *d;
- int *v;
+ prvm_eval_t *val;
// TODO
/*
name = PRVM_GetString(prog, d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
- v = (int *)(ed->fields.vp + d->ofs);
+ val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
// if the value is still all 0, skip the field
for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
{
- if (v[j])
+ if (val->ivector[j])
{
counts[i]++;
break;
PRVM_ED_ParseEpair( prog, NULL, global, Cmd_Argv(3), true );
}
+/*
+======================
+Break- and Watchpoints
+======================
+*/
+typedef struct
+{
+ char break_statement[256];
+ char watch_global[256];
+ int watch_edict;
+ char watch_field[256];
+}
+debug_data_t;
+static debug_data_t debug_data[PRVM_PROG_MAX];
+
+void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text)
+{
+ char vabuf[1024];
+ Con_Printf("PRVM_Breakpoint: %s\n", text);
+ PRVM_PrintState(prog, stack_index);
+ if (prvm_breakpointdump.integer)
+ Host_Savegame_to(prog, va(vabuf, sizeof(vabuf), "breakpoint-%s.dmp", prog->name));
+}
+
+void PRVM_Watchpoint(prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n)
+{
+ size_t sz = sizeof(prvm_vec_t) * ((type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
+ if (memcmp(o, n, sz))
+ {
+ char buf[1024];
+ char valuebuf_o[128];
+ char valuebuf_n[128];
+ PRVM_UglyValueString(prog, type, o, valuebuf_o, sizeof(valuebuf_o));
+ PRVM_UglyValueString(prog, type, n, valuebuf_n, sizeof(valuebuf_n));
+ dpsnprintf(buf, sizeof(buf), "%s: %s -> %s", text, valuebuf_o, valuebuf_n);
+ PRVM_Breakpoint(prog, stack_index, buf);
+ memcpy(o, n, sz);
+ }
+}
+
+static void PRVM_UpdateBreakpoints(prvm_prog_t *prog)
+{
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ if (!prog->loaded)
+ return;
+ if (debug->break_statement[0])
+ {
+ if (debug->break_statement[0] >= '0' && debug->break_statement[0] <= '9')
+ {
+ prog->break_statement = atoi(debug->break_statement);
+ prog->break_stack_index = 0;
+ }
+ else
+ {
+ mfunction_t *func;
+ func = PRVM_ED_FindFunction (prog, debug->break_statement);
+ if (!func)
+ {
+ Con_Printf("%s progs: no function or statement named %s to break on!\n", prog->name, debug->break_statement);
+ prog->break_statement = -1;
+ }
+ else
+ {
+ prog->break_statement = func->first_statement;
+ prog->break_stack_index = 1;
+ }
+ }
+ if (prog->break_statement >= -1)
+ Con_Printf("%s progs: breakpoint is at statement %d\n", prog->name, prog->break_statement);
+ }
+ else
+ prog->break_statement = -1;
+
+ if (debug->watch_global[0])
+ {
+ ddef_t *global = PRVM_ED_FindGlobal( prog, debug->watch_global );
+ if( !global )
+ {
+ Con_Printf( "%s progs: no global named '%s' to watch!\n", prog->name, debug->watch_global );
+ prog->watch_global_type = ev_void;
+ }
+ else
+ {
+ size_t sz = sizeof(prvm_vec_t) * ((global->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
+ prog->watch_global = global->ofs;
+ prog->watch_global_type = (etype_t)global->type;
+ memcpy(&prog->watch_global_value, PRVM_GLOBALFIELDVALUE(prog->watch_global), sz);
+ }
+ if (prog->watch_global_type != ev_void)
+ Con_Printf("%s progs: global watchpoint is at global index %d\n", prog->name, prog->watch_global);
+ }
+ else
+ prog->watch_global_type = ev_void;
+
+ if (debug->watch_field[0])
+ {
+ ddef_t *field = PRVM_ED_FindField( prog, debug->watch_field );
+ if( !field )
+ {
+ Con_Printf( "%s progs: no field named '%s' to watch!\n", prog->name, debug->watch_field );
+ prog->watch_field_type = ev_void;
+ }
+ else
+ {
+ size_t sz = sizeof(prvm_vec_t) * ((field->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
+ prog->watch_edict = debug->watch_edict;
+ prog->watch_field = field->ofs;
+ prog->watch_field_type = (etype_t)field->type;
+ if (prog->watch_edict < prog->num_edicts)
+ memcpy(&prog->watch_edictfield_value, PRVM_EDICTFIELDVALUE(PRVM_EDICT_NUM(prog->watch_edict), prog->watch_field), sz);
+ else
+ memset(&prog->watch_edictfield_value, 0, sz);
+ }
+ if (prog->watch_edict != ev_void)
+ Con_Printf("%s progs: edict field watchpoint is at edict %d field index %d\n", prog->name, prog->watch_edict, prog->watch_field);
+ }
+ else
+ prog->watch_field_type = ev_void;
+}
+
+static void PRVM_Breakpoint_f(void)
+{
+ prvm_prog_t *prog;
+
+ if( Cmd_Argc() == 2 ) {
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
+ return;
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ debug->break_statement[0] = 0;
+ }
+ PRVM_UpdateBreakpoints(prog);
+ return;
+ }
+ if( Cmd_Argc() != 3 ) {
+ Con_Printf( "prvm_breakpoint <program name> <function name | statement>\n" );
+ return;
+ }
+
+ if (!(prog = PRVM_ProgFromString(Cmd_Argv(1))))
+ return;
+
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ strlcpy(debug->break_statement, Cmd_Argv(2), sizeof(debug->break_statement));
+ }
+ PRVM_UpdateBreakpoints(prog);
+}
+
+static void PRVM_GlobalWatchpoint_f(void)
+{
+ prvm_prog_t *prog;
+
+ if( Cmd_Argc() == 2 ) {
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
+ return;
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ debug->watch_global[0] = 0;
+ }
+ PRVM_UpdateBreakpoints(prog);
+ return;
+ }
+ if( Cmd_Argc() != 3 ) {
+ Con_Printf( "prvm_globalwatchpoint <program name> <global name>\n" );
+ return;
+ }
+
+ if (!(prog = PRVM_ProgFromString(Cmd_Argv(1))))
+ return;
+
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ strlcpy(debug->watch_global, Cmd_Argv(2), sizeof(debug->watch_global));
+ }
+ PRVM_UpdateBreakpoints(prog);
+}
+
+static void PRVM_EdictWatchpoint_f(void)
+{
+ prvm_prog_t *prog;
+
+ if( Cmd_Argc() == 2 ) {
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
+ return;
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ debug->watch_field[0] = 0;
+ }
+ PRVM_UpdateBreakpoints(prog);
+ return;
+ }
+ if( Cmd_Argc() != 4 ) {
+ Con_Printf( "prvm_edictwatchpoint <program name> <edict number> <field name>\n" );
+ return;
+ }
+
+ if (!(prog = PRVM_ProgFromString(Cmd_Argv(1))))
+ return;
+
+ {
+ debug_data_t *debug = &debug_data[prog - prvm_prog_list];
+ debug->watch_edict = atoi(Cmd_Argv(2));
+ strlcpy(debug->watch_field, Cmd_Argv(3), sizeof(debug->watch_field));
+ }
+ PRVM_UpdateBreakpoints(prog);
+}
+
/*
===============
PRVM_Init
Cmd_AddCommand ("menu_cmd", PRVM_GameCommand_Menu_f, "calls the menu QC function GameCommand with the supplied string as argument");
Cmd_AddCommand ("sv_cmd", PRVM_GameCommand_Server_f, "calls the server QC function GameCommand with the supplied string as argument");
+ Cmd_AddCommand ("prvm_breakpoint", PRVM_Breakpoint_f, "marks a statement or function as breakpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear breakpoint");
+ Cmd_AddCommand ("prvm_globalwatchpoint", PRVM_GlobalWatchpoint_f, "marks a global as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
+ Cmd_AddCommand ("prvm_edictwatchpoint", PRVM_EdictWatchpoint_f, "marks an entity field as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
+
Cvar_RegisterVariable (&prvm_language);
Cvar_RegisterVariable (&prvm_traceqc);
Cvar_RegisterVariable (&prvm_statementprofiling);
Cvar_RegisterVariable (&prvm_leaktest);
Cvar_RegisterVariable (&prvm_leaktest_ignore_classnames);
Cvar_RegisterVariable (&prvm_errordump);
+ Cvar_RegisterVariable (&prvm_breakpointdump);
Cvar_RegisterVariable (&prvm_reuseedicts_startuptime);
Cvar_RegisterVariable (&prvm_reuseedicts_neverinsameframe);
*/
void PRVM_Prog_Init(prvm_prog_t *prog)
{
- if (prog->loaded)
- PRVM_Prog_Reset(prog);
-
- memset(prog, 0, sizeof(prvm_prog_t));
+ PRVM_Prog_Reset(prog);
prog->leaktest_active = prvm_leaktest.integer != 0;
}
if (!f)
Con_Print("<NULL FUNCTION>\n");
else
- Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
+ {
+ if (prog->statement_linenums)
+ Con_Printf("%12s:%i : %s : statement %i\n", PRVM_GetString(prog, f->s_file), prog->statement_linenums[prog->stack[i].s], PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
+ else
+ Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
+ }
}
}
PRVM_Profile(prog, howmany, 0, 1);
}
-void PRVM_PrintState(prvm_prog_t *prog)
+void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
{
int i;
+ mfunction_t *func = prog->xfunction;
+ int st = prog->xstatement;
+ if (stack_index > 0 && stack_index <= prog->depth)
+ {
+ func = prog->stack[prog->depth - stack_index].f;
+ st = prog->stack[prog->depth - stack_index].s;
+ }
if (prog->statestring)
{
Con_Printf("Caller-provided information: %s\n", prog->statestring);
}
- if (prog->xfunction)
+ if (func)
{
for (i = -7; i <= 0;i++)
- if (prog->xstatement + i >= prog->xfunction->first_statement)
- PRVM_PrintStatement(prog, prog->statements + prog->xstatement + i);
+ if (st + i >= func->first_statement)
+ PRVM_PrintStatement(prog, prog->statements + st + i);
}
- else
- Con_Print("null function executing??\n");
PRVM_StackTrace(prog);
}
if( prog->depth > 0 )
{
Con_Printf("QuakeC crash report for %s:\n", prog->name);
- PRVM_PrintState(prog);
+ PRVM_PrintState(prog, 0);
}
if(prvm_errordump.integer)
prog->error_cmd("PRVM_ExecuteProgram: locals stack overflow in %s", prog->name);
for (i=0 ; i < c ; i++)
- prog->localstack[prog->localstack_used+i] = ((int *)prog->globals.generic)[f->parm_start + i];
+ prog->localstack[prog->localstack_used+i] = prog->globals.ip[f->parm_start + i];
prog->localstack_used += c;
// copy parameters
{
for (j=0 ; j<f->parm_size[i] ; j++)
{
- ((int *)prog->globals.generic)[o] = ((int *)prog->globals.generic)[OFS_PARM0+i*3+j];
+ prog->globals.ip[o] = prog->globals.ip[OFS_PARM0+i*3+j];
o++;
}
}
prog->error_cmd("PRVM_ExecuteProgram: locals stack underflow in %s", prog->name);
for (i=0 ; i < c ; i++)
- ((int *)prog->globals.generic)[prog->xfunction->parm_start + i] = prog->localstack[prog->localstack_used+i];
+ prog->globals.ip[prog->xfunction->parm_start + i] = prog->localstack[prog->localstack_used+i];
// up stack
prog->depth--;
// nothing here yet
}
-#define OPA ((prvm_eval_t *)&prog->globals.generic[st->operand[0]])
-#define OPB ((prvm_eval_t *)&prog->globals.generic[st->operand[1]])
-#define OPC ((prvm_eval_t *)&prog->globals.generic[st->operand[2]])
+#define OPA ((prvm_eval_t *)&prog->globals.fp[st->operand[0]])
+#define OPB ((prvm_eval_t *)&prog->globals.fp[st->operand[1]])
+#define OPC ((prvm_eval_t *)&prog->globals.fp[st->operand[2]])
extern cvar_t prvm_traceqc;
extern cvar_t prvm_statementprofiling;
extern qboolean prvm_runawaycheck;
int restorevm_tempstringsbuf_cursize;
double calltime;
double tm, starttm;
+ prvm_vec_t tempfloat;
calltime = Sys_DirtyTime();
chooseexecprogram:
cachedpr_trace = prog->trace;
- if (prvm_statementprofiling.integer || prog->trace)
+ if (prvm_statementprofiling.integer || prog->trace || prog->watch_global >= 0 || prog->watch_edict >= 0 || prog->break_statement >= 0)
{
#define PRVMSLOWINTERPRETER 1
if (prvm_timeprofiling.integer)
int restorevm_tempstringsbuf_cursize;
double calltime;
double tm, starttm;
+ prvm_vec_t tempfloat;
calltime = Sys_DirtyTime();
chooseexecprogram:
cachedpr_trace = prog->trace;
- if (prvm_statementprofiling.integer || prog->trace)
+ if (prvm_statementprofiling.integer || prog->trace || prog->watch_global >= 0 || prog->watch_edict >= 0 || prog->break_statement >= 0)
{
#define PRVMSLOWINTERPRETER 1
if (prvm_timeprofiling.integer)
int restorevm_tempstringsbuf_cursize;
double calltime;
double tm, starttm;
+ prvm_vec_t tempfloat;
calltime = Sys_DirtyTime();
chooseexecprogram:
cachedpr_trace = prog->trace;
- if (prvm_statementprofiling.integer || prog->trace)
+ if (prvm_statementprofiling.integer || prog->trace || prog->watch_global >= 0 || prog->watch_edict >= 0 || prog->break_statement >= 0)
{
#define PRVMSLOWINTERPRETER 1
if (prvm_timeprofiling.integer)
// This code isn't #ifdef/#define protectable, don't try.
+#if PRVMSLOWINTERPRETER
+ {
+ if (prog->watch_global_type != ev_void)
+ {
+ prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global);
+ prog->xstatement = st + 1 - prog->statements;
+ PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, f);
+ }
+ if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
+ {
+ prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
+ prog->xstatement = st + 1 - prog->statements;
+ PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, f);
+ }
+ }
+#endif
+
while (1)
{
st++;
if (prog->trace)
PRVM_PrintStatement(prog, st);
prog->statement_profile[st - prog->statements]++;
+ if (prog->break_statement >= 0)
+ if ((st - prog->statements) == prog->break_statement)
+ {
+ prog->xstatement = st - prog->statements;
+ PRVM_Breakpoint(prog, prog->break_stack_index, "Breakpoint hit");
+ }
#endif
switch (st->op)
OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
break;
case OP_MUL_FV:
- OPC->vector[0] = OPA->_float * OPB->vector[0];
- OPC->vector[1] = OPA->_float * OPB->vector[1];
- OPC->vector[2] = OPA->_float * OPB->vector[2];
+ tempfloat = OPA->_float;
+ OPC->vector[0] = tempfloat * OPB->vector[0];
+ OPC->vector[1] = tempfloat * OPB->vector[1];
+ OPC->vector[2] = tempfloat * OPB->vector[2];
break;
case OP_MUL_VF:
- OPC->vector[0] = OPB->_float * OPA->vector[0];
- OPC->vector[1] = OPB->_float * OPA->vector[1];
- OPC->vector[2] = OPB->_float * OPA->vector[2];
+ tempfloat = OPB->_float;
+ OPC->vector[0] = tempfloat * OPA->vector[0];
+ OPC->vector[1] = tempfloat * OPA->vector[1];
+ OPC->vector[2] = tempfloat * OPA->vector[2];
break;
case OP_DIV_F:
if( OPB->_float != 0.0f )
}
break;
case OP_BITAND:
- OPC->_float = (int)OPA->_float & (int)OPB->_float;
+ OPC->_float = (prvm_int_t)OPA->_float & (prvm_int_t)OPB->_float;
break;
case OP_BITOR:
- OPC->_float = (int)OPA->_float | (int)OPB->_float;
+ OPC->_float = (prvm_int_t)OPA->_float | (prvm_int_t)OPB->_float;
break;
case OP_GE:
OPC->_float = OPA->_float >= OPB->_float;
if (OPB->_int < 0 || OPB->_int + 1 > prog->entityfieldsarea)
{
PreError();
- prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, OPB->_int);
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
{
prog->xstatement = st - prog->statements;
- VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), OPB->_int, prog->name);
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
}
ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
ptr->_int = OPA->_int;
if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfieldsarea)
{
PreError();
- prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, OPB->_int);
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
{
prog->xstatement = st - prog->statements;
- VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), OPB->_int, prog->name);
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
}
ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
ptr->ivector[0] = OPA->ivector[0];
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
PreError();
- prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, OPB->_int);
+ prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, (int)OPB->_int);
goto cleanup;
}
#if 0
}
#endif
ed = PRVM_PROG_TO_EDICT(OPA->edict);
- OPC->_int = ed->fields.vp - prog->edictsfields + OPB->_int;
+ OPC->_int = ed->fields.fp - prog->edictsfields + OPB->_int;
break;
case OP_LOAD_F:
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
PreError();
- prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, OPB->_int);
+ prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
goto cleanup;
}
ed = PRVM_PROG_TO_EDICT(OPA->edict);
- OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
+ OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
break;
case OP_LOAD_V:
if (OPB->_int < 0 || OPB->_int + 2 >= prog->entityfields)
{
PreError();
- prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, OPB->_int);
+ prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
goto cleanup;
}
ed = PRVM_PROG_TO_EDICT(OPA->edict);
- OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
- OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
- OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
+ ptr = (prvm_eval_t *)(ed->fields.ip + OPB->_int);
+ OPC->ivector[0] = ptr->ivector[0];
+ OPC->ivector[1] = ptr->ivector[1];
+ OPC->ivector[2] = ptr->ivector[2];
break;
//==================
if (!OPA->function)
prog->error_cmd("NULL function in %s", prog->name);
- if(!OPA->function || OPA->function >= (unsigned int)prog->numfunctions)
+ if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions)
{
PreError();
prog->error_cmd("%s CALL outside the program", prog->name);
}
else
prog->error_cmd("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, prog->name);
+
+ if (prog->trace != cachedpr_trace)
+ goto chooseexecprogram;
}
else
st = prog->statements + PRVM_EnterFunction(prog, newf);
prog->xfunction->profile += (st - startst);
prog->xstatement = st - prog->statements;
- prog->globals.generic[OFS_RETURN] = prog->globals.generic[st->operand[0]];
- prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[st->operand[0]+1];
- prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[st->operand[0]+2];
+ prog->globals.ip[OFS_RETURN ] = prog->globals.ip[st->operand[0] ];
+ prog->globals.ip[OFS_RETURN+1] = prog->globals.ip[st->operand[0]+1];
+ prog->globals.ip[OFS_RETURN+2] = prog->globals.ip[st->operand[0]+2];
st = prog->statements + PRVM_LeaveFunction(prog);
startst = st;
if (prog->depth <= exitdepth)
goto cleanup; // all done
- if (prog->trace != cachedpr_trace)
- goto chooseexecprogram;
break;
case OP_STATE:
OPC->_int = OPA->_int + OPB->_int;
break;
case OP_ADD_IF:
- OPC->_int = OPA->_int + (int) OPB->_float;
+ OPC->_int = OPA->_int + (prvm_int_t) OPB->_float;
break;
case OP_ADD_FI:
- OPC->_float = OPA->_float + (float) OPB->_int;
+ OPC->_float = OPA->_float + (prvm_vec_t) OPB->_int;
break;
case OP_SUB_I:
OPC->_int = OPA->_int - OPB->_int;
break;
case OP_SUB_IF:
- OPC->_int = OPA->_int - (int) OPB->_float;
+ OPC->_int = OPA->_int - (prvm_int_t) OPB->_float;
break;
case OP_SUB_FI:
- OPC->_float = OPA->_float - (float) OPB->_int;
+ OPC->_float = OPA->_float - (prvm_vec_t) OPB->_int;
break;
case OP_MUL_I:
OPC->_int = OPA->_int * OPB->_int;
break;
case OP_MUL_IF:
- OPC->_int = OPA->_int * (int) OPB->_float;
+ OPC->_int = OPA->_int * (prvm_int_t) OPB->_float;
break;
case OP_MUL_FI:
- OPC->_float = OPA->_float * (float) OPB->_int;
+ OPC->_float = OPA->_float * (prvm_vec_t) OPB->_int;
break;
case OP_MUL_VI:
- OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
- OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
- OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
+ OPC->vector[0] = (prvm_vec_t) OPB->_int * OPA->vector[0];
+ OPC->vector[1] = (prvm_vec_t) OPB->_int * OPA->vector[1];
+ OPC->vector[2] = (prvm_vec_t) OPB->_int * OPA->vector[2];
break;
case OP_DIV_VF:
{
OPC->_int = OPA->_int / OPB->_int;
break;
case OP_DIV_IF:
- OPC->_int = OPA->_int / (int) OPB->_float;
+ OPC->_int = OPA->_int / (prvm_int_t) OPB->_float;
break;
case OP_DIV_FI:
- OPC->_float = OPA->_float / (float) OPB->_int;
+ OPC->_float = OPA->_float / (prvm_vec_t) OPB->_int;
break;
case OP_CONV_IF:
OPC->_float = OPA->_int;
OPC->_int = OPA->_int | OPB->_int;
break;
case OP_BITAND_IF:
- OPC->_int = OPA->_int & (int)OPB->_float;
+ OPC->_int = OPA->_int & (prvm_int_t)OPB->_float;
break;
case OP_BITOR_IF:
- OPC->_int = OPA->_int | (int)OPB->_float;
+ OPC->_int = OPA->_int | (prvm_int_t)OPB->_float;
break;
case OP_BITAND_FI:
- OPC->_float = (int)OPA->_float & OPB->_int;
+ OPC->_float = (prvm_int_t)OPA->_float & OPB->_int;
break;
case OP_BITOR_FI:
- OPC->_float = (int)OPA->_float | OPB->_int;
+ OPC->_float = (prvm_int_t)OPA->_float | OPB->_int;
break;
case OP_GE_I:
OPC->_float = OPA->_int >= OPB->_int;
OPC->_float = OPA->_int || OPB->_int;
break;
case OP_GE_IF:
- OPC->_float = (float)OPA->_int >= OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int >= OPB->_float;
break;
case OP_LE_IF:
- OPC->_float = (float)OPA->_int <= OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int <= OPB->_float;
break;
case OP_GT_IF:
- OPC->_float = (float)OPA->_int > OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int > OPB->_float;
break;
case OP_LT_IF:
- OPC->_float = (float)OPA->_int < OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int < OPB->_float;
break;
case OP_AND_IF:
- OPC->_float = (float)OPA->_int && OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int && OPB->_float;
break;
case OP_OR_IF:
- OPC->_float = (float)OPA->_int || OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int || OPB->_float;
break;
case OP_GE_FI:
- OPC->_float = OPA->_float >= (float)OPB->_int;
+ OPC->_float = OPA->_float >= (prvm_vec_t)OPB->_int;
break;
case OP_LE_FI:
- OPC->_float = OPA->_float <= (float)OPB->_int;
+ OPC->_float = OPA->_float <= (prvm_vec_t)OPB->_int;
break;
case OP_GT_FI:
- OPC->_float = OPA->_float > (float)OPB->_int;
+ OPC->_float = OPA->_float > (prvm_vec_t)OPB->_int;
break;
case OP_LT_FI:
- OPC->_float = OPA->_float < (float)OPB->_int;
+ OPC->_float = OPA->_float < (prvm_vec_t)OPB->_int;
break;
case OP_AND_FI:
- OPC->_float = OPA->_float && (float)OPB->_int;
+ OPC->_float = OPA->_float && (prvm_vec_t)OPB->_int;
break;
case OP_OR_FI:
- OPC->_float = OPA->_float || (float)OPB->_int;
+ OPC->_float = OPA->_float || (prvm_vec_t)OPB->_int;
break;
case OP_NOT_I:
OPC->_float = !OPA->_int;
OPC->_float = OPA->_int == OPB->_int;
break;
case OP_EQ_IF:
- OPC->_float = (float)OPA->_int == OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int == OPB->_float;
break;
case OP_EQ_FI:
- OPC->_float = OPA->_float == (float)OPB->_int;
+ OPC->_float = OPA->_float == (prvm_vec_t)OPB->_int;
break;
case OP_NE_I:
OPC->_float = OPA->_int != OPB->_int;
break;
case OP_NE_IF:
- OPC->_float = (float)OPA->_int != OPB->_float;
+ OPC->_float = (prvm_vec_t)OPA->_int != OPB->_float;
break;
case OP_NE_FI:
- OPC->_float = OPA->_float != (float)OPB->_int;
+ OPC->_float = OPA->_float != (prvm_vec_t)OPB->_int;
break;
case OP_STORE_I:
OPB->_int = OPA->_int;
break;
case OP_GADDRESS:
- i = OPA->_int + (int) OPB->_float;
+ i = OPA->_int + (prvm_int_t) OPB->_float;
#if PRBOUNDSCHECK
if (i < 0 || i >= pr_globaldefs)
{
prog->error_cmd("Bad opcode %i in %s", st->op, prog->name);
goto cleanup;
}
+#if PRVMSLOWINTERPRETER
+ {
+ if (prog->watch_global_type != ev_void)
+ {
+ prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global);
+ prog->xstatement = st - prog->statements;
+ PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, f);
+ }
+ if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
+ {
+ prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
+ prog->xstatement = st - prog->statements;
+ PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, f);
+ }
+ }
+#endif
}
#undef PreError
#define RESTRICT
#endif
+// LordHavoc: upgrade the prvm to double precision for better time values
+// LordHavoc: to be enabled when bugs are worked out...
+//#define PRVM_64
+#ifdef PRVM_64
+typedef double prvm_vec_t;
+typedef long long prvm_int_t;
+#else
+typedef float prvm_vec_t;
+typedef int prvm_int_t;
+#endif
+typedef prvm_vec_t prvm_vec3_t[3];
+
+#ifdef VEC_64
+typedef double vec_t;
+#else
+typedef float vec_t;
+#endif
+typedef vec_t vec2_t[2];
+typedef vec_t vec3_t[3];
+typedef vec_t vec4_t[4];
+typedef vec_t vec5_t[5];
+typedef vec_t vec6_t[6];
+typedef vec_t vec7_t[7];
+typedef vec_t vec8_t[8];
+
#endif
#if defined(__GNUC__) && (__GNUC__ > 2)
#define DP_FUNC_PRINTF(n) __attribute__ ((format (printf, n, n+1)))
#define DP_FUNC_PURE __attribute__ ((pure))
+#define DP_FUNC_NORETURN __attribute__ ((noreturn))
#else
#define DP_FUNC_PRINTF(n)
#define DP_FUNC_PURE
+#define DP_FUNC_NORETURN
#endif
#include <sys/types.h>
void Host_Main(void);
void Host_Shutdown(void);
void Host_StartVideo(void);
-void Host_Error(const char *error, ...) DP_FUNC_PRINTF(1);
+void Host_Error(const char *error, ...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN;
void Host_Quit_f(void);
void Host_ClientCommands(const char *fmt, ...) DP_FUNC_PRINTF(1);
void Host_ShutdownServer(void);
#define ISWHITESPACEORCONTROL(ch) ((signed char) (ch) <= (signed char) ' ')
+#ifdef PRVM_64
+#define FLOAT_IS_TRUE_FOR_INT(x) ((x) & 0x7FFFFFFFFFFFFFFF) // also match "negative zero" doubles of value 0x8000000000000000
+#define FLOAT_LOSSLESS_FORMAT "%.17g"
+#define VECTOR_LOSSLESS_FORMAT "%.17g %.17g %.17g"
+#else
#define FLOAT_IS_TRUE_FOR_INT(x) ((x) & 0x7FFFFFFF) // also match "negative zero" floats of value 0x80000000
+#define FLOAT_LOSSLESS_FORMAT "%.9g"
+#define VECTOR_LOSSLESS_FORMAT "%.9g %.9g %.9g"
+#endif
+
+// originally this was _MSC_VER
+// but here we want to test the system libc, which on win32 is borked, and NOT the compiler
+#ifdef WIN32
+#define INT_LOSSLESS_FORMAT_SIZE "I64"
+#define INT_LOSSLESS_FORMAT_CONVERT_S(x) ((__int64)(x))
+#define INT_LOSSLESS_FORMAT_CONVERT_U(x) ((unsigned __int64)(x))
+#else
+#define INT_LOSSLESS_FORMAT_SIZE "j"
+#define INT_LOSSLESS_FORMAT_CONVERT_S(x) ((intmax_t)(x))
+#define INT_LOSSLESS_FORMAT_CONVERT_U(x) ((uintmax_t)(x))
+#endif
#endif
{
R_MoveExplosion(&explosion[i]);
if (explosion[i].alpha)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
}
}
while (numexplosions > 0 && explosion[i-1].alpha <= 0)
dist = bound(0, dist, 1);
VectorLerp(start, dist, end, org);
// now we have the nearest point on the line, so sort with it
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
}
}
}
typedef enum r_shadow_shadowmode_e
{
- R_SHADOW_SHADOWMODE_STENCIL,
- R_SHADOW_SHADOWMODE_SHADOWMAP2D
+ R_SHADOW_SHADOWMODE_STENCIL,
+ R_SHADOW_SHADOWMODE_SHADOWMAP2D
}
r_shadow_shadowmode_t;
matrix4x4_t r_shadow_shadowmapmatrix;
int r_shadow_lightscissor[4];
qboolean r_shadow_usingdeferredprepass;
-
+qboolean r_shadow_shadowmapdepthtexture;
int maxshadowtriangles;
int *shadowelements;
cvar_t r_shadow_bouncegrid_x = {CVAR_SAVE, "r_shadow_bouncegrid_x", "64", "maximum texture size of bouncegrid on X axis"};
cvar_t r_shadow_bouncegrid_y = {CVAR_SAVE, "r_shadow_bouncegrid_y", "64", "maximum texture size of bouncegrid on Y axis"};
cvar_t r_shadow_bouncegrid_z = {CVAR_SAVE, "r_shadow_bouncegrid_z", "32", "maximum texture size of bouncegrid on Z axis"};
-cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
+cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
-cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
+cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "0", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility) - bad performance (synchronous rendering) - worse on multi-gpu!"};
cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
+cvar_t r_editlights_drawproperties = {0, "r_editlights_drawproperties", "1", "draw properties of currently selected light"};
+cvar_t r_editlights_current_origin = {0, "r_editlights_current_origin", "0 0 0", "origin of selected light"};
+cvar_t r_editlights_current_angles = {0, "r_editlights_current_angles", "0 0 0", "angles of selected light"};
+cvar_t r_editlights_current_color = {0, "r_editlights_current_color", "1 1 1", "color of selected light"};
+cvar_t r_editlights_current_radius = {0, "r_editlights_current_radius", "0", "radius of selected light"};
+cvar_t r_editlights_current_corona = {0, "r_editlights_current_corona", "0", "corona intensity of selected light"};
+cvar_t r_editlights_current_coronasize = {0, "r_editlights_current_coronasize", "0", "corona size of selected light"};
+cvar_t r_editlights_current_style = {0, "r_editlights_current_style", "0", "style of selected light"};
+cvar_t r_editlights_current_shadows = {0, "r_editlights_current_shadows", "0", "shadows flag of selected light"};
+cvar_t r_editlights_current_cubemap = {0, "r_editlights_current_cubemap", "0", "cubemap of selected light"};
+cvar_t r_editlights_current_ambient = {0, "r_editlights_current_ambient", "0", "ambient intensity of selected light"};
+cvar_t r_editlights_current_diffuse = {0, "r_editlights_current_diffuse", "1", "diffuse intensity of selected light"};
+cvar_t r_editlights_current_specular = {0, "r_editlights_current_specular", "1", "specular intensity of selected light"};
+cvar_t r_editlights_current_normalmode = {0, "r_editlights_current_normalmode", "0", "normalmode flag of selected light"};
+cvar_t r_editlights_current_realtimemode = {0, "r_editlights_current_realtimemode", "0", "realtimemode flag of selected light"};
+
typedef struct r_shadow_bouncegrid_settings_s
{
r_shadow_shadowmapsize = 0;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
+ r_shadow_shadowmapdepthtexture = r_fb.usedepthtextures;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
{
{
if (!r_fb.usedepthtextures)
r_shadow_shadowmappcf = 1;
- else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
- r_shadow_shadowmappcf = 1;
- else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD"))
+ else if((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && vid.support.arb_shadow && r_shadow_shadowmapshadowsampler)
{
- r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
+ r_shadow_shadowmapsampler = true;
r_shadow_shadowmappcf = 1;
}
+ else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+ r_shadow_shadowmappcf = 1;
else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
r_shadow_shadowmappcf = 1;
else
}
else
{
+ r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
switch (r_shadow_shadowmapfilterquality)
{
case 1:
- r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
break;
case 2:
- r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
r_shadow_shadowmappcf = 1;
break;
case 3:
void R_Shadow_PrepareShadowSides(int numtris)
{
- if (maxshadowsides < numtris)
- {
- maxshadowsides = numtris;
- if (shadowsides)
+ if (maxshadowsides < numtris)
+ {
+ maxshadowsides = numtris;
+ if (shadowsides)
Mem_Free(shadowsides);
if (shadowsideslist)
Mem_Free(shadowsideslist);
v[2] = invertex3f + e[2] * 3;
TriangleNormal(v[0], v[1], v[2], normal);
if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
v[1] = invertex3f + e[1] * 3;
v[2] = invertex3f + e[2] * 3;
if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
{
- // p1, p2, p3 are in the cubemap's local coordinate system
- // bias = border/(size - border)
+ // p1, p2, p3 are in the cubemap's local coordinate system
+ // bias = border/(size - border)
int mask = 0x3F;
- float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
+ float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<4)
+ mask &= (3<<4)
| (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
return mask;
}
int mask = 0x3F;
VectorSubtract(maxs, mins, radius);
- VectorScale(radius, 0.5f, radius);
- VectorAdd(mins, radius, center);
- Matrix4x4_Transform(worldtolight, center, lightcenter);
+ VectorScale(radius, 0.5f, radius);
+ VectorAdd(mins, radius, center);
+ Matrix4x4_Transform(worldtolight, center, lightcenter);
Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
VectorSubtract(lightcenter, lightradius, pmin);
VectorAdd(lightcenter, lightradius, pmax);
- dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<4)
- | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
- | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
-
- return mask;
+ dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<4)
+ | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
+ | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+
+ return mask;
}
#define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
{
- // p is in the cubemap's local coordinate system
- // bias = border/(size - border)
- float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
- float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
- float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
- int mask = 0x3F;
- if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
- if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
- if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
- if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
- if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
- if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
- return mask;
+ // p is in the cubemap's local coordinate system
+ // bias = border/(size - border)
+ float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
+ float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
+ float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
+ int mask = 0x3F;
+ if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
+ if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
+ if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
+ if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
+ if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
+ if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
+ return mask;
}
static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
{
int i;
- vec3_t p, n;
+ vec3_t o, p, n;
int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
float scale = (size - 2*border)/size, len;
float bias = border / (float)(size - border), dp, dn, ap, an;
// check if cone enclosing side would cross frustum plane
scale = 2 / (scale*scale + 2);
+ Matrix4x4_OriginFromMatrix(&rtlight->matrix_lighttoworld, o);
for (i = 0;i < 5;i++)
{
- if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
+ if (PlaneDiff(o, &r_refdef.view.frustum[i]) > -0.03125)
continue;
Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
len = scale*VectorLength2(n);
if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
}
- if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
+ if (PlaneDiff(o, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
{
- Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
- len = scale*VectorLength(n);
+ Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
+ len = scale*VectorLength2(n);
if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
// this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
// check if frustum corners/origin cross plane sides
#if 1
- // infinite version, assumes frustum corners merely give direction and extend to infinite distance
- Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
- dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
- masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
- dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
- masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
- dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
- masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
- for (i = 0;i < 4;i++)
- {
- Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
- VectorSubtract(n, p, n);
- dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
- if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
- dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
- if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
- dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
- if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
- }
+ // infinite version, assumes frustum corners merely give direction and extend to infinite distance
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
+ dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
+ masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+ dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
+ masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+ dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
+ masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ for (i = 0;i < 4;i++)
+ {
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
+ VectorSubtract(n, p, n);
+ dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
+ if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
+ dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
+ if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
+ dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
+ if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
+ }
#else
- // finite version, assumes corners are a finite distance from origin dependent on far plane
+ // finite version, assumes corners are a finite distance from origin dependent on far plane
for (i = 0;i < 5;i++)
{
Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
TriangleNormal(v[0], v[1], v[2], normal);
if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
{
Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
{
v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
{
Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
GL_ColorMask(0, 0, 0, 0);
GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
GL_CullFace(GL_NONE);
- R_SetupShader_DepthOrShadow(false, false);
+ R_SetupShader_DepthOrShadow(false, false, false); // FIXME test if we have a skeletal model?
r_shadow_rendermode = mode;
switch(mode)
{
if (r_shadow_shadowmap2ddepthtexture) return;
if (r_fb.usedepthtextures)
{
- r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), false);
+ r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), r_shadow_shadowmapsampler);
r_shadow_shadowmap2ddepthbuffer = NULL;
r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
}
R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
else
R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
- r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
+ r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16) ||
+ r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
R_Shadow_FreeShadowMaps();
r_shadow_fb_fbo = fbo;
r_shadow_prepass_width = vid.width;
r_shadow_prepass_height = vid.height;
r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
- r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER32F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
{
int i;
float scale, size, radius, dot1, dot2;
+ prvm_vec3_t prvmshadowdir, prvmshadowfocus;
vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
entity_render_t *ent;
scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
radius = 0.5f * size / scale;
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
dot1 = DotProduct(r_refdef.view.forward, shadowdir);
dot2 = DotProduct(r_refdef.view.up, shadowdir);
VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
VectorNormalize(shadowforward);
CrossProduct(shadowdir, shadowforward, shadowright);
- Math_atov(r_shadows_focus.string, shadowfocus);
+ Math_atov(r_shadows_focus.string, prvmshadowfocus);
+ VectorCopy(prvmshadowfocus, shadowfocus);
VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
vec3_t relativelightdirection, relativeforward, relativeright;
vec3_t relativeshadowmins, relativeshadowmaxs;
vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
+ prvm_vec3_t prvmshadowdir, prvmshadowfocus;
float m[12];
matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
r_viewport_t viewport;
radius = 0.5f / scale;
nearclip = -r_shadows_throwdistance.value;
farclip = r_shadows_throwdistance.value;
- bias = r_shadow_shadowmapping_bias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
+ bias = (r_shadows_shadowmapbias.value < 0) ? r_shadow_shadowmapping_bias.value : r_shadows_shadowmapbias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
r_shadow_shadowmap_parameters[0] = size;
r_shadow_shadowmap_parameters[1] = size;
r_shadow_shadowmap_parameters[2] = 1.0;
r_shadow_shadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
- Math_atov(r_shadows_focus.string, shadowfocus);
+ Math_atov(r_shadows_focus.string, prvmshadowfocus);
+ VectorCopy(prvmshadowfocus, shadowfocus);
VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
else
R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
vec3_t relativelightdirection;
vec3_t relativeshadowmins, relativeshadowmaxs;
vec3_t tmp, shadowdir;
+ prvm_vec3_t prvmshadowdir;
if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
// get shadow dir
if (r_shadows.integer == 2)
{
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
}
}
R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
- R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
+ R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST, 0, 4, 0, 2, false, false);
if(negated)
GL_BlendEquationSubtract(false);
}
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
}
if (!r_editlights_lockcursor)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
}
int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
n = 0;
while (*s)
{
- t = s;
/*
+ t = s;
shadow = true;
for (;COM_Parse(t, true) && strcmp(
if (COM_Parse(t, true))
int lightnumber, lightcount;
size_t lightindex, range;
dlight_t *light;
- float x, y;
char temp[256];
+ float x, y;
+
if (!r_editlights.integer)
return;
+
+ // update cvars so QC can query them
+ if (r_shadow_selectedlight)
+ {
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
+ Cvar_SetQuick(&r_editlights_current_origin, temp);
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
+ Cvar_SetQuick(&r_editlights_current_angles, temp);
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
+ Cvar_SetQuick(&r_editlights_current_color, temp);
+ Cvar_SetValueQuick(&r_editlights_current_radius, r_shadow_selectedlight->radius);
+ Cvar_SetValueQuick(&r_editlights_current_corona, r_shadow_selectedlight->corona);
+ Cvar_SetValueQuick(&r_editlights_current_coronasize, r_shadow_selectedlight->coronasizescale);
+ Cvar_SetValueQuick(&r_editlights_current_style, r_shadow_selectedlight->style);
+ Cvar_SetValueQuick(&r_editlights_current_shadows, r_shadow_selectedlight->shadow);
+ Cvar_SetQuick(&r_editlights_current_cubemap, r_shadow_selectedlight->cubemapname);
+ Cvar_SetValueQuick(&r_editlights_current_ambient, r_shadow_selectedlight->ambientscale);
+ Cvar_SetValueQuick(&r_editlights_current_diffuse, r_shadow_selectedlight->diffusescale);
+ Cvar_SetValueQuick(&r_editlights_current_specular, r_shadow_selectedlight->specularscale);
+ Cvar_SetValueQuick(&r_editlights_current_normalmode, (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? 1 : 0);
+ Cvar_SetValueQuick(&r_editlights_current_realtimemode, (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? 1 : 0);
+ }
+
+ // draw properties on screen
+ if (!r_editlights_drawproperties.integer)
+ return;
x = vid_conwidth.value - 240;
y = 5;
DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
"sizescale scale : multiply radius (size) of light (1 does nothing)\n"
"originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
"style style : set lightstyle of light (flickering patterns, switches, etc)\n"
-"cubemap basename : set filter cubemap of light (not yet supported)\n"
+"cubemap basename : set filter cubemap of light\n"
"shadows 1/0 : turn on/off shadows\n"
"corona n : set corona intensity\n"
"coronasize n : set corona size (0-1)\n"
Cvar_RegisterVariable(&r_editlights_cursorpushoff);
Cvar_RegisterVariable(&r_editlights_cursorgrid);
Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
+ Cvar_RegisterVariable(&r_editlights_drawproperties);
+ Cvar_RegisterVariable(&r_editlights_current_origin);
+ Cvar_RegisterVariable(&r_editlights_current_angles);
+ Cvar_RegisterVariable(&r_editlights_current_color);
+ Cvar_RegisterVariable(&r_editlights_current_radius);
+ Cvar_RegisterVariable(&r_editlights_current_corona);
+ Cvar_RegisterVariable(&r_editlights_current_coronasize);
+ Cvar_RegisterVariable(&r_editlights_current_style);
+ Cvar_RegisterVariable(&r_editlights_current_shadows);
+ Cvar_RegisterVariable(&r_editlights_current_cubemap);
+ Cvar_RegisterVariable(&r_editlights_current_ambient);
+ Cvar_RegisterVariable(&r_editlights_current_diffuse);
+ Cvar_RegisterVariable(&r_editlights_current_specular);
+ Cvar_RegisterVariable(&r_editlights_current_normalmode);
+ Cvar_RegisterVariable(&r_editlights_current_realtimemode);
Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
Cmd_AddCommand("r_editlights_reload", R_Shadow_EditLights_Reload_f, "reloads rtlights file (or imports from .lights file or .ent file or the map itself)");
=============================================================================
*/
-void R_LightPoint(vec3_t color, const vec3_t p, const int flags)
+void R_LightPoint(float *color, const vec3_t p, const int flags)
{
int i, numlights, flag;
float f, relativepoint[3], dist, dist2, lightradius2;
#define LP_LIGHTMAP 1
#define LP_RTWORLD 2
#define LP_DYNLIGHT 4
-void R_LightPoint(vec3_t color, const vec3_t p, const int flags);
-void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, const int flags);
+void R_LightPoint(float *color, const vec3_t p, const int flags);
+void R_CompleteLightPoint(float *ambientcolor, float *diffusecolor, float *diffusenormal, const vec3_t p, const int flags);
void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
return;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
- R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((ent->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
}
// r_stain
void R_Stain(const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2);
-void R_CalcBeam_Vertex3f(float *vert, const vec3_t org1, const vec3_t org2, float width);
-void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2);
+void R_CalcBeam_Vertex3f(float *vert, const float *org1, const float *org2, float width);
+void R_CalcSprite_Vertex3f(float *vertex3f, const float *origin, const float *left, const float *up, float scalex1, float scalex2, float scaley1, float scaley2);
extern mempool_t *r_main_mempool;
// (in other words, the model has been animated in software)
qboolean forcecurrenttextureupdate; // set for RSurf_ActiveCustomEntity to force R_GetCurrentTexture to recalculate the texture parameters (such as entity alpha)
qboolean modelgeneratedvertex;
+ // skeletal animation can be done by entity (animcache) or per batch,
+ // batch may be non-skeletal even if entity is skeletal, indicating that
+ // the dynamicvertex code path had to apply skeletal manually for a case
+ // where gpu-skinning is not possible, for this reason batch has its own
+ // variables
+ int entityskeletalnumtransforms; // how many transforms are used for this mesh
+ float *entityskeletaltransform3x4; // use gpu-skinning shader on this mesh
float *modelvertex3f;
const r_meshbuffer_t *modelvertex3f_vertexbuffer;
size_t modelvertex3f_bufferoffset;
float *modeltexcoordlightmap2f;
const r_meshbuffer_t *modeltexcoordlightmap2f_vertexbuffer;
size_t modeltexcoordlightmap2f_bufferoffset;
+ unsigned char *modelskeletalindex4ub;
+ const r_meshbuffer_t *modelskeletalindex4ub_vertexbuffer;
+ size_t modelskeletalindex4ub_bufferoffset;
+ unsigned char *modelskeletalweight4ub;
+ const r_meshbuffer_t *modelskeletalweight4ub_vertexbuffer;
+ size_t modelskeletalweight4ub_bufferoffset;
r_vertexmesh_t *modelvertexmesh;
const r_meshbuffer_t *modelvertexmeshbuffer;
const r_meshbuffer_t *modelvertex3fbuffer;
// deformvertexes is used in a q3 shader, and consequently these can
// change on a per-surface basis (according to rsurface.texture)
qboolean batchgeneratedvertex;
+ qboolean batchmultidraw;
+ int batchmultidrawnumsurfaces;
+ const msurface_t **batchmultidrawsurfacelist;
int batchfirstvertex;
int batchnumvertices;
int batchfirsttriangle;
float *batchtexcoordlightmap2f;
const r_meshbuffer_t *batchtexcoordlightmap2f_vertexbuffer;
size_t batchtexcoordlightmap2f_bufferoffset;
+ unsigned char *batchskeletalindex4ub;
+ const r_meshbuffer_t *batchskeletalindex4ub_vertexbuffer;
+ size_t batchskeletalindex4ub_bufferoffset;
+ unsigned char *batchskeletalweight4ub;
+ const r_meshbuffer_t *batchskeletalweight4ub_vertexbuffer;
+ size_t batchskeletalweight4ub_bufferoffset;
int *batchelement3i;
const r_meshbuffer_t *batchelement3i_indexbuffer;
size_t batchelement3i_bufferoffset;
unsigned short *batchelement3s;
const r_meshbuffer_t *batchelement3s_indexbuffer;
size_t batchelement3s_bufferoffset;
+ int batchskeletalnumtransforms;
+ float *batchskeletaltransform3x4;
// rendering pass processing arrays in GL11 and GL13 paths
float *passcolor4f;
const r_meshbuffer_t *passcolor4f_vertexbuffer;
#define BATCHNEED_VERTEXMESH_VERTEXCOLOR (1<< 4) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
#define BATCHNEED_VERTEXMESH_TEXCOORD (1<< 5) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
#define BATCHNEED_VERTEXMESH_LIGHTMAP (1<< 6) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
-#define BATCHNEED_ARRAY_VERTEX (1<< 7) // set up rsurface.batchvertex3f and optionally others
-#define BATCHNEED_ARRAY_NORMAL (1<< 8) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS
-#define BATCHNEED_ARRAY_VECTOR (1<< 9) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS
-#define BATCHNEED_ARRAY_VERTEXCOLOR (1<<10) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
-#define BATCHNEED_ARRAY_TEXCOORD (1<<11) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
-#define BATCHNEED_ARRAY_LIGHTMAP (1<<12) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
-#define BATCHNEED_NOGAPS (1<<13) // force vertex copying (no gaps)
+#define BATCHNEED_VERTEXMESH_SKELETAL (1<< 7) // set up skeletal index and weight data for vertex shader
+#define BATCHNEED_ARRAY_VERTEX (1<< 8) // set up rsurface.batchvertex3f and optionally others
+#define BATCHNEED_ARRAY_NORMAL (1<< 9) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS
+#define BATCHNEED_ARRAY_VECTOR (1<<10) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS
+#define BATCHNEED_ARRAY_VERTEXCOLOR (1<<11) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
+#define BATCHNEED_ARRAY_TEXCOORD (1<<12) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
+#define BATCHNEED_ARRAY_LIGHTMAP (1<<13) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS
+#define BATCHNEED_ARRAY_SKELETAL (1<<14) // set up skeletal index and weight data for vertex shader
+#define BATCHNEED_NOGAPS (1<<15) // force vertex copying if firstvertex is not zero or there are gaps
+#define BATCHNEED_ALLOWMULTIDRAW (1<<16) // allow multiple draws
void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist);
void RSurf_DrawBatch(void);
void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha);
void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy);
-void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb);
+void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal);
void R_SetupShader_ShowDepth(qboolean notrippy);
void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *waterplane, qboolean notrippy);
void R_SetupShader_DeferredLight(const rtlight_t *rtlight);
extern cvar_t r_shadows_throwdirection;
extern cvar_t r_shadows_focus;
extern cvar_t r_shadows_shadowmapscale;
-
+extern cvar_t r_shadows_shadowmapbias;
extern cvar_t r_transparent_alphatocoverage;
extern cvar_t r_transparent_sortsurfacesbynearest;
extern cvar_t r_transparent_useplanardistance;
// sbar.c -- status bar code
#include "quakedef.h"
-#include "time.h"
+#include <time.h>
#include "cl_collision.h"
#include "csprogs.h"
//MED 01/04/97 added hipnotic items array
cachepic_t *hsb_items[2];
-//GAME_SOM stuff:
-cachepic_t *somsb_health;
-cachepic_t *somsb_ammo[4];
-cachepic_t *somsb_armor[3];
-
cachepic_t *zymsb_crosshair_center;
cachepic_t *zymsb_crosshair_line;
cachepic_t *zymsb_crosshair_health;
if (gamemode == GAME_DELUXEQUAKE || gamemode == GAME_BLOODOMNICIDE)
{
}
- else if (gamemode == GAME_SOM)
- {
- sb_disc = Draw_CachePic_Flags ("gfx/disc", CACHEPICFLAG_QUIET);
-
- for (i = 0;i < 10;i++)
- sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
-
- somsb_health = Draw_CachePic_Flags ("gfx/hud_health", CACHEPICFLAG_QUIET);
- somsb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
- somsb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_nails", CACHEPICFLAG_QUIET);
- somsb_ammo[2] = Draw_CachePic_Flags ("gfx/sb_rocket", CACHEPICFLAG_QUIET);
- somsb_ammo[3] = Draw_CachePic_Flags ("gfx/sb_cells", CACHEPICFLAG_QUIET);
- somsb_armor[0] = Draw_CachePic_Flags ("gfx/sb_armor1", CACHEPICFLAG_QUIET);
- somsb_armor[1] = Draw_CachePic_Flags ("gfx/sb_armor2", CACHEPICFLAG_QUIET);
- somsb_armor[2] = Draw_CachePic_Flags ("gfx/sb_armor3", CACHEPICFLAG_QUIET);
- }
else if (gamemode == GAME_NEXUIZ)
{
for (i = 0;i < 10;i++)
sb_scorebar = Draw_CachePic_Flags ("gfx/scorebar", CACHEPICFLAG_QUIET);
//MED 01/04/97 added new hipnotic weapons
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
hsb_weapons[0][0] = Draw_CachePic_Flags ("gfx/inv_laser", CACHEPICFLAG_QUIET);
hsb_weapons[0][1] = Draw_CachePic_Flags ("gfx/inv_mjolnir", CACHEPICFLAG_QUIET);
// MED 01/04/97
// hipnotic weapons
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
int grenadeflashing=0;
for (i=0 ; i<4 ; i++)
if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
{
//MED 01/04/97 changed keys
- if (gamemode != GAME_HIPNOTIC || (i>1))
+ if (!(gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH) || (i>1))
Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
}
//MED 01/04/97 added hipnotic items
// hipnotic items
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
for (i=0 ; i<2 ; i++)
if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
else if (gamemode == GAME_DELUXEQUAKE)
{
}
- else if (gamemode == GAME_SOM)
- {
- if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
- Sbar_DrawScoreboard ();
- else if (sb_lines)
- {
- // this is the top left of the sbar area
- sbar_x = 0;
- sbar_y = vid_conheight.integer - 24*3;
-
- // armor
- if (cl.stats[STAT_ARMOR])
- {
- if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
- Sbar_DrawPic(0, 0, somsb_armor[2]);
- else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
- Sbar_DrawPic(0, 0, somsb_armor[1]);
- else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
- Sbar_DrawPic(0, 0, somsb_armor[0]);
- Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
- }
-
- // health
- Sbar_DrawPic(0, 24, somsb_health);
- Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
-
- // ammo icon
- if (cl.stats[STAT_ITEMS] & IT_SHELLS)
- Sbar_DrawPic(0, 48, somsb_ammo[0]);
- else if (cl.stats[STAT_ITEMS] & IT_NAILS)
- Sbar_DrawPic(0, 48, somsb_ammo[1]);
- else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
- Sbar_DrawPic(0, 48, somsb_ammo[2]);
- else if (cl.stats[STAT_ITEMS] & IT_CELLS)
- Sbar_DrawPic(0, 48, somsb_ammo[3]);
- Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
- if (cl.stats[STAT_SHELLS])
- Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
- }
- }
else if (gamemode == GAME_NEXUIZ)
{
if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
// keys (hipnotic only)
//MED 01/04/97 moved keys here so they would not be overwritten
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
if (cl.stats[STAT_ITEMS] & IT_KEY1)
Sbar_DrawPic (209, 3, sb_items[0]);
qboolean active;
/// false = don't do ClientDisconnect on drop
qboolean clientconnectcalled;
- /// false = don't send datagrams
+ /// false = don't allow spawn
+ qboolean prespawned;
+ /// false = don't allow begin
qboolean spawned;
+ /// false = don't send datagrams
+ qboolean begun;
/// 1 = send svc_serverinfo and advance to 2, 2 doesn't send, then advances to 0 (allowing unlimited sending) when prespawn is received
int sendsignon;
float clmovement_inputtimeout;
/// spawn parms are carried from level to level
- float spawn_parms[NUM_SPAWN_PARMS];
+ prvm_vec_t spawn_parms[NUM_SPAWN_PARMS];
// properties that are sent across the network only when changed
char name[MAX_SCOREBOARDNAME], old_name[MAX_SCOREBOARDNAME];
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
+"#ifdef USECELSHADING\n"
+"# define SHADEDIFFUSE myhalf diffuse = cast_myhalf(min(max(float(dot(surfacenormal, lightnormal)) * 2.0, 0.0), 1.0));\n"
+"# ifdef USEEXACTSPECULARMATH\n"
+"# define SHADESPECULAR(specpow) myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), eyenormal))*-1.0, 0.0)), 1.0 + specpow);specular = max(0.0, specular * 10.0 - 9.0);\n"
+"# else\n"
+"# define SHADESPECULAR(specpow) myhalf3 specularnormal = normalize(lightnormal + eyenormal);myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + specpow);specular = max(0.0, specular * 10.0 - 9.0);\n"
+"# endif\n"
+"#else\n"
+"# define SHADEDIFFUSE myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"# ifdef USEEXACTSPECULARMATH\n"
+"# define SHADESPECULAR(specpow) myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), eyenormal))*-1.0, 0.0)), 1.0 + specpow);\n"
+"# else\n"
+"# define SHADESPECULAR(specpow) myhalf3 specularnormal = normalize(lightnormal + eyenormal);myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + specpow);\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#ifdef GLSL130\n"
"precision highp float;\n"
"# ifdef VERTEX_SHADER\n"
"dp_attribute vec3 Attrib_TexCoord2; // tvector\n"
"dp_attribute vec3 Attrib_TexCoord3; // normal\n"
"dp_attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
+"#ifdef USESKELETAL\n"
+"//uniform mat4 Skeletal_Transform[128];\n"
+"uniform vec4 Skeletal_Transform12[768];\n"
+"dp_attribute vec4 Attrib_SkeletalIndex;\n"
+"dp_attribute vec4 Attrib_SkeletalWeight;\n"
+"#endif\n"
"#endif\n"
"dp_varying mediump vec4 VertexColor;\n"
"\n"
"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#endif\n"
" gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
"#ifdef USETRIPPY\n"
" gl_Position = TrippyVertex(gl_Position);\n"
"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#endif\n"
" gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
" VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
"#ifdef USETRIPPY\n"
"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#endif\n"
" VertexColor = Attrib_Color;\n"
"#ifdef USEDIFFUSE\n"
" TexCoord1 = Attrib_TexCoord0.xy;\n"
"\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#endif\n"
"#ifdef USEALPHAGENVERTEX\n"
" VertexColor = Attrib_Color;\n"
"#endif\n"
"\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" mat3 SkeletalNormalMatrix = mat3(cross(SkeletalMatrix[1].xyz, SkeletalMatrix[2].xyz), cross(SkeletalMatrix[2].xyz, SkeletalMatrix[0].xyz), cross(SkeletalMatrix[0].xyz, SkeletalMatrix[1].xyz)); // is actually transpose(inverse(mat3(SkeletalMatrix))) * det(mat3(SkeletalMatrix))\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+" vec3 SkeletalSVector = normalize(Attrib_TexCoord1.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalTVector = normalize(Attrib_TexCoord2.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalNormal = normalize(Attrib_TexCoord3.xyz * SkeletalNormalMatrix);\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#define Attrib_TexCoord1 SkeletalSVector\n"
+"#define Attrib_TexCoord2 SkeletalTVector\n"
+"#define Attrib_TexCoord3 SkeletalNormal\n"
+"#endif\n"
"#ifdef USEALPHAGENVERTEX\n"
" VertexColor = Attrib_Color;\n"
"#endif\n"
"uniform sampler2D Texture_ScreenNormalMap;\n"
"#endif\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
+"#ifdef USECELOUTLINES\n"
+"uniform sampler2D Texture_ScreenNormalMap;\n"
+"#endif\n"
"uniform sampler2D Texture_ScreenDiffuse;\n"
"uniform sampler2D Texture_ScreenSpecular;\n"
"#endif\n"
"# else\n"
"# ifdef USESHADOWSAMPLER\n"
"# ifdef USESHADOWMAPPCF\n"
-"# define texval(x, y) dp_shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) \n"
-" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
-" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# define texval(off) dp_shadow2D(Texture_ShadowMap2D, vec3(off, shadowmaptc.z)) \n"
+" vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
+" vec4 size = vec4(offset + 1.0, 2.0 - offset);\n"
+"# if USESHADOWMAPPCF > 1\n"
+" vec2 center = (shadowmaptc.xy - offset + 0.5)*ShadowMap_TextureScale;\n"
+" vec4 weight = (vec4(-1.5, -1.5, 2.0, 2.0) + (shadowmaptc.xy - 0.5*offset).xyxy)*ShadowMap_TextureScale.xyxy;\n"
+" f = (1.0/25.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.xy), texval(weight.zy), texval(weight.xw), texval(weight.zw))) +\n"
+" (2.0/25.0)*dot(size, vec4(texval(vec2(weight.z, center.y)), texval(vec2(center.x, weight.w)), texval(vec2(weight.x, center.y)), texval(vec2(center.x, weight.y)))) +\n"
+" (4.0/25.0)*texval(center);\n"
+"# else\n"
+" vec4 weight = (vec4(1.0, 1.0, -0.5, -0.5) + (shadowmaptc.xy - 0.5*offset).xyxy)*ShadowMap_TextureScale.xyxy;\n"
+" f = (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(texval(weight.zw), texval(weight.xw), texval(weight.zy), texval(weight.xy)));\n"
+"# endif \n"
"# else\n"
" f = dp_shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));\n"
"# endif\n"
"uniform highp mat4 ModelViewMatrix;\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+" mat3 SkeletalNormalMatrix = mat3(cross(SkeletalMatrix[1].xyz, SkeletalMatrix[2].xyz), cross(SkeletalMatrix[2].xyz, SkeletalMatrix[0].xyz), cross(SkeletalMatrix[0].xyz, SkeletalMatrix[1].xyz)); // is actually transpose(inverse(mat3(SkeletalMatrix))) * det(mat3(SkeletalMatrix))\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+" vec3 SkeletalSVector = normalize(Attrib_TexCoord1.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalTVector = normalize(Attrib_TexCoord2.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalNormal = normalize(Attrib_TexCoord3.xyz * SkeletalNormalMatrix);\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#define Attrib_TexCoord1 SkeletalSVector\n"
+"#define Attrib_TexCoord2 SkeletalTVector\n"
+"#define Attrib_TexCoord3 SkeletalNormal\n"
+"#endif\n"
" TexCoordSurfaceLightmap = vec4((TexMatrix * Attrib_TexCoord0).xy, 0.0, 0.0);\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
" VertexColor = Attrib_Color;\n"
" // surfacenormal = pixel normal in viewspace\n"
" // LightVector = pixel to light in viewspace\n"
" // CubeVector = pixel in lightspace\n"
-" // eyevector = pixel to view in viewspace\n"
+" // eyenormal = pixel to view direction in viewspace\n"
" vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
" myhalf fade = cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
"#ifdef USEDIFFUSE\n"
" // calculate diffuse shading\n"
" myhalf3 lightnormal = cast_myhalf3(normalize(LightPosition - position));\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
"#endif\n"
"#ifdef USESPECULAR\n"
" // calculate directional shading\n"
-" vec3 eyevector = position * -1.0;\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
-"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(eyevector)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
-"# endif\n"
+" myhalf3 eyenormal = -normalize(cast_myhalf3(position));\n"
+"SHADESPECULAR(SpecularPower * normalmap.a)\n"
"#endif\n"
"\n"
"#if defined(USESHADOWMAP2D)\n"
"#endif\n"
"void main(void)\n"
"{\n"
+"#ifdef USESKELETAL\n"
+" ivec4 si0 = ivec4(Attrib_SkeletalIndex * 3.0);\n"
+" ivec4 si1 = si0 + ivec4(1, 1, 1, 1);\n"
+" ivec4 si2 = si0 + ivec4(2, 2, 2, 2);\n"
+" vec4 sw = Attrib_SkeletalWeight;\n"
+" vec4 SkeletalMatrix1 = Skeletal_Transform12[si0.x] * sw.x + Skeletal_Transform12[si0.y] * sw.y + Skeletal_Transform12[si0.z] * sw.z + Skeletal_Transform12[si0.w] * sw.w;\n"
+" vec4 SkeletalMatrix2 = Skeletal_Transform12[si1.x] * sw.x + Skeletal_Transform12[si1.y] * sw.y + Skeletal_Transform12[si1.z] * sw.z + Skeletal_Transform12[si1.w] * sw.w;\n"
+" vec4 SkeletalMatrix3 = Skeletal_Transform12[si2.x] * sw.x + Skeletal_Transform12[si2.y] * sw.y + Skeletal_Transform12[si2.z] * sw.z + Skeletal_Transform12[si2.w] * sw.w;\n"
+" mat4 SkeletalMatrix = mat4(SkeletalMatrix1, SkeletalMatrix2, SkeletalMatrix3, vec4(0.0, 0.0, 0.0, 1.0));\n"
+"// ivec4 si = ivec4(Attrib_SkeletalIndex);\n"
+"// mat4 SkeletalMatrix = Skeletal_Transform[si.x] * Attrib_SkeletalWeight.x + Skeletal_Transform[si.y] * Attrib_SkeletalWeight.y + Skeletal_Transform[si.z] * Attrib_SkeletalWeight.z + Skeletal_Transform[si.w] * Attrib_SkeletalWeight.w;\n"
+" mat3 SkeletalNormalMatrix = mat3(cross(SkeletalMatrix[1].xyz, SkeletalMatrix[2].xyz), cross(SkeletalMatrix[2].xyz, SkeletalMatrix[0].xyz), cross(SkeletalMatrix[0].xyz, SkeletalMatrix[1].xyz)); // is actually transpose(inverse(mat3(SkeletalMatrix))) * det(mat3(SkeletalMatrix))\n"
+" vec4 SkeletalVertex = Attrib_Position * SkeletalMatrix;\n"
+" SkeletalVertex.w = 1.0;\n"
+" vec3 SkeletalSVector = normalize(Attrib_TexCoord1.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalTVector = normalize(Attrib_TexCoord2.xyz * SkeletalNormalMatrix);\n"
+" vec3 SkeletalNormal = normalize(Attrib_TexCoord3.xyz * SkeletalNormalMatrix);\n"
+"#define Attrib_Position SkeletalVertex\n"
+"#define Attrib_TexCoord1 SkeletalSVector\n"
+"#define Attrib_TexCoord2 SkeletalTVector\n"
+"#define Attrib_TexCoord3 SkeletalNormal\n"
+"#endif\n"
+"\n"
"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR) || defined(USEALPHAGENVERTEX)\n"
" VertexColor = Attrib_Color;\n"
"#endif\n"
" diffusetex += cast_myhalf3(offsetMappedTexture2D(Texture_ReflectMask)) * cast_myhalf3(dp_textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
"#endif\n"
"\n"
+"#ifdef USESPECULAR\n"
+" myhalf3 eyenormal = normalize(cast_myhalf3(EyeVectorFogDepth.xyz));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
" // light source\n"
"#ifdef USEDIFFUSE\n"
" myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
-"#ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"#else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"#endif\n"
+"SHADESPECULAR(SpecularPower * glosstex.a)\n"
" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
"#else\n"
"\n"
"#ifdef SHADING\n"
"# ifdef USEDIFFUSE\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
"# ifdef USESPECULAR\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"# endif\n"
+"SHADESPECULAR(SpecularPower * glosstex.a)\n"
" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"#endif\n"
"#endif\n"
"\n"
+"#ifdef USECELOUTLINES\n"
+"# ifdef USEDEFERREDLIGHTMAP\n"
+"// vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
+" vec4 ScreenTexCoordStep = vec4(PixelToScreenTexCoord.x, 0.0, 0.0, PixelToScreenTexCoord.y);\n"
+" vec4 DepthNeighbors;\n"
+"\n"
+" // enable to test ink on white geometry\n"
+"// color.rgb = vec3(1.0, 1.0, 1.0);\n"
+"\n"
+" // note: this seems to be negative\n"
+" float DepthCenter = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord).b;\n"
+"\n"
+" // edge detect method\n"
+"// DepthNeighbors.x = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord - ScreenTexCoordStep.xy).b;\n"
+"// DepthNeighbors.y = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + ScreenTexCoordStep.xy).b;\n"
+"// DepthNeighbors.z = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + ScreenTexCoordStep.zw).b;\n"
+"// DepthNeighbors.w = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord - ScreenTexCoordStep.zw).b;\n"
+"// float DepthAverage = dot(DepthNeighbors, vec4(0.25, 0.25, 0.25, 0.25));\n"
+"// float DepthDelta = abs(dot(DepthNeighbors.xy, vec2(-1.0, 1.0))) + abs(dot(DepthNeighbors.zw, vec2(-1.0, 1.0)));\n"
+"// color.rgb *= max(0.5, 1.0 - max(0.0, abs(DepthCenter - DepthAverage) - 0.2 * DepthDelta) / (0.01 + 0.2 * DepthDelta));\n"
+"// color.rgb *= step(abs(DepthCenter - DepthAverage), 0.2 * DepthDelta); \n"
+"\n"
+" // shadow method\n"
+" float DepthScale1 = 4.0 / DepthCenter; // inner ink (shadow on object)\n"
+"// float DepthScale1 = -4.0 / DepthCenter; // outer ink (shadow around object)\n"
+"// float DepthScale1 = 0.003;\n"
+" float DepthScale2 = DepthScale1 / 2.0;\n"
+"// float DepthScale3 = DepthScale1 / 4.0;\n"
+" float DepthBias1 = -DepthCenter * DepthScale1;\n"
+" float DepthBias2 = -DepthCenter * DepthScale2;\n"
+"// float DepthBias3 = -DepthCenter * DepthScale3;\n"
+" float DepthShadow = max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2(-1.0, 0.0)).b * DepthScale1 + DepthBias1)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 1.0, 0.0)).b * DepthScale1 + DepthBias1)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, -1.0)).b * DepthScale1 + DepthBias1)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, 1.0)).b * DepthScale1 + DepthBias1)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2(-2.0, 0.0)).b * DepthScale2 + DepthBias2)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 2.0, 0.0)).b * DepthScale2 + DepthBias2)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, -2.0)).b * DepthScale2 + DepthBias2)\n"
+" + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, 2.0)).b * DepthScale2 + DepthBias2)\n"
+"// + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2(-3.0, 0.0)).b * DepthScale3 + DepthBias3)\n"
+"// + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 3.0, 0.0)).b * DepthScale3 + DepthBias3)\n"
+"// + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, -3.0)).b * DepthScale3 + DepthBias3)\n"
+"// + max(0.0, dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + PixelToScreenTexCoord * vec2( 0.0, 3.0)).b * DepthScale3 + DepthBias3)\n"
+" - 0.0;\n"
+" color.rgb *= 1.0 - max(0.0, min(DepthShadow, 1.0));\n"
+"// color.r = DepthCenter / -1024.0;\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#ifdef USEFOG\n"
" color.rgb = FogVertex(color);\n"
"#endif\n"
void* decoder_ptr=NULL;
if(ras_version>0 && ras_dll){
- fileext[4]=0; //Terminator
+ fileext[3]=0; //Terminator
// See if already loaded
if (sfx->rasptr) return true;
S_KillChannel(now_c);
}else{ //We found no channel .... So we need to make a new one ...
channel_new_smart(&prev_c,&now_c);
- now_c->entnum =entnum;
- now_c->entchannel=entchannel;
if(!now_c){
Con_Printf("S_StartSound_OnEnt: could not make new channel_t\n");
channel_delete_and_next(&prev_c,&now_c);
return -1;
}
+ now_c->entnum =entnum;
+ now_c->entchannel=entchannel;
}
//Lets start the sound on the acquired sound source and channel
// paint in the channels.
// channels with zero volumes still advance in time but don't paint.
- ch = channels;
+ ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int
for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
{
sfx = ch->sfx;
// do the actual paint now (may skip work if silent)
paint = paintbuffer;
- wantframes = totalmixframes;
istartframe = 0;
for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
{
MSG_WriteByte (&client->netconnection->message, svc_signonnum);
MSG_WriteByte (&client->netconnection->message, 1);
+ client->prespawned = false; // need prespawn, spawn, etc
client->spawned = false; // need prespawn, spawn, etc
+ client->begun = false; // need prespawn, spawn, etc
client->sendsignon = 1; // send this message, and increment to 2, 2 will be set to 0 by the prespawn command
// clear movement info until client enters the new level properly
strlcpy(client->name, "unconnected", sizeof(client->name));
strlcpy(client->old_name, "unconnected", sizeof(client->old_name));
+ client->prespawned = false;
client->spawned = false;
+ client->begun = false;
client->edict = PRVM_EDICT_NUM(clientnum+1);
if (client->netconnection)
client->netconnection->message.allowoverflow = true; // we can catch it
if (client->netconnection)
SV_SendServerinfo (client);
else
- client->spawned = true;
+ client->prespawned = client->spawned = client->begun = true;
}
unsigned int customizeentityforclient;
unsigned int sendentity;
float f;
- float *v;
+ prvm_vec_t *v;
vec3_t cullmins, cullmaxs;
dp_model_t *model;
{
// angle fixing was requested by global thinking code...
// so store the current angles for later use
- memcpy(host_client->fixangle_angles, PRVM_serveredictvector(ent, angles), sizeof(host_client->fixangle_angles));
+ VectorCopy(PRVM_serveredictvector(ent, angles), host_client->fixangle_angles);
host_client->fixangle_angles_set = TRUE;
// and clear fixangle for the next frame
MSG_WriteByte (msg, stats[STAT_NAILS]);
MSG_WriteByte (msg, stats[STAT_ROCKETS]);
MSG_WriteByte (msg, stats[STAT_CELLS]);
- if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || gamemode == GAME_NEXUIZ)
{
for (i = 0;i < 32;i++)
if (stats[STAT_ACTIVEWEAPON] & (1<<i))
return;
for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
{
- if (!client->spawned || !client->netconnection || client->unreliablemsg.cursize + sv.datagram.cursize > client->unreliablemsg.maxsize || client->unreliablemsg_splitpoints >= (int)(sizeof(client->unreliablemsg_splitpoint)/sizeof(client->unreliablemsg_splitpoint[0])))
+ if (!client->begun || !client->netconnection || client->unreliablemsg.cursize + sv.datagram.cursize > client->unreliablemsg.maxsize || client->unreliablemsg_splitpoints >= (int)(sizeof(client->unreliablemsg_splitpoint)/sizeof(client->unreliablemsg_splitpoint[0])))
continue;
SZ_Write(&client->unreliablemsg, sv.datagram.data, sv.datagram.cursize);
client->unreliablemsg_splitpoint[client->unreliablemsg_splitpoints++] = client->unreliablemsg.cursize;
msg.cursize = 0;
msg.allowoverflow = false;
- if (host_client->spawned)
+ if (host_client->begun)
{
// the player is in the game
MSG_WriteByte (&msg, svc_time);
PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
- if (host_client->spawned)
+ if (host_client->begun)
SV_BroadcastPrintf("%s ^7changed name to %s\n", host_client->old_name, host_client->name);
strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
// send notification to all clients
// frags
host_client->frags = (int)PRVM_serveredictfloat(host_client->edict, frags);
if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
- if(!host_client->spawned && host_client->netconnection)
+ if(!host_client->begun && host_client->netconnection)
host_client->frags = -666;
if (host_client->old_frags != host_client->frags)
{
}
for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
- if (client->netconnection && (client->spawned || client->clientconnectcalled)) // also send MSG_ALL to people who are past ClientConnect, but not spawned yet
+ if (client->netconnection && (client->begun || client->clientconnectcalled)) // also send MSG_ALL to people who are past ClientConnect, but not spawned yet
SZ_Write (&client->netconnection->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
SZ_Clear (&sv.reliable_datagram);
//
// AK possible hack since num_edicts is still 0
ent = PRVM_EDICT_NUM(0);
- memset (ent->fields.vp, 0, prog->entityfields * 4);
+ memset (ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
ent->priv.server->free = false;
PRVM_serveredictstring(ent, model) = PRVM_SetEngineString(prog, sv.worldname);
PRVM_serveredictfloat(ent, modelindex) = 1; // world model
// and we need to set the ->edict pointers to point into the progs edicts
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
{
- host_client->spawned = false;
+ host_client->begun = false;
host_client->edict = PRVM_EDICT_NUM(i + 1);
PRVM_ED_ClearEdict(prog, host_client->edict);
}
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
- host_client->spawned = true;
+ host_client->begun = true;
}
}
prog->error_cmd = Host_Error;
prog->ExecuteProgram = SVVM_ExecuteProgram;
- PRVM_Prog_Load(prog, sv_progs.string, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
+ PRVM_Prog_Load(prog, sv_progs.string, NULL, 0, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
// some mods compiled with scrambling compilers lack certain critical
// global names and field names such as "self" and "time" and "nextthink"
playing = false;
if (sv.active)
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
- if(host_client->spawned)
+ if(host_client->begun)
if(host_client->netconnection)
playing = true;
if(sv.time < 10)
if (sv.paused == 1 && sv_realtime > sv.pausedstart && sv.pausedstart > 0)
{
PRVM_serverglobalfloat(time) = sv.time;
- prog->globals.generic[OFS_PARM0] = sv_realtime - sv.pausedstart;
+ prog->globals.fp[OFS_PARM0] = sv_realtime - sv.pausedstart;
prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
}
{
prvm_prog_t *prog = SVVM_prog;
float dz;
- vec3_t oldorg, neworg, end, traceendpos;
+ vec3_t oldorg, neworg, end, traceendpos, entorigin, entmins, entmaxs;
trace_t trace;
int i;
prvm_edict_t *enemy;
// try the move
VectorCopy (PRVM_serveredictvector(ent, origin), oldorg);
VectorAdd (PRVM_serveredictvector(ent, origin), move, neworg);
+ VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
// flying monsters don't step up
if ( (int)PRVM_serveredictfloat(ent, flags) & (FL_SWIM | FL_FLY) )
neworg[2] += 8;
}
}
- trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+ VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
+ trace = SV_TraceBox(entorigin, entmins, entmaxs, neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
if (trace.fraction == 1)
{
VectorCopy (neworg, end);
end[2] -= sv_stepheight.value*2;
- trace = SV_TraceBox(neworg, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+ trace = SV_TraceBox(neworg, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
if (trace.startsolid)
{
neworg[2] -= sv_stepheight.value;
- trace = SV_TraceBox(neworg, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+ trace = SV_TraceBox(neworg, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
if (trace.startsolid)
return false;
}
float pitchsign = 1;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may differ from vec_t
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size when clipping against monsters
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
- VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
+ VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
else
- Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+ Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
}
float pitchsign = 1;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may differ from vec_t
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size when clipping against monsters
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
- VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
+ VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, false);
+ Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, false);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
}
qboolean pointtrace;
prvm_edict_t *traceowner, *touch;
trace_t trace;
+ // temporary storage because prvm_vec_t may differ from vec_t
+ vec3_t touchmins, touchmaxs;
// bounding box of entire move area
vec3_t clipboxmins, clipboxmaxs;
// size of the moving object
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
- VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
+ VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
+ VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
}
vec3_t paddedmins, paddedmaxs;
if (maxedicts < 1 || resultedicts == NULL)
return 0;
- VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1);
- VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1);
+ // LordHavoc: discovered this actually causes its own bugs (dm6 teleporters being too close to info_teleport_destination)
+ //VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1);
+ //VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1);
+ VectorCopy(mins, paddedmins);
+ VectorCopy(maxs, paddedmaxs);
if (sv_areadebug.integer)
{
int numresultedicts = 0;
{
prvm_prog_t *prog = SVVM_prog;
dp_model_t *model;
- vec3_t mins, maxs;
+ vec3_t mins, maxs, entmins, entmaxs, entangles;
int modelindex;
if (ent == prog->edicts)
model = SV_GetModelByIndex(modelindex);
VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
- VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
// set the abs box
{
// TODO maybe should do this for rotating SOLID_BSP too? Would behave better with rotating doors
// TODO special handling for spheres?
- RotateBBox(PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, angles), mins, maxs);
+ VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
+ VectorCopy(PRVM_serveredictvector(ent, angles), entangles);
+ RotateBBox(entmins, entmaxs, entangles, mins, maxs);
VectorAdd(PRVM_serveredictvector(ent, origin), mins, mins);
VectorAdd(PRVM_serveredictvector(ent, origin), maxs, maxs);
}
{
prvm_prog_t *prog = SVVM_prog;
int contents;
- vec3_t org;
+ vec3_t org, entorigin, entmins, entmaxs;
trace_t trace;
contents = SV_GenericHitSuperContentsMask(ent);
VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
- trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, contents);
+ VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
+ trace = SV_TraceBox(org, entmins, entmaxs, entorigin, ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, contents);
if (trace.startsupercontents & contents)
return true;
else
// FIXME: this breaks entities larger than the hull size
int i;
vec3_t v, m1, m2, s;
- VectorAdd(org, PRVM_serveredictvector(ent, mins), m1);
- VectorAdd(org, PRVM_serveredictvector(ent, maxs), m2);
+ VectorAdd(org, entmins, m1);
+ VectorAdd(org, entmaxs, m2);
VectorSubtract(m2, m1, s);
#define EPSILON (1.0f / 32.0f)
if (s[0] >= EPSILON*2) {m1[0] += EPSILON;m2[0] -= EPSILON;}
#else
// verify if the endpos is REALLY outside solid
VectorCopy(trace.endpos, org);
- trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), org, MOVE_NOMONSTERS, ent, contents);
+ trace = SV_TraceBox(org, entmins, entmaxs, org, MOVE_NOMONSTERS, ent, contents);
if(trace.startsolid)
Con_Printf("SV_TestEntityPosition: trace.endpos detected to be in solid. NOT using it.\n");
else
//
for (i=0 ; i<3 ; i++)
{
- if (IS_NAN(PRVM_serveredictvector(ent, velocity)[i]))
+ if (PRVM_IS_NAN(PRVM_serveredictvector(ent, velocity)[i]))
{
Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, velocity)[i] = 0;
}
- if (IS_NAN(PRVM_serveredictvector(ent, origin)[i]))
+ if (PRVM_IS_NAN(PRVM_serveredictvector(ent, origin)[i]))
{
Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, origin)[i] = 0;
==================
*/
#define STOP_EPSILON 0.1
-static void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+static void ClipVelocity (prvm_vec3_t in, vec3_t normal, prvm_vec3_t out, prvm_vec_t overbounce)
{
int i;
float backoff;
int blocked, bumpcount;
int i, j, numplanes;
float d, time_left, gravity;
- vec3_t dir, push, planes[MAX_CLIP_PLANES], primal_velocity, original_velocity, new_velocity;
+ vec3_t dir, push, planes[MAX_CLIP_PLANES];
+ prvm_vec3_t primal_velocity, original_velocity, new_velocity;
#if 0
vec3_t end;
#endif
int checkcontents;
qboolean rotated;
float savesolid, movetime2, pushltime;
- vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org;
+ vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, pushermins, pushermaxs, checkorigin, checkmins, checkmaxs;
int num_moved;
int numcheckentities;
static prvm_edict_t *checkentities[MAX_EDICTS];
// final position, move it
if (!((int)PRVM_serveredictfloat(check, flags) & FL_ONGROUND) || PRVM_PROG_TO_EDICT(PRVM_serveredictedict(check, groundentity)) != pusher)
{
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
+ VectorCopy(PRVM_serveredictvector(pusher, mins), pushermins);
+ VectorCopy(PRVM_serveredictvector(pusher, maxs), pushermaxs);
+ VectorCopy(PRVM_serveredictvector(check, origin), checkorigin);
+ VectorCopy(PRVM_serveredictvector(check, mins), checkmins);
+ VectorCopy(PRVM_serveredictvector(check, maxs), checkmaxs);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents);
//trace = SV_TraceBox(PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), MOVE_NOMONSTERS, check, checkcontents);
if (!trace.startsolid)
{
PRVM_serveredictfloat(check, flags) = (int)PRVM_serveredictfloat(check, flags) & ~FL_ONGROUND;
// if it is still inside the pusher, block
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
+ VectorCopy(PRVM_serveredictvector(pusher, mins), pushermins);
+ VectorCopy(PRVM_serveredictvector(pusher, maxs), pushermaxs);
+ VectorCopy(PRVM_serveredictvector(check, origin), checkorigin);
+ VectorCopy(PRVM_serveredictvector(check, mins), checkmins);
+ VectorCopy(PRVM_serveredictvector(check, maxs), checkmaxs);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents);
if (trace.startsolid)
{
vec3_t move2;
{
prvm_prog_t *prog = SVVM_prog;
float d, i;
- vec3_t forward, into, side;
+ vec3_t forward, into, side, v_angle;
- AngleVectors (PRVM_serveredictvector(ent, v_angle), forward, NULL, NULL);
+ VectorCopy(PRVM_serveredictvector(ent, v_angle), v_angle);
+ AngleVectors (v_angle, forward, NULL, NULL);
if ((d = DotProduct (stepnormal, forward) + 0.5) < 0)
{
// cut the tangential velocity
int originalmove_groundentity;
int hitsupercontentsmask;
int type;
- vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity;
+ vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity, entmins, entmaxs;
trace_t downtrace, trace;
qboolean applygravity;
type = MOVE_NOMONSTERS; // only clip against bmodels
else
type = MOVE_NORMAL;
- trace = SV_TraceBox(upmove, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), downmove, type, ent, SV_GenericHitSuperContentsMask(ent));
+ VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
+ trace = SV_TraceBox(upmove, entmins, entmaxs, downmove, type, ent, SV_GenericHitSuperContentsMask(ent));
if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
clip |= 1; // but we HAVE found a floor
}
*/
static void SV_CheckWaterTransition (prvm_edict_t *ent)
{
+ vec3_t entorigin;
prvm_prog_t *prog = SVVM_prog;
// LordHavoc: bugfixes in this function are keyed to the sv_gameplayfix_bugfixedcheckwatertransition cvar - if this cvar is 0 then all the original bugs should be reenabled for compatibility
int cont;
- cont = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_serveredictvector(ent, origin)));
+ VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
+ cont = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(entorigin));
if (!PRVM_serveredictfloat(ent, watertype))
{
// just spawned here
{
// angle fixing was requested by physics code...
// so store the current angles for later use
- memcpy(host_client->fixangle_angles, PRVM_serveredictvector(ent, angles), sizeof(host_client->fixangle_angles));
+ VectorCopy(PRVM_serveredictvector(ent, angles), host_client->fixangle_angles);
host_client->fixangle_angles_set = TRUE;
// and clear fixangle for the next frame
{
prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
- if (!host_client->spawned)
+ if (!host_client->begun)
return;
// make sure the velocity is sane (not a NaN)
{
prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
- if (!host_client->spawned)
+ if (!host_client->begun)
return;
// make sure the velocity is sane (not a NaN)
{
// angle fixing was requested by physics code...
// so store the current angles for later use
- memcpy(host_client->fixangle_angles, PRVM_serveredictvector(ent, angles), sizeof(host_client->fixangle_angles));
+ VectorCopy(PRVM_serveredictvector(ent, angles), host_client->fixangle_angles);
host_client->fixangle_angles_set = TRUE;
// and clear fixangle for the next frame
{
prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
- if (!host_client->spawned)
+ if (!host_client->begun)
{
memset(&host_client->cmd, 0, sizeof(host_client->cmd));
return;
static void DropPunchAngle (void)
{
prvm_prog_t *prog = SVVM_prog;
- float len;
- vec3_t v;
+ vec_t len;
+ vec3_t punchangle, punchvector;
- len = VectorNormalizeLength (PRVM_serveredictvector(host_client->edict, punchangle));
+ VectorCopy(PRVM_serveredictvector(host_client->edict, punchangle), punchangle);
+ VectorCopy(PRVM_serveredictvector(host_client->edict, punchvector), punchvector);
- len -= 10*sv.frametime;
- if (len < 0)
- len = 0;
- VectorScale (PRVM_serveredictvector(host_client->edict, punchangle), len, PRVM_serveredictvector(host_client->edict, punchangle));
+ len = VectorNormalizeLength(punchangle);
+ if (len > 0)
+ {
+ len -= 10*sv.frametime;
+ if (len < 0)
+ len = 0;
+ VectorScale(punchangle, len, punchangle);
+ }
- VectorCopy(PRVM_serveredictvector(host_client->edict, punchvector), v);
- len = VectorNormalizeLength(v);
+ len = VectorNormalizeLength(punchvector);
if (len > 0)
{
len -= 20*sv.frametime;
if (len < 0)
len = 0;
- VectorScale(v, len, v);
+ VectorScale(punchvector, len, punchvector);
}
- VectorCopy(v, PRVM_serveredictvector(host_client->edict, punchvector));
+
+ VectorCopy(punchangle, PRVM_serveredictvector(host_client->edict, punchangle));
+ VectorCopy(punchvector, PRVM_serveredictvector(host_client->edict, punchvector));
}
/*
{
prvm_prog_t *prog = SVVM_prog;
int i;
- vec3_t wishvel;
- float speed, newspeed, wishspeed, addspeed, accelspeed, temp;
+ vec3_t wishvel, v_angle;
+ vec_t speed, newspeed, wishspeed, addspeed, accelspeed, temp;
// user intentions
- AngleVectors (PRVM_serveredictvector(host_client->edict, v_angle), forward, right, up);
+ VectorCopy(PRVM_serveredictvector(host_client->edict, v_angle), v_angle);
+ AngleVectors(v_angle, forward, right, up);
for (i=0 ; i<3 ; i++)
wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove;
void SV_ClientThink (void)
{
prvm_prog_t *prog = SVVM_prog;
- vec3_t v_angle;
+ vec3_t v_angle, angles, velocity;
//Con_Printf("clientthink for %ims\n", (int) (sv.frametime * 1000));
// angles
// show 1/3 the pitch angle and all the roll angle
VectorAdd (PRVM_serveredictvector(host_client->edict, v_angle), PRVM_serveredictvector(host_client->edict, punchangle), v_angle);
- PRVM_serveredictvector(host_client->edict, angles)[ROLL] = V_CalcRoll (PRVM_serveredictvector(host_client->edict, angles), PRVM_serveredictvector(host_client->edict, velocity))*4;
+ VectorCopy(PRVM_serveredictvector(host_client->edict, angles), angles);
+ VectorCopy(PRVM_serveredictvector(host_client->edict, velocity), velocity);
+ PRVM_serveredictvector(host_client->edict, angles)[ROLL] = V_CalcRoll (angles, velocity)*4;
if (!PRVM_serveredictfloat(host_client->edict, fixangle))
{
PRVM_serveredictvector(host_client->edict, angles)[PITCH] = -v_angle[PITCH]/3;
if (sv_numreadmoves < 1)
return;
// only start accepting input once the player is spawned
- if (!host_client->spawned)
+ if (!host_client->begun)
return;
#if DEBUGMOVES
Con_Printf("SV_ExecuteClientMoves: read %i moves at sv.time %f\n", sv_numreadmoves, (float)sv.time);
// if the client hasn't progressed through signons yet,
// ignore any clc_ackframes we get (they're probably from the
// previous level)
- if (host_client->spawned && host_client->latestframenum < num)
+ if (host_client->begun && host_client->latestframenum < num)
{
int i;
for (i = host_client->latestframenum + 1;i < num;i++)
"DP_QC_STRFTIME "
"DP_QC_STRINGBUFFERS "
"DP_QC_STRINGBUFFERS_CVARLIST "
+"DP_QC_STRINGBUFFERS_EXT_WIP "
"DP_QC_STRINGCOLORFUNCTIONS "
"DP_QC_STRING_CASE_FUNCTIONS "
"DP_QC_STRREPLACE "
static void VM_SV_setorigin(prvm_prog_t *prog)
{
prvm_edict_t *e;
- float *org;
VM_SAFEPARMCOUNT(2, VM_setorigin);
VM_Warning(prog, "setorigin: can not modify free entity\n");
return;
}
- org = PRVM_G_VECTOR(OFS_PARM1);
- VectorCopy (org, PRVM_serveredictvector(e, origin));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
SV_LinkEdict(e);
static void VM_SV_setsize(prvm_prog_t *prog)
{
prvm_edict_t *e;
- float *min, *max;
+ vec3_t mins, maxs;
VM_SAFEPARMCOUNT(3, VM_setsize);
VM_Warning(prog, "setsize: can not modify free entity\n");
return;
}
- min = PRVM_G_VECTOR(OFS_PARM1);
- max = PRVM_G_VECTOR(OFS_PARM2);
- SetMinMaxSize(prog, e, min, max, false);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
+ SetMinMaxSize(prog, e, mins, maxs, false);
}
*/
static void VM_SV_particle(prvm_prog_t *prog)
{
- float *org, *dir;
- float color;
- float count;
+ vec3_t org, dir;
+ int color;
+ int count;
VM_SAFEPARMCOUNT(4, VM_SV_particle);
- org = PRVM_G_VECTOR(OFS_PARM0);
- dir = PRVM_G_VECTOR(OFS_PARM1);
- color = PRVM_G_FLOAT(OFS_PARM2);
- count = PRVM_G_FLOAT(OFS_PARM3);
- SV_StartParticle (org, dir, (int)color, (int)count);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
+ color = (int)PRVM_G_FLOAT(OFS_PARM2);
+ count = (int)PRVM_G_FLOAT(OFS_PARM3);
+ SV_StartParticle (org, dir, color, count);
}
static void VM_SV_ambientsound(prvm_prog_t *prog)
{
const char *samp;
- float *pos;
- float vol, attenuation;
+ vec3_t pos;
+ prvm_vec_t vol, attenuation;
int soundnum, large;
VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
- pos = PRVM_G_VECTOR (OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
samp = PRVM_G_STRING(OFS_PARM1);
vol = PRVM_G_FLOAT(OFS_PARM2);
attenuation = PRVM_G_FLOAT(OFS_PARM3);
*/
static void VM_SV_traceline(prvm_prog_t *prog)
{
- float *v1, *v2;
+ vec3_t v1, v2;
trace_t trace;
int move;
prvm_edict_t *ent;
prog->xfunction->builtinsprofile += 30;
- v1 = PRVM_G_VECTOR(OFS_PARM0);
- v2 = PRVM_G_VECTOR(OFS_PARM1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
move = (int)PRVM_G_FLOAT(OFS_PARM2);
ent = PRVM_G_EDICT(OFS_PARM3);
- if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
+ if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
// LordHavoc: added this for my own use, VERY useful, similar to traceline
static void VM_SV_tracebox(prvm_prog_t *prog)
{
- float *v1, *v2, *m1, *m2;
+ vec3_t v1, v2, m1, m2;
trace_t trace;
int move;
prvm_edict_t *ent;
prog->xfunction->builtinsprofile += 30;
- v1 = PRVM_G_VECTOR(OFS_PARM0);
- m1 = PRVM_G_VECTOR(OFS_PARM1);
- m2 = PRVM_G_VECTOR(OFS_PARM2);
- v2 = PRVM_G_VECTOR(OFS_PARM3);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
move = (int)PRVM_G_FLOAT(OFS_PARM4);
ent = PRVM_G_EDICT(OFS_PARM5);
- if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
+ if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
{
int i;
float gravity;
- vec3_t move, end;
+ vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
vec3_t original_origin;
vec3_t original_velocity;
vec3_t original_angles;
VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
- trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
+ VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
+ VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
+ VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
+ trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
*/
static void VM_SV_checkpvs(prvm_prog_t *prog)
{
- vec3_t viewpos;
+ vec3_t viewpos, absmin, absmax;
prvm_edict_t *viewee;
#if 1
unsigned char *pvs;
}
#if 1
- if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+ if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
{
// no PVS support on this worldmodel... darn
PRVM_G_FLOAT(OFS_RETURN) = 3;
PRVM_G_FLOAT(OFS_RETURN) = 2;
return;
}
- PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
+ VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
+ VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
+ PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
#else
// using fat PVS like FTEQW does (slow)
- if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+ if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
{
// no PVS support on this worldmodel... darn
PRVM_G_FLOAT(OFS_RETURN) = 3;
PRVM_G_FLOAT(OFS_RETURN) = 2;
return;
}
- PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
+ VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
+ VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
+ PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
#endif
}
static void VM_SV_droptofloor(prvm_prog_t *prog)
{
prvm_edict_t *ent;
- vec3_t end;
+ vec3_t end, entorigin, entmins, entmaxs;
trace_t trace;
VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
if (sv_gameplayfix_unstickentities.integer)
SV_UnstickEntity(ent);
- trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+ VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
+ trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
{
vec3_t offset, org;
*/
static void VM_SV_pointcontents(prvm_prog_t *prog)
{
+ vec3_t point;
VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
- PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
+ PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
}
/*
VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
imgname = PRVM_G_STRING(OFS_PARM1);
- size = (int) PRVM_G_FLOAT(OFS_PARM2);
+ size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
if(size > 65535)
size = 65535;
static void VM_SV_getlight(prvm_prog_t *prog)
{
vec3_t ambientcolor, diffusecolor, diffusenormal;
- vec_t *p;
+ vec3_t p;
VM_SAFEPARMCOUNT(1, VM_SV_getlight);
- p = PRVM_G_VECTOR(OFS_PARM0);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
VectorClear(ambientcolor);
VectorClear(diffusecolor);
VectorClear(diffusenormal);
VM_Warning(prog, "copyentity: can not modify free entity\n");
return;
}
- memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
+ memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
SV_LinkEdict(out);
}
{
int i;
const char *s;
+ vec3_t org;
VM_SAFEPARMCOUNT(5, VM_SV_effect);
s = PRVM_G_STRING(OFS_PARM1);
if (!s[0])
return;
}
- SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+ SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
}
static void VM_SV_te_blood(prvm_prog_t *prog)
if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
{
VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
- VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
}
model = SV_GetModelByIndex(modelindex);
VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
- VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
tagmatrix = identitymatrix;
int parentindex;
const char *tagname;
int returncode;
- vec3_t fo, le, up, trans;
+ vec3_t forward, left, up, origin;
const dp_model_t *model;
VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
- Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
- VectorScale(le, -1, PRVM_serverglobalvector(v_right));
+ Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
+ VectorCopy(forward, PRVM_serverglobalvector(v_forward));
+ VectorNegate(left, PRVM_serverglobalvector(v_right));
+ VectorCopy(up, PRVM_serverglobalvector(v_up));
+ VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
model = SV_GetModelFromEdict(e);
VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
- VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
+ VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
- Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
+ Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
- VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
- VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
- VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
+ VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
+ VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
+ VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
switch(returncode)
{
// #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
static void VM_SV_trailparticles(prvm_prog_t *prog)
{
+ vec3_t start, end;
VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
MSG_WriteByte(&sv.datagram, svc_trailparticles);
MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
- MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
- MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
+ MSG_WriteVector(&sv.datagram, start, sv.protocol);
+ MSG_WriteVector(&sv.datagram, end, sv.protocol);
SV_FlushBroadcastMessages();
}
int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
dp_model_t *model = SV_GetModelByIndex(modelindex);
- float blendfrac;
int numblends;
int bonenum;
int blendindex;
framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
frameblend_t frameblend[MAX_FRAMEBLENDS];
- matrix4x4_t blendedmatrix;
+ matrix4x4_t bonematrix;
matrix4x4_t matrix;
PRVM_G_FLOAT(OFS_RETURN) = 0;
if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
lastbone = min(lastbone, model->num_bones - 1);
lastbone = min(lastbone, skeleton->model->num_bones - 1);
VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
- VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
- blendfrac = 1.0f - retainfrac;
+ VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
- frameblend[numblends].lerp *= blendfrac;
+ ;
for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
{
- memset(&blendedmatrix, 0, sizeof(blendedmatrix));
- Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
+ memset(&bonematrix, 0, sizeof(bonematrix));
for (blendindex = 0;blendindex < numblends;blendindex++)
{
Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
- Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
+ Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
}
- skeleton->relativetransforms[bonenum] = blendedmatrix;
+ Matrix4x4_Normalize3(&bonematrix, &bonematrix);
+ Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
}
PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
}
VM_log, // #532
VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
-NULL, // #535
-NULL, // #536
-NULL, // #537
-NULL, // #538
+VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
NULL, // #539
VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
//
/// an error will cause the entire program to exit
-void Sys_Error (const char *error, ...) DP_FUNC_PRINTF(1);
+void Sys_Error (const char *error, ...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN;
/// (may) output text to terminal which launched program
void Sys_PrintToTerminal(const char *text);
#include "qtypes.h"
#include "quakedef.h"
-#include "errno.h"
+#include <errno.h>
#include "resource.h"
#include "conproc.h"
vid.softpixels = (unsigned int *) vidx11_ximage[vidx11_ximage_pos]->data;
DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+ ++vidx11_shmwait;
+ XShmPutImage(vidx11_display, win, vidx11_gc, vidx11_ximage[!vidx11_ximage_pos], 0, 0, 0, 0, vid.width, vid.height, True);
+
// save mouse motion so we can deal with it later
in_mouse_x = 0;
in_mouse_y = 0;
- while(vidx11_shmwait)
+ while(vidx11_shmwait > 1)
HandleEvents();
in_mouse_x_save += in_mouse_x;
in_mouse_y_save += in_mouse_y;
in_mouse_x = 0;
in_mouse_y = 0;
-
- ++vidx11_shmwait;
- XShmPutImage(vidx11_display, win, vidx11_gc, vidx11_ximage[!vidx11_ximage_pos], 0, 0, 0, 0, vid.width, vid.height, True);
} else {
// no buffer switching here, we just flush the renderer
DPSOFTRAST_Finish();
if (vid_usingvsync != vid_usevsync)
{
vid_usingvsync = vid_usevsync;
- if (qglXSwapIntervalSGI (vid_usevsync))
+ if (qglXSwapIntervalSGI && qglXSwapIntervalSGI (vid_usevsync))
Con_Print("glXSwapIntervalSGI didn't accept the vid_vsync change, it will take effect on next vid_restart (GLX_SGI_swap_control does not allow turning off vsync)\n");
}
*/
#undef WIN32_LEAN_AND_MEAN //hush a warning, SDL.h redefines this
#include <SDL.h>
-#include <SDL_syswm.h>
#include <stdio.h>
#include "quakedef.h"
scr_numtouchscreenareas = 0;
if (vid_touchscreen.integer)
{
- vec3_t move, aim, click;
+ float move[3], aim[3], click[3];
static qboolean buttons[16];
static keydest_t oldkeydest;
keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest;
vid.support.ext_draw_range_elements = true;
vid.support.ext_framebuffer_object = false;//true;
- // FIXME remove this workaround once FBO + npot texture mapping is fixed
- if(!vid.support.arb_texture_non_power_of_two)
- {
- vid.support.arb_framebuffer_object = false;
- vid.support.ext_framebuffer_object = false;
- }
-
vid.support.ext_packed_depth_stencil = false;
vid.support.ext_stencil_two_side = false;
vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D");
// Adding the OS independent XPM version --blub
#include "darkplaces.xpm"
#include "nexuiz.xpm"
+#if SDL_MAJOR_VERSION == 1
+#if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
+#include <SDL_syswm.h>
+#endif
+#endif
static SDL_Surface *icon = NULL;
static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
{
else
vid.support.ext_framebuffer_object = GL_CheckExtension("GL_EXT_framebuffer_object", extfbofuncs, "-nofbo", false);
- // FIXME remove this workaround once FBO + npot texture mapping is fixed
- if(!vid.support.arb_texture_non_power_of_two)
- {
- vid.support.arb_framebuffer_object = false;
- vid.support.ext_framebuffer_object = false;
- }
-
vid.support.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil", NULL, "-nopackeddepthstencil", false);
vid.support.ext_stencil_two_side = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false);
vid.support.ext_texture_3d = GL_CheckExtension("GL_EXT_texture3D", texture3dextfuncs, "-notexture3d", false);
(vid_sRGB_fallback.integer >= 3) // force fallback
||
(vid_sRGB_fallback.integer >= 2 && // fallback if framebuffer is 8bit
- !(r_viewfbo.integer >= 2 && vid.support.ext_framebuffer_object && vid.samples < 2))
+ !(r_viewfbo.integer >= 2 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2))
)
vid.sRGB2D = vid.sRGB3D = false;
vid.support.ext_draw_range_elements = true;
vid.support.ext_framebuffer_object = true;
- // FIXME remove this workaround once FBO + npot texture mapping is fixed
- if(!vid.support.arb_texture_non_power_of_two)
- {
- vid.support.arb_framebuffer_object = false;
- vid.support.ext_framebuffer_object = false;
- }
-
vid.support.ext_texture_3d = true;
//vid.support.ext_texture_compression_s3tc = true;
vid.support.ext_texture_filter_anisotropic = true;
vid.support.ext_draw_range_elements = true;
vid.support.ext_framebuffer_object = true;
- // FIXME remove this workaround once FBO + npot texture mapping is fixed
- if(!vid.support.arb_texture_non_power_of_two)
- {
- vid.support.arb_framebuffer_object = false;
- vid.support.ext_framebuffer_object = false;
- }
-
vid.support.ext_texture_3d = true;
vid.support.ext_texture_compression_s3tc = true;
vid.support.ext_texture_filter_anisotropic = true;
ent = &cl.entities[cl.viewentity];
cldead = (cl.stats[STAT_HEALTH] <= 0 && cl.stats[STAT_HEALTH] != -666 && cl.stats[STAT_HEALTH] != -2342);
- V_CalcRefdefUsing(&ent->render.matrix, cl.viewangles, !ent->persistent.trail_allowed, cl.onground, cl.cmd.jump, cl.stats[STAT_VIEWHEIGHT], cldead, cl.intermission, cl.velocity); // FIXME use a better way to detect teleport/warp than trail_allowed
+ V_CalcRefdefUsing(&ent->render.matrix, cl.viewangles, !ent->persistent.trail_allowed, cl.onground, cl.cmd.jump, cl.stats[STAT_VIEWHEIGHT], cldead, cl.intermission != 0, cl.velocity); // FIXME use a better way to detect teleport/warp than trail_allowed
}
else
{
vec3_t paddedmins, paddedmaxs;
int igrid[3], igridmins[3], igridmaxs[3];
- VectorSet(paddedmins, requestmins[0] - 1.0f, requestmins[1] - 1.0f, requestmins[2] - 1.0f);
- VectorSet(paddedmaxs, requestmaxs[0] + 1.0f, requestmaxs[1] + 1.0f, requestmaxs[2] + 1.0f);
+ // LordHavoc: discovered this actually causes its own bugs (dm6 teleporters being too close to info_teleport_destination)
+ //VectorSet(paddedmins, requestmins[0] - 1.0f, requestmins[1] - 1.0f, requestmins[2] - 1.0f);
+ //VectorSet(paddedmaxs, requestmaxs[0] + 1.0f, requestmaxs[1] + 1.0f, requestmaxs[2] + 1.0f);
+ VectorCopy(requestmins, paddedmins);
+ VectorCopy(requestmaxs, paddedmaxs);
// FIXME: if areagrid_marknumber wraps, all entities need their
// ent->priv.server->areagridmarknumber reset
const char* dllnames [] =
{
# if defined(WIN32)
+ "libode3.dll",
+ "libode2.dll",
"libode1.dll",
# elif defined(MACOSX)
+ "libode.3.dylib",
+ "libode.2.dylib",
"libode.1.dylib",
# else
+ "libode.so.3",
+ "libode.so.2",
"libode.so.1",
# endif
NULL
prvm_prog_t *prog = world->prog;
const float *iv;
const int *ie;
- dBodyID body = (dBodyID)ed->priv.server->ode_body;
+ dBodyID body;
dMass mass;
- dReal test;
const dReal *ovelocity, *ospinvelocity;
void *dataID;
dp_model_t *model;
vec_t radius;
vec3_t scale;
vec_t spinlimit;
+ vec_t test;
qboolean gravity;
qboolean geom_modified = false;
edict_odefunc_t *func, *nextf;
if (physics_ode_trick_fixnan.integer)
{
test = VectorLength2(origin) + VectorLength2(forward) + VectorLength2(left) + VectorLength2(up) + VectorLength2(velocity) + VectorLength2(spinvelocity);
- if (IS_NAN(test))
+ if (VEC_IS_NAN(test))
{
modified = true;
//Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .axis_forward = '%f %f %f' .axis_left = '%f %f %f' .axis_up = %f %f %f' .spinvelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2], spinvelocity[0], spinvelocity[1], spinvelocity[2]);
if (physics_ode_trick_fixnan.integer >= 2)
Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .angles = '%f %f %f' .avelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], angles[0], angles[1], angles[2], avelocity[0], avelocity[1], avelocity[2]);
test = VectorLength2(origin);
- if (IS_NAN(test))
+ if (VEC_IS_NAN(test))
VectorClear(origin);
test = VectorLength2(forward) * VectorLength2(left) * VectorLength2(up);
- if (IS_NAN(test))
+ if (VEC_IS_NAN(test))
{
VectorSet(angles, 0, 0, 0);
VectorSet(forward, 1, 0, 0);
VectorSet(up, 0, 0, 1);
}
test = VectorLength2(velocity);
- if (IS_NAN(test))
+ if (VEC_IS_NAN(test))
VectorClear(velocity);
test = VectorLength2(spinvelocity);
- if (IS_NAN(test))
+ if (VEC_IS_NAN(test))
{
VectorClear(avelocity);
VectorClear(spinvelocity);
return NULL;
}
if (pool == NULL)
- Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
+ {
+ if(olddata)
+ pool = ((memheader_t *)((unsigned char *) olddata - sizeof(memheader_t)))->pool;
+ else
+ Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
+ }
if (mem_mutex)
Thread_LockMutex(mem_mutex);
if (developer_memory.integer)
//store a value to a pointer
case OP_STOREP_IF:
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
ptr->_float = (float)OPA->_int;
break;
case OP_STOREP_FI:
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
break;
case OP_STOREP_I:
case OP_GSTOREP_I:
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
case OP_GSTOREP_S:
case OP_STOREP_FNC: // pointers
case OP_GSTOREP_FNC:
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
- PR_RunError (progfuncs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(progfuncs, pr_xfunction->s_name), OPB->_int, addressableused);
+ PR_RunError (progfuncs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(progfuncs, pr_xfunction->s_name), OPB->_int, prinst->addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_int = OPA->_int;
break;
case OP_STOREP_V:
case OP_GSTOREP_V:
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
break;
case OP_STOREP_C: //store character in a string
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_vector[2] *= OPA->_float;
break;
case OP_MULSTOREP_F: // e.f *= f
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPC->_float = (ptr->_float *= OPA->_float);
break;
case OP_MULSTOREP_VF: // e.v *= f
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F: // e.f /= f
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F: // e.f += f
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPC->_float = (ptr->_float += OPA->_float);
break;
case OP_ADDSTOREP_V: // e.v += v
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F: // e.f -= f
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPC->_float = (ptr->_float -= OPA->_float);
break;
case OP_SUBSTOREP_V: // e.v -= v
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
break;
case OP_LOADP_C: //load character from a string
i = (unsigned int)OPA->_int + (unsigned int)OPB->_float;
- if ((unsigned int)i >= addressableused)
+ if ((unsigned int)i >= prinst->addressableused)
{
i = (unsigned int)OPB->_float;
ptr = (eval_t*)PR_StringToNative(progfuncs, OPA->_int);
case OP_LOADP_S:
case OP_LOADP_FNC:
i = OPA->_int + OPB->_int*4;
- if ((unsigned int)i >= addressableused)
+ if ((unsigned int)i >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
case OP_LOADP_V:
i = OPA->_int + OPB->_int*4;
- if ((unsigned int)i >= addressableused)
+ if ((unsigned int)i >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
break;
case OP_BITSETP: // .b (+) a
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
break;
case OP_BITCLRP: // .b (-) a
- if ((unsigned int)OPB->_int >= addressableused)
+ if ((unsigned int)OPB->_int >= prinst->addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
//for 64bit systems. :)
//addressable memory is memory available to the vm itself for writing.
//once allocated, it cannot be freed for the lifetime of the VM.
-void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount)
+void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount)
{
ammount = (ammount + 4)&~3; //round up to 4
- if (addressableused + ammount > addressablesize)
+ if (prinst->addressableused + ammount > prinst->addressablesize)
{
/*only do this if the caller states that it can cope with addressable-block relocations/resizes*/
if (externs->addressablerelocated)
#if 0//def _DEBUG
int oldtot = addressablesize;
#endif
- int newsize = (addressableused + ammount + 4096) & ~(4096-1);
- newblock = VirtualAlloc (NULL, addressablesize, MEM_RESERVE, PAGE_NOACCESS);
+ int newsize = (prinst->addressableused + ammount + 4096) & ~(4096-1);
+ newblock = VirtualAlloc (NULL, prinst->addressablesize, MEM_RESERVE, PAGE_NOACCESS);
if (newblock)
{
- VirtualAlloc (newblock, addressableused, MEM_COMMIT, PAGE_READWRITE);
- memcpy(newblock, addressablehunk, addressableused);
+ VirtualAlloc (newblock, prinst->addressableused, MEM_COMMIT, PAGE_READWRITE);
+ memcpy(newblock, prinst->addressablehunk, prinst->addressableused);
#if 0//def _DEBUG
- VirtualAlloc (addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS);
+ VirtualAlloc (prinst->addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS);
#else
- VirtualFree (addressablehunk, 0, MEM_RELEASE);
+ VirtualFree (prinst->addressablehunk, 0, MEM_RELEASE);
#endif
- PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
- addressablehunk = newblock;
- addressablesize = newsize;
+ PRAddressableRelocate(progfuncs, prinst->addressablehunk, newblock, prinst->addressableused);
+ prinst->addressablehunk = newblock;
+ prinst->addressablesize = newsize;
}
#else
char *newblock;
- int newsize = (addressableused + ammount + 1024*1024) & ~(1024*1024-1);
- newblock = realloc(newblock, addressablesize);
+ int newsize = (prinst->addressableused + ammount + 1024*1024) & ~(1024*1024-1);
+ newblock = realloc(newblock, prinst->addressablesize);
if (newblock)
{
- PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
- addressablehunk = newblock;
- addressablesize = newsize;
+ PRAddressableRelocate(progfuncs, prinst->addressablehunk, newblock, prinst->addressableused);
+ prinst->addressablehunk = newblock;
+ prinst->addressablesize = newsize;
}
#endif
}
- if (addressableused + ammount > addressablesize)
+ if (prinst->addressableused + ammount > prinst->addressablesize)
Sys_Error("Not enough addressable memory for progs VM");
}
- addressableused += ammount;
+ prinst->addressableused += ammount;
#ifdef _WIN32
- if (!VirtualAlloc (addressablehunk, addressableused, MEM_COMMIT, PAGE_READWRITE))
+ if (!VirtualAlloc (prinst->addressablehunk, prinst->addressableused, MEM_COMMIT, PAGE_READWRITE))
Sys_Error("VirtualAlloc failed. Blame windows.");
#endif
- return &addressablehunk[addressableused-ammount];
+ return &prinst->addressablehunk[prinst->addressableused-ammount];
+}
+
+
+#define MARKER 0xF1E3E3E7u
+typedef struct
+{
+ unsigned int next;
+ unsigned int prev;
+ unsigned int size;
+} qcmemfreeblock_t;
+typedef struct
+{
+ unsigned int marker;
+ unsigned int size;
+} qcmemusedblock_t;
+static void PF_fmem_unlink(progfuncs_t *pr, qcmemfreeblock_t *p)
+{
+ qcmemfreeblock_t *np;
+ if (p->prev)
+ {
+ np = (qcmemfreeblock_t*)(pr->stringtable + p->prev);
+ np->next = p->next;
+ }
+ else
+ pr->inst->mfreelist = p->next;
+ if (p->next)
+ {
+ np = (qcmemfreeblock_t*)(pr->stringtable + p->next);
+ np->prev = p->prev;
+ }
+}
+static void *PR_memalloc (progfuncs_t *progfuncs, unsigned int size)
+{
+ qcmemfreeblock_t *p, *np;
+ qcmemusedblock_t *ub = NULL;
+ unsigned int b,n;
+ /*round size up*/
+ size = (size+sizeof(qcmemusedblock_t) + 63) & ~63;
+
+ b = prinst->mfreelist;
+ while (b)
+ {
+ if (b < 0 || b >= prinst->addressableused)
+ {
+ printf("PF_memalloc: memory corruption\n");
+ PR_StackTrace(progfuncs);
+ return NULL;
+ }
+ p = (qcmemfreeblock_t*)(progfuncs->stringtable + b);
+ if (p->size >= size)
+ {
+ if (p->next && p->next < b + p->size ||
+ p->next >= prinst->addressableused ||
+ b + p->size >= prinst->addressableused ||
+ p->prev >= b)
+ {
+ printf("PF_memalloc: memory corruption\n");
+ PR_StackTrace(progfuncs);
+ return NULL;
+ }
+
+ ub = (qcmemusedblock_t*)p;
+ if (p->size > size + 63)
+ {
+ /*make a new header just after it, with basically the same properties, and shift the important fields over*/
+ n = b + size;
+ np = (qcmemfreeblock_t*)(progfuncs->stringtable + b + size);
+ np->prev = p->prev;
+ np->next = p->next;
+ np->size = p->size - size;
+ if (np->prev)
+ {
+ p = (qcmemfreeblock_t*)(progfuncs->stringtable + np->prev);
+ p->next = n;
+ }
+ else
+ prinst->mfreelist = n;
+ if (p->next)
+ {
+ p = (qcmemfreeblock_t*)(progfuncs->stringtable + np->next);
+ p->prev = n;
+ }
+ }
+ else
+ {
+ size = p->size; /*alloc the entire block*/
+ /*unlink this entry*/
+ PF_fmem_unlink(progfuncs, p);
+ }
+ break;
+ }
+ }
+
+ /*assign more space*/
+ if (!ub)
+ {
+ ub = PRAddressableExtend(progfuncs, size);
+ if (!ub)
+ {
+ printf("PF_memalloc: memory exausted\n");
+ PR_StackTrace(progfuncs);
+ return NULL;
+ }
+ }
+ memset(ub, 0, size);
+ ub->marker = MARKER;
+ ub->size = size;
+ return ub+1;
+}
+static void PR_memfree (progfuncs_t *progfuncs, void *memptr)
+{
+ qcmemusedblock_t *ub;
+ qcmemfreeblock_t *p, *np;
+ unsigned int l, ln;
+ unsigned int size;
+ unsigned int ptr = memptr?((char*)memptr - progfuncs->stringtable):0;
+
+ /*freeing NULL is ignored*/
+ if (!ptr)
+ return;
+ if (ptr < sizeof(qcmemusedblock_t) || ptr >= prinst->addressableused)
+ {
+ printf("PF_memfree: pointer invalid - out of range (%u >= %u)\n", ptr, prinst->addressableused);
+ PR_StackTrace(progfuncs);
+ return;
+ }
+
+ ub = (qcmemusedblock_t*)(progfuncs->stringtable + ptr);
+ ub--;
+ ptr = (char*)ub - progfuncs->stringtable;
+ if (ub->marker != MARKER || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst->addressableused)
+ {
+ printf("PF_memfree: memory corruption or double free\n");
+ PR_StackTrace(progfuncs);
+ return;
+ }
+ ub->marker = 0;
+ size = ub->size;
+
+ for (ln = prinst->mfreelist, l = 0; ;)
+ {
+ if (ln < 0 || ln >= prinst->addressableused)
+ {
+ printf("PF_memfree: memory corruption\n");
+ PR_StackTrace(progfuncs);
+ return;
+ }
+ if (!ln || ln >= ptr)
+ {
+ np = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
+ if (l && l+np->size>ptr)
+ {
+ printf("PF_memfree: double free\n");
+ PR_StackTrace(progfuncs);
+ return;
+ }
+
+ /*generate the free block, now we know its proper values*/
+ p = (qcmemfreeblock_t*)(progfuncs->stringtable + ptr);
+ p->prev = l;
+ p->next = ln;
+ p->size = size;
+
+ /*update the next's previous*/
+ if (p->next)
+ {
+ np = (qcmemfreeblock_t*)(progfuncs->stringtable + p->next);
+ np->prev = p->prev;
+
+ /*extend this block and kill the next if they are adjacent*/
+ if (p->next == ptr + size)
+ {
+ p->size += np->size;
+ PF_fmem_unlink(progfuncs, np);
+ }
+ }
+
+ /*update the link to get here*/
+ if (!l)
+ prinst->mfreelist = ptr;
+ else
+ {
+ np = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
+ np->next = ptr;
+
+ /*we're adjacent to the previous block, so merge them by killing the newly freed region*/
+ if (l + np->size == ptr)
+ {
+ np->size += size;
+ PF_fmem_unlink(progfuncs, p);
+ }
+ }
+ break;
+ }
+
+ l = ln;
+ p = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
+ ln = p->next;
+ }
}
void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
{
- addressableused = 0;
+ prinst->addressableused = 0;
if (totalammount < 0) //flush
{
- totalammount = addressablesize;
+ totalammount = prinst->addressablesize;
// return;
}
#ifdef _WIN32
- if (addressablehunk && addressablesize != totalammount)
+ if (prinst->addressablehunk && prinst->addressablesize != totalammount)
{
- VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
- addressablehunk = NULL;
+ VirtualFree(prinst->addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
+ prinst->addressablehunk = NULL;
}
- if (!addressablehunk)
- addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS);
+ if (!prinst->addressablehunk)
+ prinst->addressablehunk = VirtualAlloc (prinst->addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS);
#else
- if (addressablehunk)
- free(addressablehunk);
- addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
-// memset(addressablehunk, 0xff, totalammount);
+ if (prinst->addressablehunk && prinst->addressablesize != totalammount)
+ {
+ free(prinst->addressablehunk);
+ prinst->addressablehunk = NULL;
+ }
+ if (!prinst->addressablehunk)
+ prinst->addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
+// memset(prinst->addressablehunk, 0xff, totalammount);
#endif
- if (!addressablehunk)
+ if (!prinst->addressablehunk)
Sys_Error("Out of memory\n");
- addressablesize = totalammount;
+ prinst->addressablesize = totalammount;
}
int PR_InitEnts(progfuncs_t *progfuncs, int max_ents)
prinst->edicttable = PRHunkAlloc(progfuncs, maxedicts*sizeof(struct edicts_s *));
sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize);
prinst->edicttable[0] = sv_edicts;
- ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableAlloc(progfuncs, max_fields_size);
+ ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableExtend(progfuncs, max_fields_size);
QC_ClearEdict(progfuncs, sv_edicts);
sv_num_edicts = 1;
if (!str)
return 0;
- if (str >= progfuncs->stringtable && str < progfuncs->stringtable + addressableused)
+ if (str >= progfuncs->stringtable && str < progfuncs->stringtable + prinst->addressableused)
return str - progfuncs->stringtable;
for (i = prinst->numallocedstrings-1; i >= 0; i--)
}
}
- if (str >= addressableused)
+ if ((unsigned int)str >= (unsigned int)prinst->addressableused)
{
printf("invalid string offset %x\n", str);
PR_StackTrace(progfuncs);
PR_QueryField,
QC_ClearEdict,
QC_FindPrefixedGlobals,
- PRAddressableAlloc,
- PR_AllocTempStringLen
+ PR_memalloc,
+ PR_AllocTempStringLen,
+ PR_memfree,
};
#undef printf
#undef extensionbuiltin
#undef field
#undef shares
+#undef maxedicts
#undef sv_num_edicts
f = inst->parms->memfree;
- for ( i=1 ; i<inst->maxedicts; i++)
+ for ( i=1 ; i<inst->inst->maxedicts; i++)
{
- e = (edictrun_t *)(inst->prinst->edicttable[i]);
- inst->prinst->edicttable[i] = NULL;
+ e = (edictrun_t *)(inst->inst->edicttable[i]);
+ inst->inst->edicttable[i] = NULL;
if (e)
{
// e->entnum = i;
PRHunkFree(inst, 0);
#ifdef _WIN32
- VirtualFree(inst->addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
+ VirtualFree(inst->inst->addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
#else
- free(inst->addressablehunk);
+ free(inst->inst->addressablehunk);
#endif
- if (inst->prinst->allocedstrings)
- f(inst->prinst->allocedstrings);
- inst->prinst->allocedstrings = NULL;
- if (inst->prinst->tempstrings)
- f(inst->prinst->tempstrings);
- inst->prinst->tempstrings = NULL;
+ if (inst->inst->allocedstrings)
+ f(inst->inst->allocedstrings);
+ inst->inst->allocedstrings = NULL;
+ if (inst->inst->tempstrings)
+ f(inst->inst->tempstrings);
+ inst->inst->tempstrings = NULL;
/*
inst->prinst->extensionbuiltin = eb;
}
*/
- if (inst->prinst->field)
- f(inst->prinst->field);
- if (inst->prinst->shares)
- f(inst->prinst->shares); //free memory
- f(inst->prinst);
+ if (inst->inst->field)
+ f(inst->inst->field);
+ if (inst->inst->shares)
+ f(inst->inst->shares); //free memory
+ f(inst->inst);
f(inst);
}
}
#undef memalloc
#undef pr_trace
+#undef pr_progstate
+#undef pr_argc
funcs = ext->memalloc(sizeof(progfuncs_t));
memcpy(funcs, &deffuncs, sizeof(progfuncs_t));
- funcs->prinst = ext->memalloc(sizeof(prinst_t));
- memset(funcs->prinst,0, sizeof(prinst_t));
+ funcs->inst = ext->memalloc(sizeof(prinst_t));
+ memset(funcs->inst,0, sizeof(prinst_t));
- funcs->pr_trace = &funcs->prinst->pr_trace;
- funcs->progstate = &funcs->pr_progstate;
- funcs->callargc = &funcs->pr_argc;
+ funcs->pr_trace = &funcs->inst->pr_trace;
+ funcs->progstate = &funcs->inst->progstate;
+ funcs->callargc = &funcs->inst->pr_argc;
funcs->parms = ext;
prinst->edicttable[num] = *(struct edict_s **)&e = (void*)memalloc(externs->edictsize);
memset(e, 0, externs->edictsize);
- e->fields = PRAddressableAlloc(progfuncs, fields_size);
+ e->fields = PRAddressableExtend(progfuncs, fields_size);
e->entnum = num;
QC_ClearEdict(progfuncs, (struct edict_s*)e);
l = strlen(string) + 1;
- newc = PRAddressableAlloc (progfuncs, l<minlength?minlength:l);
+ newc = progfuncs->AddressableAlloc (progfuncs, l<minlength?minlength:l);
+ if (!newc)
+ return progfuncs->stringtable;
+
new_p = newc;
for (i=0 ; i< l ; i++)
}
len=sizeof(char)*pr_progs->numstrings;
- s = PRAddressableAlloc(progfuncs, len);
+ s = PRAddressableExtend(progfuncs, len);
memcpy(s, pr_strings, len);
pr_strings = (char *)s;
len=sizeof(float)*pr_progs->numglobals;
- s = PRAddressableAlloc(progfuncs, len);
+ s = PRAddressableExtend(progfuncs, len);
memcpy(s, pr_globals, len);
glob = pr_globals = (float *)s;
//extern progfuncs_t *progfuncs;
-#define prinst progfuncs->prinst
+#define prinst progfuncs->inst
#define externs progfuncs->parms
#include "pr_comp.h"
int PRHunkMark(progfuncs_t *progfuncs);
void PRHunkFree(progfuncs_t *progfuncs, int mark);
void *PRHunkAlloc(progfuncs_t *progfuncs, int size);
-void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount);
+void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount);
#ifdef printf
#undef LIKEPRINTF
//initlib.c
+int mfreelist;
var(char *, addressablehunk);
-#define addressablehunk prinst->addressablehunk
var(unsigned int, addressableused);
-#define addressableused prinst->addressableused
var(unsigned int, addressablesize);
-#define addressablesize prinst->addressablesize
//var(extensionbuiltin_t *, extensionbuiltin);
pbool (*Decompile) (progfuncs_t *prinst, char *fname);
- struct prinst_s *prinst; //internal variables. Leave alone.
+ struct prinst_s *inst; //internal variables. Leave alone.
int *callargc; //number of args of built-in call
void (*RegisterBuiltin) (progfuncs_t *prinst, char *, builtin_t);
void (*EntClear) (progfuncs_t *progfuncs, struct edict_s *e);
void (*FindPrefixGlobals) (progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) );
- void *(*AddressableAlloc) (progfuncs_t *progfuncs, int ammount); /*returns memory within the qc block, use stringtoprogs to get a usable qc pointer/string*/
+ void *(*AddressableAlloc) (progfuncs_t *progfuncs, unsigned int ammount); /*returns memory within the qc block, use stringtoprogs to get a usable qc pointer/string*/
string_t (*AllocTempString) (progfuncs_t *prinst, char **str, unsigned int len);
+ void (*AddressableFree) (progfuncs_t *progfuncs, void *mem); /*frees a block of addressable memory*/
};
typedef struct progexterns_s {
void QCC_BspModels (void)
{
+/*
int p;
char *gamedir;
int i;
if (result != 0)
QCC_Error(ERR_INTERNAL, "QCC_BspModels() system returned non zero (failure) with: qbsp %s/%s ; light -extra %s/%s (%i)\n", gamedir, name, gamedir, name, errno);
}
+*/
}
// CopyString returns an offset from the string heap