// Sauerbraten Editing related bindings
// found in autoexec.cfg in your sauerbraten directory
-editbind SPACE [ cancelsel ]
-editbind MOUSE1 [ if $blendpaintmode [paintblendmap] [editdrag] ]
+editbind SPACE [ cancelsel ]
+editbind MOUSE1 [ editdrag ]
editbind MOUSE3 [ selcorners ]
-editbind MOUSE2 [ if $blendpaintmode [rotateblendbrush] [editextend] ]
+editbind MOUSE2 [ editextend ]
editbind J [ gotosel ]
editbind COMMA [ domodifier 10; onrelease entautoview ]
delta_edit_0 = [
- if $blendpaintmode [
- scrollblendbrush $arg1
- ] [
- editfacewentpush $arg1 1 // Fill and Empty cube
- ]
+ editfacewentpush $arg1 1 // Fill and Empty cube
]
delta_edit_1 = [ nodebug [ gridpower (+ $arg1 $gridpower) ] ]
delta_edit_2 = [ editfacewentpush $arg1 0 ] // push face/corners selected
delta_edit_3 = [ editfacewentpush $arg1 2 ] // push corner pointed at by cursor
-delta_edit_4 = [ if $blendpaintmode [rotateblendbrush $arg1] [editrotate $arg1] ] // rotate 90 degrees
delta_edit_5 = [ entproperty 0 $arg1 ] // and the others
delta_edit_6 = [ edittex $arg1 ] // change textures
delta_edit_10 = [ entautoview $arg1 ]
//editbind RALT [multiplier2 = 32;onrelease [multiplier2 = 16]]
multiplier = 1
multiplier2 = 16
-
-//Blendmap Painting
-editbind KP0 [setblendpaintmode 0]
-editbind KP1 [setblendpaintmode 1]
-editbind KP2 [setblendpaintmode 2]
-editbind KP3 [setblendpaintmode 3]
-editbind KP4 [setblendpaintmode 4]
-editbind KP5 [setblendpaintmode 5]
-
-editbind KP8 [scrollblendbrush -1]
-editbind KP9 [scrollblendbrush 1]
-
] [] [] [uniform sampler2D decal;]
]
-glowshader = [
- defershader 0 $arg1 [
- defuniformparam "glowcolor" 1 1 1 // glow color
- worldshader @arg1 [] [] [
- vec3 glow = texture2D(glowmap, texcoord0).rgb;
- glow *= glowcolor.rgb;
- gl_FragColor = diffuse*lm + vec4(glow, 0.0);
- ] [] [uniform sampler2D glowmap;]
- glareworldshader @arg1 [] [
- vec3 glow = texture2D(glowmap, texcoord0).rgb;
- glow *= glowcolor.rgb;
- float k = max(glow.r, max(glow.g, glow.b));
- gl_FragColor.rgb = min(k*k*32.0, 1.0) * glow;
- gl_FragColor.a =
- //:variantoverride texture2D(lightmap, texcoord1).a
- colorparams.a
- ;
- ] [] [
- uniform sampler2D glowmap;
- //:variant uniform sampler2D lightmap;
- ]
- ]
-]
-glowshader "glowworld"
-glowshader "glowalphaworld"
-
-defershader 0 "pulseworld" [
- defuniformparam "pulsespeed" 1 // pulse frequency (Hz)
- worldshader "pulseworld" [
- pulse = abs(fract(millis * pulsespeed.x)*2.0 - 1.0);
- ] [
- vec3 diffuse2 = texture2D(decal, texcoord0).rgb;
- diffuse.rgb = mix(diffuse.rgb, diffuse2, pulse);
- ] [] [uniform float millis; varying float pulse;] [uniform sampler2D decal;]
-]
-
-pulseglowshader = [
- defershader 0 $arg1 [
- defuniformparam "glowcolor" 1 1 1 // glow color
- defuniformparam "pulseglowspeed" 1 // pulse frequency (Hz)
- defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color
- worldshader @arg1 [
- pulse = mix(glowcolor.rgb, pulseglowcolor.rgb, abs(fract(millis * pulseglowspeed.x)*2.0 - 1.0));
- ] [] [
- vec3 glow = texture2D(glowmap, texcoord0).rgb;
- gl_FragColor = diffuse*lm + vec4(glow*pulse, 0.0);
- ] [uniform float millis; varying vec3 pulse;] [uniform sampler2D glowmap;]
- glareworldshader @arg1 [
- pulse = mix(glowcolor.rgb, pulseglowcolor.rgb, abs(fract(millis * pulseglowspeed.x)*2.0 - 1.0));
- ] [
- vec3 glow = texture2D(glowmap, texcoord0).rgb;
- glow *= pulse;
- float k = max(glow.r, max(glow.g, glow.b));
- gl_FragColor.rgb = min(k*k*32.0, 1.0) * glow;
- gl_FragColor.a =
- //:variantoverride texture2D(lightmap, texcoord1).a
- colorparams.a
- ;
- ] [uniform float millis; varying vec3 pulse;] [
- uniform sampler2D glowmap;
- //:variant uniform sampler2D lightmap;
- ]
- ]
-]
-pulseglowshader "pulseglowworld"
-pulseglowshader "pulseglowalphaworld"
-
shader 0 "noglareworld" [
attribute vec4 vvertex;
uniform mat4 camprojmatrix;
}
]
-shader 0 "depthfxworld" [
- attribute vec4 vvertex;
- uniform mat4 camprojmatrix;
- uniform vec4 depthscale, depthoffsets;
- varying vec4 depthranges;
- void main(void)
- {
- gl_Position = camprojmatrix * vvertex;
- depthranges = depthoffsets + gl_Position.w*depthscale;
- }
-] [
- varying vec4 depthranges;
- void main(void)
- {
- gl_FragColor = depthranges;
- }
-]
-
-shader 0 depthfxsplitworld [
- attribute vec4 vvertex;
- uniform mat4 camprojmatrix;
- uniform vec4 depthscale, depthoffsets;
- varying vec4 depthranges;
- void main(void)
- {
- gl_Position = camprojmatrix * vvertex;
- depthranges = depthoffsets + gl_Position.w*depthscale;
- }
-] [
- varying vec4 depthranges;
- void main(void)
- {
- vec4 ranges = vec4(depthranges.x, fract(depthranges.yzw));
- ranges.xy -= ranges.yz*vec2(0.00390625, 0.00390625);
- gl_FragColor = ranges;
- }
-]
-
// bumptype:
// o -> orthonormalize
// t -> tangent space cam
// s -> spec
// S -> spec map
// p -> parallax
-// g -> glow
-// G -> pulse glow
// a -> alpha map
btopt = [ >= (strstr $bumptype $arg1) 0 ]
bumptype = $arg2
stype = (? (btopt "e") 3 1)
if (! (btopt "i")) [
- if (btopt "G") [
- defuniformparam "glowcolor" 1 1 1 // glow color
- defuniformparam "pulseglowspeed" 1 // pulse frequency (Hz)
- defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color
- ] [if (btopt "g") [
- defuniformparam "glowcolor" 1 1 1 // glow color
- ]]
if (btopt "S") [
defuniformparam "specscale" 6 6 6 // spec map multiplier
] [if (btopt "s") [
if (|| (btopt "p") (btopt "P")) [
defuniformparam "parallaxscale" 0.06 -0.03 // parallax scaling
]
- if (btopt "R") [
- defuniformparam "envscale" 1 1 1 // reflectivity map multiplier
- ] [if (btopt "r") [
- defuniformparam "envscale" 0.2 0.2 0.2 // reflectivity
- ]]
] [
if (btopt "s") [stype = (+ $stype 8)]
]
uniform mat4 camprojmatrix;
uniform vec2 texgenscroll;
varying vec2 texcoord0, texcoord1;
- @(if (|| (btopt "t") (btopt "r")) [result [uniform vec3 camera; varying vec3 camvec;]])
- @(if (btopt "G") [result [uniform float millis; varying float pulse;]])
- @(if (btopt "r") [result [varying mat3 world;]])
void main(void)
{
gl_Position = camprojmatrix * vvertex;
]])
]])
- @(if (btopt "G") [result [
- pulse = abs(fract(millis*pulseglowspeed.x)*2.0 - 1.0);
- ]])
-
@(if (|| (! (btopt "i")) (btopt "s")) [result [
//:dynlight
]])
varying vec2 texcoord0, texcoord1;
uniform sampler2D diffusemap, lmcolor, lmdir;
@(if (|| (! (btopt "i")) (btopt "s") (btopt "p") (btopt "P")) [result [uniform sampler2D normalmap;]])
- @(if (|| (btopt "t") (btopt "r")) [result [varying vec3 camvec;]])
- @(if (btopt "g") [result [uniform sampler2D glowmap;]])
- @(if (btopt "G") [result [varying float pulse;]])
- @(if (btopt "r") [result [uniform samplerCube envmap; varying mat3 world;]])
- @(if (|| (! (btopt "i")) (btopt "s")) [result [uniform vec4 ambient;]])
void main(void)
{
@(if (|| (! (btopt "i")) (btopt "s")) [result [
]])
@(if (|| (btopt "p") (btopt "P")) [] [result [#define dtc texcoord0]])
- @(if (|| (! (btopt "i")) (btopt "S") (btopt "a")) [result [
- vec4 diffuse = texture2D(diffusemap, dtc);
- @(if (&& (btopt "a") (! (btopt "S"))) [result [
- #define alpha diffuse.a
- ]])
- ]])
- @(if (! (btopt "i")) [result [
- diffuse.rgb *= colorparams.rgb;
- ]])
- @(if (|| (! (btopt "i")) (btopt "s") (btopt "a")) [result [
- @(if (! (btopt "P")) [
- if (&& (btopt "a") (btopt "S")) [result [
- vec4 normal = texture2D(normalmap, dtc);
- #define alpha normal.a
- #define bump normal.rgb
- ]] [result [
- vec3 bump = texture2D(normalmap, dtc).rgb;
- ]]
- ])
- bump = bump*2.0 - 1.0;
- ]])
-
@(if (btopt "s") [result [
vec3 halfangle = normalize(camdir + lmlv);
float spec = pow(clamp(dot(halfangle, bump), 0.0, 1.0), @(? (btopt "i") "128.0" "32.0"));
]])
]])
- @(if (|| (! (btopt "i")) (btopt "s")) [result [
- lmc.rgb = max(lmc.rgb*clamp(dot(lmlv, bump), 0.0, 1.0), ambient.xyz);
- @(if (btopt "i") [result [
- //:dynlight lmc
-
- @(? (btopt "g") "diffuse.rgb" "gl_FragColor.rgb") = diffuse.rgb * lmc.rgb;
- ]] [result [
- //:shadowmap lmc
- //:dynlight lmc
-
- @(? (|| (btopt "g") (btopt "r")) "diffuse.rgb" "gl_FragColor.rgb") = diffuse.rgb * lmc.rgb;
- ]])
- ]])
-
- @(if (btopt "r") [result [
- vec3 rvec;
- @(if (btopt "t") [result [
- vec3 rvects = 2.0*bump*dot(camvec, bump) - camvec;
- rvec = world * rvects;
- ]] [result [
- vec3 bumpw = world * bump;
- rvec = 2.0*bumpw*dot(camvec, bumpw) - camvec;
- ]])
- vec3 reflect = textureCube(envmap, rvec).rgb;
- @@(if (btopt "R") [result [
- vec3 rmod = envscale.xyz*diffuse.a;
- ]] [result [
- #define rmod envscale.xyz
- ]])
- @(? (btopt "g") "diffuse.rgb" "gl_FragColor.rgb") = mix(diffuse.rgb, reflect, rmod);
- ]])
-
- @(if (btopt "a") [result [
- @(? (btopt "g") "diffuse.rgb" "gl_FragColor.rgb") *= alpha;
- ]])
-
- @(if (btopt "g") [result [
- vec3 glow = texture2D(glowmap, dtc).rgb;
- @@(if (btopt "G") [result [
- vec3 pulsecol = mix(glowcolor.xyz, pulseglowcolor.xyz, pulse);
- ]])
- @@(if (btopt "i") [result [
- glow *= @(? (btopt "G") "pulsecol" "glowcolor.xyz");
- float k = max(glow.r, max(glow.g, glow.b));
- k = min(k*k*32.0, 1.0);
- @(if (btopt "s") [result [
- gl_FragColor.rgb = glow*k + diffuse.rgb;
- ]] [result [
- gl_FragColor.rgb = glow*k;
- gl_FragColor.a =
- //:variantoverride texture2D(lmcolor, texcoord1).a
- colorparams.a
- ;
- ]])
- ]] [result [
- gl_FragColor.rgb = glow * @(? (btopt "G") "pulsecol" "glowcolor.xyz") + diffuse.rgb;
- ]])
- ]])
-
@(if (btopt "a") [result [
gl_FragColor.a *= alpha;
//:fog fogcolor * alpha
fastshader bumpspecmapalphaworld bumpalphaworld 1
altshader bumpspecmapalphaworld bumpalphaworld
-bumpshader "bumpglowworld" "g"
-bumpshader "bumpspecglowworld" "otsg"
-altshader bumpspecglowworld bumpglowworld
-bumpshader "bumpspecmapglowworld" "otsSg"
-fastshader bumpspecmapglowworld bumpglowworld 2
-altshader bumpspecmapglowworld bumpglowworld
-
-bumpshader "bumppulseglowworld" "gG"
-bumpshader "bumpspecpulseglowworld" "otsgG"
-altshader bumpspecpulseglowworld bumppulseglowworld
-bumpshader "bumpspecmappulseglowworld" "otsSgG"
-fastshader bumpspecmappulseglowworld bumppulseglowworld 2
-altshader bumpspecmappulseglowworld bumppulseglowworld
-
bumpshader "bumpparallaxworld" "pot"
fastshader bumpparallaxworld bumpworld 1
altshader bumpparallaxworld bumpworld
fastshader bumpspecmapparallaxworld bumpworld 1
altshader bumpspecmapparallaxworld bumpworld
-bumpshader "bumpparallaxglowworld" "potg"
-fastshader bumpparallaxglowworld bumpglowworld 1
-altshader bumpparallaxglowworld bumpglowworld
-bumpshader "bumpspecparallaxglowworld" "potsg"
-fastshader bumpspecparallaxglowworld bumpparallaxglowworld 2
-fastshader bumpspecparallaxglowworld bumpglowworld 1
-altshader bumpspecparallaxglowworld bumpglowworld
-bumpshader "bumpspecmapparallaxglowworld" "potsSg"
-fastshader bumpspecmapparallaxglowworld bumpparallaxglowworld 2
-fastshader bumpspecmapparallaxglowworld bumpglowworld 1
-altshader bumpspecmapparallaxglowworld bumpglowworld
-
-bumpshader "bumpparallaxpulseglowworld" "potgG"
-fastshader bumpparallaxpulseglowworld bumppulseglowworld 1
-altshader bumpparallaxpulseglowworld bumppulseglowworld
-bumpshader "bumpspecparallaxpulseglowworld" "potsgG"
-fastshader bumpspecparallaxpulseglowworld bumpparallaxpulseglowworld 2
-fastshader bumpspecparallaxpulseglowworld bumppulseglowworld 1
-altshader bumpspecparallaxpulseglowworld bumppulseglowworld
-bumpshader "bumpspecmapparallaxpulseglowworld" "potsSgG"
-fastshader bumpspecmapparallaxpulseglowworld bumpparallaxpulseglowworld 2
-fastshader bumpspecmapparallaxpulseglowworld bumppulseglowworld 1
-altshader bumpspecmapparallaxpulseglowworld bumppulseglowworld
-
bumpshader "bumpenvworldalt" "e"
bumpshader "bumpenvworld" "eor"
altshader bumpenvworld bumpenvworldalt
altshader bumpenvspecmapworld bumpenvworldalt
fastshader bumpenvspecmapworld bumpenvworldalt 2
-bumpshader "bumpenvglowworldalt" "eg"
-bumpshader "bumpenvglowworld" "eorg"
-altshader bumpenvglowworld bumpenvglowworldalt
-fastshader bumpenvglowworld bumpenvglowworldalt 2
-bumpshader "bumpenvspecglowworld" "eotsrg"
-altshader bumpenvspecglowworld bumpenvglowworldalt
-fastshader bumpenvspecglowworld bumpenvglowworldalt 2
-bumpshader "bumpenvspecmapglowworld" "eotsSrRg"
-altshader bumpenvspecmapglowworld bumpenvglowworldalt
-fastshader bumpenvspecmapglowworld bumpenvglowworldalt 2
-
-bumpshader "bumpenvpulseglowworldalt" "egG"
-bumpshader "bumpenvpulseglowworld" "eorgG"
-altshader bumpenvpulseglowworld bumpenvpulseglowworldalt
-fastshader bumpenvpulseglowworld bumpenvpulseglowworldalt 2
-bumpshader "bumpenvspecpulseglowworld" "eotsrgG"
-altshader bumpenvspecpulseglowworld bumpenvpulseglowworldalt
-fastshader bumpenvspecpulseglowworld bumpenvpulseglowworldalt 2
-bumpshader "bumpenvspecmappulseglowworld" "eotsSrRgG"
-altshader bumpenvspecmappulseglowworld bumpenvpulseglowworldalt
-fastshader bumpenvspecmappulseglowworld bumpenvpulseglowworldalt 2
-
bumpshader "bumpenvparallaxworldalt" "epot"
altshader bumpenvparallaxworldalt bumpenvworldalt
bumpshader "bumpenvparallaxworld" "epotr"
fastshader bumpenvspecmapparallaxworld bumpenvparallaxworldalt 2
fastshader bumpenvspecmapparallaxworld bumpenvworldalt 1
-bumpshader "bumpenvparallaxglowworldalt" "epotg"
-altshader bumpenvparallaxglowworldalt bumpenvglowworldalt
-bumpshader "bumpenvparallaxglowworld" "epotrg"
-altshader bumpenvparallaxglowworld bumpenvparallaxglowworldalt
-fastshader bumpenvparallaxglowworld bumpenvparallaxglowworldalt 2
-fastshader bumpenvparallaxglowworld bumpenvglowworldalt 1
-bumpshader "bumpenvspecparallaxglowworld" "epotsrg"
-altshader bumpenvspecparallaxglowworld bumpenvparallaxglowworldalt
-fastshader bumpenvspecparallaxglowworld bumpenvparallaxglowworldalt 2
-fastshader bumpenvspecparallaxglowworld bumpenvglowworldalt 1
-bumpshader "bumpenvspecmapparallaxglowworld" "epotsSrRg"
-altshader bumpenvspecmapparallaxglowworld bumpenvparallaxglowworldalt
-fastshader bumpenvspecmapparallaxglowworld bumpenvparallaxglowworldalt 2
-fastshader bumpenvspecmapparallaxglowworld bumpenvglowworldalt 1
-
-bumpshader "bumpenvparallaxpulseglowworldalt" "epotgG"
-altshader bumpenvparallaxpulseglowworldalt bumpenvpulseglowworldalt
-bumpshader "bumpenvparallaxpulseglowworld" "epotrgG"
-altshader bumpenvparallaxpulseglowworld bumpenvparallaxpulseglowpulseglowworldalt
-fastshader bumpenvparallaxpulseglowworld bumpenvparallaxpulseglowpulseglowworldalt 2
-fastshader bumpenvparallaxpulseglowworld bumpenvpulseglowworldalt 1
-bumpshader "bumpenvspecparallaxpulseglowworld" "epotsrgG"
-altshader bumpenvspecparallaxpulseglowworld bumpenvparallaxpulseglowworldalt
-fastshader bumpenvspecparallaxpulseglowworld bumpenvparallaxpulseglowworldalt 2
-fastshader bumpenvspecparallaxpulseglowworld bumpenvpulseglowworldalt 1
-bumpshader "bumpenvspecmapparallaxpulseglowworld" "epotsSrRgG"
-altshader bumpenvspecmapparallaxpulseglowworld bumpenvparallaxpulseglowworldalt
-fastshader bumpenvspecmapparallaxpulseglowworld bumpenvparallaxpulseglowworldalt 2
-fastshader bumpenvspecmapparallaxpulseglowworld bumpenvpulseglowworldalt 1
-
////////////////////////////////////////////////
//
// model shaders
]])
@(if (mdlopt "e") [result [
uniform mat3 modelworld;
- uniform vec2 envmapscale;
varying vec3 rvec;
varying float rmod;
]])
@(if (mdlopt "e") [result [
float invfresnel = dot(camdir, mnormal);
rvec = modelworld * (2.0*invfresnel*mnormal - camdir);
- rmod = envmapscale.x*max(invfresnel, 0.0) + envmapscale.y;
]])
]])
}
@(if (mdlopt "e") [result [
#define lightvec lightdirworld
uniform vec3 lightdirworld;
- uniform vec2 envmapscale;
varying vec3 camvec;
varying mat3 world;
]] [result [
light.rgb *= 2.0;
- @(if (mdlopt "m") [result [
- vec3 masks = texture2D(tex1, texcoord0).rgb;
- vec3 glow = light.rgb * maskscale.y;
- ]])
-
@(if (mdlopt "n") [result [
vec3 normal = texture2D(tex3, texcoord0).rgb - 0.5;
@(if (mdlopt "e") [result [
vec3 camn = normalize(camvec);
float invfresnel = dot(camn, normal);
vec3 rvec = 2.0*invfresnel*normal - camn;
- float rmod = envmapscale.x*max(invfresnel, 0.0) + envmapscale.y;
]])
vec3 reflect = textureCube(tex2, rvec).rgb;
@(if (! (mdlopt "m")) [result [
]])
]])
- @(if (mdlopt "m") [result [
- @(if (mdlopt "e") [result [
- light.rgb = mix(light.rgb, glow, masks.g); // glow mask in green channel
- gl_FragColor.rgb = mix(light.rgb, reflect, rmod*masks.b); // envmap mask in blue channel
- ]] [if (mdlopt "i") [result [
- float k = min(masks.g*masks.g*maskscale.w, 1.0); // glow mask in green channel
- gl_FragColor.rgb = @(? (mdlopt "s") "glow*k + light.rgb" "glow*k");
- ]] [result [
- gl_FragColor.rgb = mix(light.rgb, glow, masks.g); // glow mask in green channel
- ]]])
- ]])
-
@(if (|| (mdlopt "i") (mdlopt "m") (mdlopt "e")) [result [
gl_FragColor.a = light.a * color.a;
]])
loop i 4 [
variantshader 0 $shadername 0 (modelvertexshader (concatword $arg1 "b") (+ $i 1)) []
]
- glaremodeltype = (strreplace (concatword $arg1 "i") "e")
- if (< (strstr $glaremodeltype "s") 0) [glaremodeltype = (strreplace $glaremodeltype "n")]
- variantshader 0 $shadername 1 (modelvertexshader $glaremodeltype) (modelfragmentshader $glaremodeltype)
- loop i 4 [
- variantshader 0 $shadername 1 (modelvertexshader (concatword $glaremodeltype "b") (+ $i 1)) 1
- ]
if (>= (strstr $arg1 "e") 0) [
altshader $shadername (modelshader (strreplace $arg1 "e"))
]
vec2 dtc = texcoord0 + texture2D(tex0, texcoord2).xy*0.1; // use color texture as noise to distort texcoords
vec4 diffuse = texture2D(tex0, dtc);
float blend = max(pow(clamp(1.0 - dot(texcoord1, texcoord1), 0.0, 1.0), blendparams.x), blendparams.y);
- @(if (>= (strstr $arg1 "glare") 0) [result [
- float k = blend*blend;
- diffuse.rgb *= k*8.0;
- diffuse.a *= k;
- diffuse.b += k*k;
- ]] [result [
- diffuse *= blend*4.0; // dup alpha into RGB channels + intensify and over saturate
- diffuse.b += 0.5 - blend*0.5; // blue tint
- ]])
@(if (>= (strstr $arg1 "soft") 0) [result [
gl_FragColor.rgb = diffuse.rgb * color.rgb;
]
]
-looplist i ["" "glare" "soft" "soft8"] [
+looplist i ["" "soft" "soft8"] [
explosionshader [explosion@i]
]
guiradio "^f2high quality" maxdynlights 5
]
]
- guilist [
- guicheckbox "^f0soft particles^t" depthfx
- if $depthfx [
- guibar
- guiradio "^f0low quality" depthfxsize 7 [blurdepthfx 1]
- guibar
- guiradio "^f2medium quality" depthfxsize 10 [blurdepthfx 0]
- guibar
- guiradio "^f3high quality" depthfxsize 12 [blurdepthfx 0]
- ]
- ]
guilist [
guicheckbox "^f0decals^t^t" decals
if $decals [
+++ /dev/null
-Description
-
-===========
-
-Files in this folder:
-
-
-
-by "makkE"
-
-Markus Bekel
-
-e-mail: makk_e@web.de
-
-
-
-===================================================================================================
-
-These files have been licensed under a the
-
-"Creative Commons Deed / Attribution Non-commercial Share-Alike ( at-nc-sa )"
-
-===================================================================================================
-
-
-
-You are free:
-
-
-
- * to copy, distribute, display, and perform the work
-
- * to make derivative works
-
-
-
-Under the following conditions:
-
-
-
-"by"
-
- -Attribution. You must give the original author credit.
-
-"nc"
-
- -Non-Commercial. You may not use this work for commercial purposes.
-
-"sa"
-
- -Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a licence identical to this one.
-
-
-
- * For any reuse or distribution, you must make clear to others the licence terms of this work.
-
- * Any of these conditions can be waived if you get permission from the copyright holder.
-
-
-
-Your fair use and other rights are in no way affected by the above.
-
-
-
-This is a human-readable summary of the Legal Code (the full licence).
-
-
-
-=====================================================================================================
-
-
-
-See:
-
-
-
-http://creativecommons.org/licenses/by-nc-sa/2.5/deed.en_GB
-
-
-
-for the original "human readable" document.
-
-
-
-http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
-
-
-
-for the full legal code.
-
-
-
-visit creativecommons.org for general information and translations of the above documents.
-
-
-
-
-
-
-
+++ /dev/null
-mdlalphadepth 0
-
+++ /dev/null
-Description
-===========
-Files in this folder:
-
-by "makkE"
-Markus Bekel
-e-mail: makk_e@web.de
-
-===================================================================================================
-These files have been licensed under a the
-"Creative Commons Deed / Attribution Non-commercial Share-Alike ( at-nc-sa )"
-===================================================================================================
-
-You are free:
-
- * to copy, distribute, display, and perform the work
- * to make derivative works
-
-Under the following conditions:
-
-"by"
- -Attribution. You must give the original author credit.
-"nc"
- -Non-Commercial. You may not use this work for commercial purposes.
-"sa"
- -Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a licence identical to this one.
-
- * For any reuse or distribution, you must make clear to others the licence terms of this work.
- * Any of these conditions can be waived if you get permission from the copyright holder.
-
-Your fair use and other rights are in no way affected by the above.
-
-This is a human-readable summary of the Legal Code (the full licence).
-
-=====================================================================================================
-
-See:
-
-http://creativecommons.org/licenses/by-nc-sa/2.5/deed.en_GB
-
-for the original "human readable" document.
-
-http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
-
-for the full legal code.
-
-visit creativecommons.org for general information and translations of the above documents.
-
-
-
+++ /dev/null
-mdlscale 150
-mdlspec 50
-mdlalphadepth 0
-mdlcollide 0
-
--- /dev/null
+iqmload model.iqm\r
+iqmskin * "diffuse.png" "mask.png"\r
+iqmbumpmap * "normal.png"\r
+iqmalphatest Cylinder01\r
+iqmalphatest Cylinder02\r
+iqmalphatest Cylinder03\r
+iqmskin Cylinder01 "overlay_diffuse.png" "overlay_mask.png"\r
+iqmskin Cylinder02 "overlay_diffuse.png" "overlay_mask.png"\r
+iqmskin Cylinder03 "overlay_diffuse.png" "overlay_mask.png"\r
+mdlambient 40\r
+mdlspec 120\r
+mdlscale 75\r
+++ /dev/null
-md3load model.md3\r
-md3skin * "diffuse.png" "mask.png"\r
-md3bumpmap * "normal.png"\r
-md3alphatest Cylinder01\r
-md3alphatest Cylinder02\r
-md3alphatest Cylinder03\r
-md3skin Cylinder01 "overlay_diffuse.png" "overlay_mask.png"\r
-md3skin Cylinder02 "overlay_diffuse.png" "overlay_mask.png"\r
-md3skin Cylinder03 "overlay_diffuse.png" "overlay_mask.png"\r
-mdlambient 40\r
-mdlspec 120\r
-mdlscale 75\r
CXXFLAGS= -O3 -fomit-frame-pointer -ffast-math
-override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti
+override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti -Wno-unused-parameter
PLATFORM= $(shell uname -s | tr '[:lower:]' '[:upper:]')
PLATFORM_PREFIX= native
shared/zip.o \
engine/3dgui.o \
engine/bih.o \
- engine/blend.o \
engine/client.o \
engine/command.o \
engine/console.o \
engine/bih.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
engine/bih.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
engine/bih.o: engine/lightmap.h engine/bih.h engine/texture.h engine/model.h
-engine/blend.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
-engine/blend.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
-engine/blend.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
-engine/blend.o: engine/lightmap.h engine/bih.h engine/texture.h
-engine/blend.o: engine/model.h
engine/client.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
engine/client.o: shared/ents.h shared/command.h shared/glexts.h
engine/client.o: shared/glemu.h shared/iengine.h shared/igame.h
engine/renderparticles.o: shared/igame.h engine/world.h engine/octa.h
engine/renderparticles.o: engine/lightmap.h engine/bih.h engine/texture.h
engine/renderparticles.o: engine/model.h engine/rendertarget.h
-engine/renderparticles.o: engine/depthfx.h engine/explosion.h engine/lightning.h
+engine/renderparticles.o: engine/explosion.h engine/lightning.h
engine/rendertext.o: engine/engine.h shared/cube.h shared/tools.h
engine/rendertext.o: shared/geom.h shared/ents.h shared/command.h
engine/rendertext.o: shared/glexts.h shared/glemu.h shared/iengine.h
Slot &slot = *vslot.slot;
if(slot.sts.empty()) return;
VSlot *layer = NULL;
- Texture *t = NULL, *glowtex = NULL, *layertex = NULL;
+ Texture *t = NULL, *layertex = NULL;
if(slot.loaded)
{
t = slot.sts[0].t;
if(t == notexture) return;
Slot &slot = *vslot.slot;
- if(slot.texmask&(1<<TEX_GLOW)) { loopvj(slot.sts) if(slot.sts[j].type==TEX_GLOW) { glowtex = slot.sts[j].t; break; } }
if(vslot.layer)
{
layer = &lookupvslot(vslot.layer);
gle::attribf(x, y+ys); gle::attrib(tc[3]);
gle::attribf(x+xs, y+ys); gle::attrib(tc[2]);
gle::end();
- if(glowtex)
- {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glBindTexture(GL_TEXTURE_2D, glowtex->id);
- if(hit || overlaid) gle::color(vec(vslot.glowcolor).mul(color));
- else gle::color(vslot.glowcolor);
- gle::begin(GL_TRIANGLE_STRIP);
- gle::attribf(x, y); gle::attrib(tc[0]);
- gle::attribf(x+xs, y); gle::attrib(tc[1]);
- gle::attribf(x, y+ys); gle::attrib(tc[3]);
- gle::attribf(x+xs, y+ys); gle::attrib(tc[2]);
- gle::end();
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
if(layertex)
{
glBindTexture(GL_TEXTURE_2D, layertex->id);
struct shaderparams
{
- float spec, ambient, fullbright, envmapmin, envmapmax, scrollu, scrollv, alphatest;
+ float spec, ambient, fullbright, scrollu, scrollv, alphatest;
- shaderparams() : spec(1.0f), ambient(0.3f), fullbright(0), envmapmin(0), envmapmax(0), scrollu(0), scrollv(0), alphatest(0.9f) {}
+ shaderparams() : spec(1.0f), ambient(0.3f), fullbright(0), scrollu(0), scrollv(0), alphatest(0.9f) {}
};
struct shaderparamskey
struct skin : shaderparams
{
part *owner;
- Texture *tex, *masks, *envmap, *normalmap;
+ Texture *tex, *masks, *normalmap;
Shader *shader;
bool alphablend, cullface;
shaderparamskey *key;
- skin() : owner(0), tex(notexture), masks(notexture), envmap(NULL), normalmap(NULL), shader(NULL), alphablend(true), cullface(true), key(NULL) {}
+ skin() : owner(0), tex(notexture), masks(notexture), normalmap(NULL), shader(NULL), alphablend(true), cullface(true), key(NULL) {}
bool masked() const { return masks != notexture; }
- bool envmapped() { return envmapmax>0 && envmapmodels; }
bool bumpmapped() { return normalmap && bumpmodels; }
bool tangents() { return bumpmapped(); }
bool alphatested() const { return alphatest > 0 && tex->type&Texture::ALPHA; }
minshade = scale*max(ambient, mincolor);
LOCALPARAMF(lightscale, scale - minshade, scale, minshade + bias);
}
- float curglow = glow;
- if(glowpulse > 0)
- {
- float curpulse = lastmillis*glowpulse;
- curpulse -= floor(curpulse);
- curglow += glowdelta*2*fabs(curpulse - 0.5f);
- }
LOCALPARAMF(texscroll, scrollu*lastmillis/1000.0f, scrollv*lastmillis/1000.0f);
- if(envmapped()) LOCALPARAMF(envmapscale, envmapmin-envmapmax, envmapmax);
}
Shader *loadshader()
if(alphatested()) opts[optslen++] = 'a';
if(owner->tangents()) opts[optslen++] = 'q';
if(bumpmapped()) opts[optslen++] = 'n';
- if(envmapped()) opts[optslen++] = 'e';
if(masked()) opts[optslen++] = 'm';
if(!fullbright && (masked() || spec>=0.01f)) opts[optslen++] = 's';
opts[optslen++] = '\0';
glBindTexture(GL_TEXTURE_2D, masks->id);
lastmasks = masks;
}
- if(envmapped())
- {
- GLuint emtex = envmap ? envmap->id : closestenvmaptex;
- if(lastenvmaptex!=emtex)
- {
- glActiveTexture_(GL_TEXTURE2);
- activetmu = 2;
- glBindTexture(GL_TEXTURE_CUBE_MAP, emtex);
- lastenvmaptex = emtex;
- }
- }
if(activetmu != 0) glActiveTexture_(GL_TEXTURE0);
}
};
virtual void setshader(Shader *s)
{
- if(glaring) s->setvariant(0, 1);
- else s->set();
+ s->set();
}
template<class V, class T> void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight)
}
}
- bool envmapped()
- {
- loopv(skins) if(skins[i].envmapped()) return true;
- return false;
- }
-
bool tangents()
{
loopv(skins) if(skins[i].tangents()) return true;
if(!(anim&ANIM_NOSKIN))
{
- if(envmapped()) GLOBALPARAM(modelworld, matrix3(matrixstack[matrixpos]));
-
vec odir, ocampos;
matrixstack[matrixpos].transposedtransformnormal(lightdir, odir);
GLOBALPARAM(lightdir, odir);
transparent = trans;
lightdir = dir;
lightcolor = color;
-
- if(envmapped())
- {
- setupenvmap:
- closestenvmaptex = lookupenvmap(closestenvmap(o));
- GLOBALPARAM(lightdirworld, dir);
- }
- else if(a) for(int i = 0; a[i].tag; i++) if(a[i].m && a[i].m->envmapped()) goto setupenvmap;
}
if(depthoffset && !enabledepthoffset)
{
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
render(anim|ANIM_NOSKIN, basetime, basetime2, pitch, axis, forward, d, a);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, fading ? GL_FALSE : GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthFunc(GL_LEQUAL);
}
return parts[0]->unlink(p);
}
- bool envmapped()
- {
- loopv(parts) if(parts[i]->envmapped()) return true;
- return false;
- }
-
virtual bool flipy() const { return false; }
virtual bool loadconfig() { return false; }
virtual bool loaddefaultparts() { return false; }
loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].shader = shader;
}
- void setenvmap(float envmapmin, float envmapmax, Texture *envmap)
- {
- if(parts.empty()) loaddefaultparts();
- loopv(parts) loopvj(parts[i]->skins)
- {
- skin &s = parts[i]->skins[j];
- if(envmapmax)
- {
- s.envmapmin = envmapmin;
- s.envmapmax = envmapmax;
- }
- if(envmap) s.envmap = envmap;
- }
- }
-
void setspec(float spec)
{
if(parts.empty()) loaddefaultparts();
static bool enabletc, enablealphablend, enablecullface, enablenormals, enabletangents, enablebones, enabledepthoffset;
static vec lightdir, lightcolor;
static float transparent, lastalphatest;
- static GLuint lastvbuf, lasttcbuf, lastnbuf, lastxbuf, lastbbuf, lastebuf, lastenvmaptex, closestenvmaptex;
+ static GLuint lastvbuf, lasttcbuf, lastnbuf, lastxbuf, lastbbuf, lastebuf;
static Texture *lasttex, *lastmasks, *lastnormalmap;
static int matrixpos;
static matrix4 matrixstack[64];
enabletc = enablealphablend = enablenormals = enabletangents = enablebones = enabledepthoffset = false;
enablecullface = true;
lastalphatest = -1;
- lastvbuf = lasttcbuf = lastxbuf = lastnbuf = lastbbuf = lastebuf = lastenvmaptex = closestenvmaptex = 0;
+ lastvbuf = lasttcbuf = lastxbuf = lastnbuf = lastbbuf = lastebuf = 0;
lasttex = lastmasks = lastnormalmap = NULL;
transparent = 1;
shaderparamskey::invalidate();
vec animmodel::lightdir(0, 0, 1), animmodel::lightcolor(1, 1, 1);
float animmodel::transparent = 1, animmodel::lastalphatest = -1;
GLuint animmodel::lastvbuf = 0, animmodel::lasttcbuf = 0, animmodel::lastnbuf = 0, animmodel::lastxbuf = 0, animmodel::lastbbuf = 0,
- animmodel::lastebuf = 0, animmodel::lastenvmaptex = 0, animmodel::closestenvmaptex = 0;
+ animmodel::lastebuf = 0;
Texture *animmodel::lasttex = NULL, *animmodel::lastmasks = NULL, *animmodel::lastnormalmap = NULL;
int animmodel::matrixpos = 0;
matrix4 animmodel::matrixstack[64];
#define loopskins(meshname, s, body) loopmeshes(meshname, m, { skin &s = mdl.skins[i]; body; })
static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin)
- {
+ {(void)envmapmax;(void)envmapmin;
loopskins(meshname, s,
s.tex = textureload(makerelpath(MDL::dir, tex), 0, true, false);
if(*masks)
{
s.masks = textureload(makerelpath(MDL::dir, masks), 0, true, false);
- s.envmapmax = *envmapmax;
- s.envmapmin = *envmapmin;
}
);
}
+++ /dev/null
-#include "engine.h"
-
-enum
-{
- BM_BRANCH = 0,
- BM_SOLID,
- BM_IMAGE
-};
-
-struct BlendMapBranch;
-struct BlendMapSolid;
-struct BlendMapImage;
-
-struct BlendMapNode
-{
- union
- {
- BlendMapBranch *branch;
- BlendMapSolid *solid;
- BlendMapImage *image;
- };
-
- void cleanup(int type);
- void splitsolid(uchar &type, uchar val);
-};
-
-struct BlendMapBranch
-{
- uchar type[4];
- BlendMapNode children[4];
-
- ~BlendMapBranch()
- {
- loopi(4) children[i].cleanup(type[i]);
- }
-
- uchar shrink(BlendMapNode &child, int quadrant);
-};
-
-struct BlendMapSolid
-{
- uchar val;
-
- BlendMapSolid(uchar val) : val(val) {}
-};
-
-#define BM_SCALE 1
-#define BM_IMAGE_SIZE 64
-
-struct BlendMapImage
-{
- uchar data[BM_IMAGE_SIZE*BM_IMAGE_SIZE];
-};
-
-void BlendMapNode::cleanup(int type)
-{
- switch(type)
- {
- case BM_BRANCH: delete branch; break;
- case BM_IMAGE: delete image; break;
- }
-}
-
-#define DEFBMSOLIDS(n) n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, n+8, n+9, n+10, n+11, n+12, n+13, n+14, n+15
-
-static BlendMapSolid bmsolids[256] =
-{
- DEFBMSOLIDS(0x00), DEFBMSOLIDS(0x10), DEFBMSOLIDS(0x20), DEFBMSOLIDS(0x30),
- DEFBMSOLIDS(0x40), DEFBMSOLIDS(0x50), DEFBMSOLIDS(0x60), DEFBMSOLIDS(0x70),
- DEFBMSOLIDS(0x80), DEFBMSOLIDS(0x90), DEFBMSOLIDS(0xA0), DEFBMSOLIDS(0xB0),
- DEFBMSOLIDS(0xC0), DEFBMSOLIDS(0xD0), DEFBMSOLIDS(0xE0), DEFBMSOLIDS(0xF0),
-};
-
-void BlendMapNode::splitsolid(uchar &type, uchar val)
-{
- cleanup(type);
- type = BM_BRANCH;
- branch = new BlendMapBranch;
- loopi(4)
- {
- branch->type[i] = BM_SOLID;
- branch->children[i].solid = &bmsolids[val];
- }
-}
-
-uchar BlendMapBranch::shrink(BlendMapNode &child, int quadrant)
-{
- uchar childtype = type[quadrant];
- child = children[quadrant];
- type[quadrant] = BM_SOLID;
- children[quadrant].solid = &bmsolids[0];
- return childtype;
-}
-
-struct BlendMapRoot : BlendMapNode
-{
- uchar type;
-
- BlendMapRoot() : type(BM_SOLID) { solid = &bmsolids[0xFF]; }
- BlendMapRoot(uchar type, const BlendMapNode &node) : BlendMapNode(node), type(type) {}
-
- void cleanup() { BlendMapNode::cleanup(type); }
-
- void shrink(int quadrant)
- {
- if(type == BM_BRANCH)
- {
- BlendMapRoot oldroot = *this;
- type = branch->shrink(*this, quadrant);
- oldroot.cleanup();
- }
- }
-};
-
-static BlendMapRoot blendmap;
-
-struct BlendMapCache
-{
- BlendMapRoot node;
- int scale;
- ivec2 origin;
-};
-
-BlendMapCache *newblendmapcache() { return new BlendMapCache; }
-
-void freeblendmapcache(BlendMapCache *&cache) { delete cache; cache = NULL; }
-
-bool setblendmaporigin(BlendMapCache *cache, const ivec &o, int size)
-{
- if(blendmap.type!=BM_BRANCH)
- {
- cache->node = blendmap;
- cache->scale = worldscale-BM_SCALE;
- cache->origin = ivec2(0, 0);
- return cache->node.solid!=&bmsolids[0xFF];
- }
-
- BlendMapBranch *bm = blendmap.branch;
- int bmscale = worldscale-BM_SCALE, bmsize = 1<<bmscale,
- x = o.x>>BM_SCALE, y = o.y>>BM_SCALE,
- x1 = max(x-1, 0), y1 = max(y-1, 0),
- x2 = min(((o.x + size + (1<<BM_SCALE)-1)>>BM_SCALE) + 1, bmsize),
- y2 = min(((o.y + size + (1<<BM_SCALE)-1)>>BM_SCALE) + 1, bmsize),
- diff = (x1^x2)|(y1^y2);
- if(diff < bmsize) while(!(diff&(1<<(bmscale-1))))
- {
- bmscale--;
- int n = (((y1>>bmscale)&1)<<1) | ((x1>>bmscale)&1);
- if(bm->type[n]!=BM_BRANCH)
- {
- cache->node = BlendMapRoot(bm->type[n], bm->children[n]);
- cache->scale = bmscale;
- cache->origin = ivec2(x1&(~0U<<bmscale), y1&(~0U<<bmscale));
- return cache->node.solid!=&bmsolids[0xFF];
- }
- bm = bm->children[n].branch;
- }
-
- cache->node.type = BM_BRANCH;
- cache->node.branch = bm;
- cache->scale = bmscale;
- cache->origin = ivec2(x1&(~0U<<bmscale), y1&(~0U<<bmscale));
- return true;
-}
-
-bool hasblendmap(BlendMapCache *cache)
-{
- return cache->node.solid!=&bmsolids[0xFF];
-}
-
-static uchar lookupblendmap(int x, int y, BlendMapBranch *bm, int bmscale)
-{
- for(;;)
- {
- bmscale--;
- int n = (((y>>bmscale)&1)<<1) | ((x>>bmscale)&1);
- switch(bm->type[n])
- {
- case BM_SOLID: return bm->children[n].solid->val;
- case BM_IMAGE: return bm->children[n].image->data[(y&((1<<bmscale)-1))*BM_IMAGE_SIZE + (x&((1<<bmscale)-1))];
- }
- bm = bm->children[n].branch;
- }
-}
-
-uchar lookupblendmap(BlendMapCache *cache, const vec &pos)
-{
- if(cache->node.type==BM_SOLID) return cache->node.solid->val;
-
- uchar vals[4], *val = vals;
- float bx = pos.x/(1<<BM_SCALE) - 0.5f, by = pos.y/(1<<BM_SCALE) - 0.5f;
- int ix = (int)floor(bx), iy = (int)floor(by),
- rx = ix-cache->origin.x, ry = iy-cache->origin.y;
- loop(vy, 2) loop(vx, 2)
- {
- int cx = clamp(rx+vx, 0, (1<<cache->scale)-1), cy = clamp(ry+vy, 0, (1<<cache->scale)-1);
- if(cache->node.type==BM_IMAGE)
- *val++ = cache->node.image->data[cy*BM_IMAGE_SIZE + cx];
- else *val++ = lookupblendmap(cx, cy, cache->node.branch, cache->scale);
- }
- float fx = bx - ix, fy = by - iy;
- return uchar((1-fy)*((1-fx)*vals[0] + fx*vals[1]) +
- fy*((1-fx)*vals[2] + fx*vals[3]));
-}
-
-static void fillblendmap(uchar &type, BlendMapNode &node, int size, uchar val, int x1, int y1, int x2, int y2)
-{
- if(max(x1, y1) <= 0 && min(x2, y2) >= size)
- {
- node.cleanup(type);
- type = BM_SOLID;
- node.solid = &bmsolids[val];
- return;
- }
-
- if(type==BM_BRANCH)
- {
- size /= 2;
- if(y1 < size)
- {
- if(x1 < size) fillblendmap(node.branch->type[0], node.branch->children[0], size, val,
- x1, y1, min(x2, size), min(y2, size));
- if(x2 > size) fillblendmap(node.branch->type[1], node.branch->children[1], size, val,
- max(x1-size, 0), y1, x2-size, min(y2, size));
- }
- if(y2 > size)
- {
- if(x1 < size) fillblendmap(node.branch->type[2], node.branch->children[2], size, val,
- x1, max(y1-size, 0), min(x2, size), y2-size);
- if(x2 > size) fillblendmap(node.branch->type[3], node.branch->children[3], size, val,
- max(x1-size, 0), max(y1-size, 0), x2-size, y2-size);
- }
- loopi(4) if(node.branch->type[i]!=BM_SOLID || node.branch->children[i].solid->val!=val) return;
- node.cleanup(type);
- type = BM_SOLID;
- node.solid = &bmsolids[val];
- return;
- }
- else if(type==BM_SOLID)
- {
- uchar oldval = node.solid->val;
- if(oldval==val) return;
-
- if(size > BM_IMAGE_SIZE)
- {
- node.splitsolid(type, oldval);
- fillblendmap(type, node, size, val, x1, y1, x2, y2);
- return;
- }
-
- type = BM_IMAGE;
- node.image = new BlendMapImage;
- memset(node.image->data, oldval, sizeof(node.image->data));
- }
-
- uchar *dst = &node.image->data[y1*BM_IMAGE_SIZE + x1];
- loopi(y2-y1)
- {
- memset(dst, val, x2-x1);
- dst += BM_IMAGE_SIZE;
- }
-}
-
-void fillblendmap(int x, int y, int w, int h, uchar val)
-{
- int bmsize = worldsize>>BM_SCALE,
- x1 = clamp(x, 0, bmsize),
- y1 = clamp(y, 0, bmsize),
- x2 = clamp(x+w, 0, bmsize),
- y2 = clamp(y+h, 0, bmsize);
- if(max(x1, y1) >= bmsize || min(x2, y2) <= 0 || x1>=x2 || y1>=y2) return;
- fillblendmap(blendmap.type, blendmap, bmsize, val, x1, y1, x2, y2);
-}
-
-static void invertblendmap(uchar &type, BlendMapNode &node, int size, int x1, int y1, int x2, int y2)
-{
- if(type==BM_BRANCH)
- {
- size /= 2;
- if(y1 < size)
- {
- if(x1 < size) invertblendmap(node.branch->type[0], node.branch->children[0], size,
- x1, y1, min(x2, size), min(y2, size));
- if(x2 > size) invertblendmap(node.branch->type[1], node.branch->children[1], size,
- max(x1-size, 0), y1, x2-size, min(y2, size));
- }
- if(y2 > size)
- {
- if(x1 < size) invertblendmap(node.branch->type[2], node.branch->children[2], size,
- x1, max(y1-size, 0), min(x2, size), y2-size);
- if(x2 > size) invertblendmap(node.branch->type[3], node.branch->children[3], size,
- max(x1-size, 0), max(y1-size, 0), x2-size, y2-size);
- }
- return;
- }
- else if(type==BM_SOLID)
- {
- fillblendmap(type, node, size, 255-node.solid->val, x1, y1, x2, y2);
- }
- else if(type==BM_IMAGE)
- {
- uchar *dst = &node.image->data[y1*BM_IMAGE_SIZE + x1];
- loopi(y2-y1)
- {
- loopj(x2-x1) dst[j] = 255-dst[j];
- dst += BM_IMAGE_SIZE;
- }
- }
-}
-
-void invertblendmap(int x, int y, int w, int h)
-{
- int bmsize = worldsize>>BM_SCALE,
- x1 = clamp(x, 0, bmsize),
- y1 = clamp(y, 0, bmsize),
- x2 = clamp(x+w, 0, bmsize),
- y2 = clamp(y+h, 0, bmsize);
- if(max(x1, y1) >= bmsize || min(x2, y2) <= 0 || x1>=x2 || y1>=y2) return;
- invertblendmap(blendmap.type, blendmap, bmsize, x1, y1, x2, y2);
-}
-
-static void optimizeblendmap(uchar &type, BlendMapNode &node)
-{
- switch(type)
- {
- case BM_IMAGE:
- {
- uint val = node.image->data[0];
- val |= val<<8;
- val |= val<<16;
- for(uint *data = (uint *)node.image->data, *end = &data[sizeof(node.image->data)/sizeof(uint)]; data < end; data++)
- if(*data != val) return;
- node.cleanup(type);
- type = BM_SOLID;
- node.solid = &bmsolids[val&0xFF];
- break;
- }
- case BM_BRANCH:
- {
- loopi(4) optimizeblendmap(node.branch->type[i], node.branch->children[i]);
- if(node.branch->type[3]!=BM_SOLID) return;
- uint val = node.branch->children[3].solid->val;
- loopi(3) if(node.branch->type[i]!=BM_SOLID || node.branch->children[i].solid->val != val) return;
- node.cleanup(type);
- type = BM_SOLID;
- node.solid = &bmsolids[val];
- break;
- }
- }
-}
-
-void optimizeblendmap()
-{
- optimizeblendmap(blendmap.type, blendmap);
-}
-
-VARF(blendpaintmode, 0, 0, 5,
-{
- if(!blendpaintmode) stoppaintblendmap();
-});
-
-static void blitblendmap(uchar &type, BlendMapNode &node, int bmx, int bmy, int bmsize, uchar *src, int sx, int sy, int sw, int sh, int smode)
-{
- if(type==BM_BRANCH)
- {
- bmsize /= 2;
- if(sy < bmy + bmsize)
- {
- if(sx < bmx + bmsize) blitblendmap(node.branch->type[0], node.branch->children[0], bmx, bmy, bmsize, src, sx, sy, sw, sh, smode);
- if(sx + sw > bmx + bmsize) blitblendmap(node.branch->type[1], node.branch->children[1], bmx+bmsize, bmy, bmsize, src, sx, sy, sw, sh, smode);
- }
- if(sy + sh > bmy + bmsize)
- {
- if(sx < bmx + bmsize) blitblendmap(node.branch->type[2], node.branch->children[2], bmx, bmy+bmsize, bmsize, src, sx, sy, sw, sh, smode);
- if(sx + sw > bmx + bmsize) blitblendmap(node.branch->type[3], node.branch->children[3], bmx+bmsize, bmy+bmsize, bmsize, src, sx, sy, sw, sh, smode);
- }
- return;
- }
- if(type==BM_SOLID)
- {
- uchar val = node.solid->val;
- if(bmsize > BM_IMAGE_SIZE)
- {
- node.splitsolid(type, val);
- blitblendmap(type, node, bmx, bmy, bmsize, src, sx, sy, sw, sh, smode);
- return;
- }
-
- type = BM_IMAGE;
- node.image = new BlendMapImage;
- memset(node.image->data, val, sizeof(node.image->data));
- }
-
- int x1 = clamp(sx - bmx, 0, bmsize), y1 = clamp(sy - bmy, 0, bmsize),
- x2 = clamp(sx+sw - bmx, 0, bmsize), y2 = clamp(sy+sh - bmy, 0, bmsize);
- uchar *dst = &node.image->data[y1*BM_IMAGE_SIZE + x1];
- src += max(bmy - sy, 0)*sw + max(bmx - sx, 0);
- loopi(y2-y1)
- {
- switch(smode)
- {
- case 1:
- memcpy(dst, src, x2 - x1);
- break;
-
- case 2:
- loopi(x2 - x1) dst[i] = min(dst[i], src[i]);
- break;
-
- case 3:
- loopi(x2 - x1) dst[i] = max(dst[i], src[i]);
- break;
-
- case 4:
- loopi(x2 - x1) dst[i] = min(dst[i], uchar(0xFF - src[i]));
- break;
-
- case 5:
- loopi(x2 - x1) dst[i] = max(dst[i], uchar(0xFF - src[i]));
- break;
- }
- dst += BM_IMAGE_SIZE;
- src += sw;
- }
-}
-
-void blitblendmap(uchar *src, int sx, int sy, int sw, int sh, int smode)
-{
- int bmsize = worldsize>>BM_SCALE;
- if(max(sx, sy) >= bmsize || min(sx+sw, sy+sh) <= 0 || min(sw, sh) <= 0) return;
- blitblendmap(blendmap.type, blendmap, 0, 0, bmsize, src, sx, sy, sw, sh, smode);
-}
-
-void resetblendmap()
-{
- blendmap.cleanup();
- blendmap.type = BM_SOLID;
- blendmap.solid = &bmsolids[0xFF];
-}
-
-void enlargeblendmap()
-{
- if(blendmap.type == BM_SOLID) return;
- BlendMapBranch *branch = new BlendMapBranch;
- branch->type[0] = blendmap.type;
- branch->children[0] = blendmap;
- loopi(3)
- {
- branch->type[i+1] = BM_SOLID;
- branch->children[i+1].solid = &bmsolids[0xFF];
- }
- blendmap.type = BM_BRANCH;
- blendmap.branch = branch;
-}
-
-void shrinkblendmap(int octant)
-{
- blendmap.shrink(octant&3);
-}
-
-void moveblendmap(uchar type, BlendMapNode &node, int size, int x, int y, int dx, int dy)
-{
- if(type == BM_BRANCH)
- {
- size /= 2;
- moveblendmap(node.branch->type[0], node.branch->children[0], size, x, y, dx, dy);
- moveblendmap(node.branch->type[1], node.branch->children[1], size, x + size, y, dx, dy);
- moveblendmap(node.branch->type[2], node.branch->children[2], size, x, y + size, dx, dy);
- moveblendmap(node.branch->type[3], node.branch->children[3], size, x + size, y + size, dx, dy);
- return;
- }
- else if(type == BM_SOLID)
- {
- fillblendmap(x+dx, y+dy, size, size, node.solid->val);
- }
- else if(type == BM_IMAGE)
- {
- blitblendmap(node.image->data, x+dx, y+dy, size, size, 1);
- }
-}
-
-void moveblendmap(int dx, int dy)
-{
- BlendMapRoot old = blendmap;
- blendmap.type = BM_SOLID;
- blendmap.solid = &bmsolids[0xFF];
- moveblendmap(old.type, old, worldsize>>BM_SCALE, 0, 0, dx, dy);
- old.cleanup();
-}
-
-struct BlendBrush
-{
- char *name;
- int w, h;
- uchar *data;
- GLuint tex;
-
- BlendBrush(const char *name, int w, int h) :
- name(newstring(name)), w(w), h(h), data(new uchar[w*h]), tex(0)
- {}
-
- ~BlendBrush()
- {
- cleanup();
- delete[] name;
- if(data) delete[] data;
- }
-
- void cleanup()
- {
- if(tex) { glDeleteTextures(1, &tex); tex = 0; }
- }
-
- void gentex()
- {
- if(!tex) glGenTextures(1, &tex);
- uchar *buf = new uchar[2*w*h];
- uchar *dst = buf, *src = data;
- loopi(h)
- {
- loopj(w) *dst++ = 255 - *src++;
- }
- createtexture(tex, w, h, buf, 3, 1, hasTRG ? GL_R8 : GL_LUMINANCE8);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- GLfloat border[4] = { 0, 0, 0, 0 };
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
- delete[] buf;
- }
-
- void reorient(bool flipx, bool flipy, bool swapxy)
- {
- uchar *rdata = new uchar[w*h];
- int stridex = 1, stridey = 1;
- if(swapxy) stridex *= h; else stridey *= w;
- uchar *src = data, *dst = rdata;
- if(flipx) { dst += (w-1)*stridex; stridex = -stridex; }
- if(flipy) { dst += (h-1)*stridey; stridey = -stridey; }
- loopi(h)
- {
- uchar *curdst = dst;
- loopj(w)
- {
- *curdst = *src++;
- curdst += stridex;
- }
- dst += stridey;
- }
- if(swapxy) swap(w, h);
- delete[] data;
- data = rdata;
- if(tex) gentex();
- }
-};
-
-static vector<BlendBrush *> brushes;
-static int curbrush = -1;
-
-void cleanupblendmap()
-{
- loopv(brushes) brushes[i]->cleanup();
-}
-
-void clearblendbrushes()
-{
- while(brushes.length()) delete brushes.pop();
- curbrush = -1;
-}
-
-void delblendbrush(const char *name)
-{
- loopv(brushes) if(!strcmp(brushes[i]->name, name))
- {
- delete brushes[i];
- brushes.remove(i--);
- }
- curbrush = brushes.empty() ? -1 : clamp(curbrush, 0, brushes.length()-1);
-}
-
-void addblendbrush(const char *name, const char *imgname)
-{
- delblendbrush(name);
-
- ImageData s;
- if(!loadimage(imgname, s)) { conoutf(CON_ERROR, "could not load blend brush image %s", imgname); return; }
- if(max(s.w, s.h) > (1<<12))
- {
- conoutf(CON_ERROR, "blend brush image size exceeded %dx%d pixels: %s", 1<<12, 1<<12, imgname);
- return;
- }
-
- BlendBrush *brush = new BlendBrush(name, s.w, s.h);
-
- uchar *dst = brush->data, *srcrow = s.data;
- loopi(s.h)
- {
- for(uchar *src = srcrow, *end = &srcrow[s.w*s.bpp]; src < end; src += s.bpp)
- *dst++ = src[0];
- srcrow += s.pitch;
- }
-
- brushes.add(brush);
- if(curbrush < 0) curbrush = 0;
- else if(curbrush >= brushes.length()) curbrush = brushes.length()-1;
-
-}
-
-void nextblendbrush(int *dir)
-{
- curbrush += *dir < 0 ? -1 : 1;
- if(brushes.empty()) curbrush = -1;
- else if(!brushes.inrange(curbrush)) curbrush = *dir < 0 ? brushes.length()-1 : 0;
-}
-
-void setblendbrush(const char *name)
-{
- loopv(brushes) if(!strcmp(brushes[i]->name, name)) { curbrush = i; break; }
-}
-
-void getblendbrushname(int *n)
-{
- result(brushes.inrange(*n) ? brushes[*n]->name : "");
-}
-
-void curblendbrush()
-{
- intret(curbrush);
-}
-
-COMMAND(clearblendbrushes, "");
-COMMAND(delblendbrush, "s");
-COMMAND(addblendbrush, "ss");
-COMMAND(nextblendbrush, "i");
-COMMAND(setblendbrush, "s");
-COMMAND(getblendbrushname, "i");
-COMMAND(curblendbrush, "");
-
-extern int nompedit;
-
-bool canpaintblendmap(bool brush = true, bool sel = false, bool msg = true)
-{
- if(noedit(!sel, msg) || (nompedit && multiplayer())) return false;
- if(!blendpaintmode)
- {
- if(msg) conoutf(CON_ERROR, "operation only allowed in blend paint mode");
- return false;
- }
- if(brush && !brushes.inrange(curbrush))
- {
- if(msg) conoutf(CON_ERROR, "no blend brush selected");
- return false;
- }
- return true;
-}
-
-void rotateblendbrush(int *val)
-{
- if(!canpaintblendmap()) return;
- BlendBrush *brush = brushes[curbrush];
- const texrotation &r = texrotations[*val < 0 ? 3 : clamp(*val, 1, 7)];
- brush->reorient(r.flipx, r.flipy, r.swapxy);
-}
-
-COMMAND(rotateblendbrush, "i");
-
-void paintblendmap(bool msg)
-{
- if(!canpaintblendmap(true, false, msg)) return;
-
- BlendBrush *brush = brushes[curbrush];
- int x = (int)floor(clamp(worldpos.x, 0.0f, float(worldsize))/(1<<BM_SCALE) - 0.5f*brush->w),
- y = (int)floor(clamp(worldpos.y, 0.0f, float(worldsize))/(1<<BM_SCALE) - 0.5f*brush->h);
- blitblendmap(brush->data, x, y, brush->w, brush->h, blendpaintmode);
- previewblends(ivec((x-1)<<BM_SCALE, (y-1)<<BM_SCALE, 0),
- ivec((x+brush->w+1)<<BM_SCALE, (y+brush->h+1)<<BM_SCALE, worldsize));
-}
-
-VAR(paintblendmapdelay, 1, 500, 3000);
-VAR(paintblendmapinterval, 1, 30, 3000);
-
-int paintingblendmap = 0, lastpaintblendmap = 0;
-
-void stoppaintblendmap()
-{
- paintingblendmap = 0;
- lastpaintblendmap = 0;
-}
-
-void trypaintblendmap()
-{
- if(!paintingblendmap || totalmillis - paintingblendmap < paintblendmapdelay) return;
- if(lastpaintblendmap)
- {
- int diff = totalmillis - lastpaintblendmap;
- if(diff < paintblendmapinterval) return;
- lastpaintblendmap = (diff - diff%paintblendmapinterval) + lastpaintblendmap;
- }
- else lastpaintblendmap = totalmillis;
- paintblendmap(false);
-}
-
-ICOMMAND(paintblendmap, "D", (int *isdown),
-{
- if(*isdown)
- {
- if(!paintingblendmap) { paintblendmap(true); paintingblendmap = totalmillis; }
- }
- else stoppaintblendmap();
-});
-
-void clearblendmapsel()
-{
- if(noedit(false) || (nompedit && multiplayer())) return;
- extern selinfo sel;
- int x1 = sel.o.x>>BM_SCALE, y1 = sel.o.y>>BM_SCALE,
- x2 = (sel.o.x+sel.s.x*sel.grid+(1<<BM_SCALE)-1)>>BM_SCALE,
- y2 = (sel.o.y+sel.s.y*sel.grid+(1<<BM_SCALE)-1)>>BM_SCALE;
- fillblendmap(x1, y1, x2-x1, y2-y1, 0xFF);
- previewblends(ivec(x1<<BM_SCALE, y1<<BM_SCALE, 0),
- ivec(x2<<BM_SCALE, y2<<BM_SCALE, worldsize));
-}
-
-COMMAND(clearblendmapsel, "");
-
-void invertblendmapsel()
-{
- if(noedit(false) || (nompedit && multiplayer())) return;
- extern selinfo sel;
- int x1 = sel.o.x>>BM_SCALE, y1 = sel.o.y>>BM_SCALE,
- x2 = (sel.o.x+sel.s.x*sel.grid+(1<<BM_SCALE)-1)>>BM_SCALE,
- y2 = (sel.o.y+sel.s.y*sel.grid+(1<<BM_SCALE)-1)>>BM_SCALE;
- invertblendmap(x1, y1, x2-x1, y2-y1);
- previewblends(ivec(x1<<BM_SCALE, y1<<BM_SCALE, 0),
- ivec(x2<<BM_SCALE, y2<<BM_SCALE, worldsize));
-}
-
-COMMAND(invertblendmapsel, "");
-
-void invertblendmap()
-{
- if(noedit(false) || (nompedit && multiplayer())) return;
- invertblendmap(0, 0, worldsize>>BM_SCALE, worldsize>>BM_SCALE);
- previewblends(ivec(0, 0, 0), ivec(worldsize, worldsize, worldsize));
-}
-
-COMMAND(invertblendmap, "");
-
-void showblendmap()
-{
- if(noedit(true) || (nompedit && multiplayer())) return;
- previewblends(ivec(0, 0, 0), ivec(worldsize, worldsize, worldsize));
-}
-
-COMMAND(showblendmap, "");
-COMMAND(optimizeblendmap, "");
-ICOMMAND(clearblendmap, "", (),
-{
- if(noedit(true) || (nompedit && multiplayer())) return;
- resetblendmap();
- showblendmap();
-});
-
-ICOMMAND(moveblendmap, "ii", (int *dx, int *dy),
-{
- if(noedit(true) || (nompedit && multiplayer())) return;
- if(*dx%(BM_IMAGE_SIZE<<BM_SCALE) || *dy%(BM_IMAGE_SIZE<<BM_SCALE))
- {
- conoutf(CON_ERROR, "blendmap movement must be in multiples of %d", BM_IMAGE_SIZE<<BM_SCALE);
- return;
- }
- if(*dx <= -worldsize || *dx >= worldsize || *dy <= -worldsize || *dy >= worldsize)
- resetblendmap();
- else
- moveblendmap(*dx>>BM_SCALE, *dy>>BM_SCALE);
- showblendmap();
-});
-
-void renderblendbrush()
-{
- if(!blendpaintmode || !brushes.inrange(curbrush)) return;
-
- BlendBrush *brush = brushes[curbrush];
- int x1 = (int)floor(clamp(worldpos.x, 0.0f, float(worldsize))/(1<<BM_SCALE) - 0.5f*brush->w) << BM_SCALE,
- y1 = (int)floor(clamp(worldpos.y, 0.0f, float(worldsize))/(1<<BM_SCALE) - 0.5f*brush->h) << BM_SCALE,
- x2 = x1 + (brush->w << BM_SCALE),
- y2 = y1 + (brush->h << BM_SCALE);
-
- if(max(x1, y1) >= worldsize || min(x2, y2) <= 0 || x1>=x2 || y1>=y2) return;
-
- if(!brush->tex) brush->gentex();
- renderblendbrush(brush->tex, x1, y1, x2 - x1, y2 - y1);
-}
-
-bool loadblendmap(stream *f, uchar &type, BlendMapNode &node)
-{
- type = f->getchar();
- switch(type)
- {
- case BM_SOLID:
- {
- int val = f->getchar();
- if(val<0 || val>0xFF) return false;
- node.solid = &bmsolids[val];
- break;
- }
-
- case BM_IMAGE:
- node.image = new BlendMapImage;
- if(f->read(node.image->data, sizeof(node.image->data)) != sizeof(node.image->data))
- return false;
- break;
-
- case BM_BRANCH:
- node.branch = new BlendMapBranch;
- loopi(4) { node.branch->type[i] = BM_SOLID; node.branch->children[i].solid = &bmsolids[0xFF]; }
- loopi(4) if(!loadblendmap(f, node.branch->type[i], node.branch->children[i]))
- return false;
- break;
-
- default:
- type = BM_SOLID;
- node.solid = &bmsolids[0xFF];
- return false;
- }
- return true;
-}
-
-bool loadblendmap(stream *f, int info)
-{
- resetblendmap();
- return loadblendmap(f, blendmap.type, blendmap);
-}
-
-void saveblendmap(stream *f, uchar type, BlendMapNode &node)
-{
- f->putchar(type);
- switch(type)
- {
- case BM_SOLID:
- f->putchar(node.solid->val);
- break;
-
- case BM_IMAGE:
- f->write(node.image->data, sizeof(node.image->data));
- break;
-
- case BM_BRANCH:
- loopi(4) saveblendmap(f, node.branch->type[i], node.branch->children[i]);
- break;
- }
-}
-
-void saveblendmap(stream *f)
-{
- saveblendmap(f, blendmap.type, blendmap);
-}
-
-uchar shouldsaveblendmap()
-{
- return blendmap.solid!=&bmsolids[0xFF] ? 1 : 0;
-}
-
+++ /dev/null
-// eye space depth texture for soft particles, done at low res then blurred to prevent ugly jaggies
-VARP(depthfxfpscale, 1, 1<<12, 1<<16);
-VARP(depthfxscale, 1, 1<<6, 1<<8);
-VARP(depthfxblend, 1, 16, 64);
-VARP(depthfxpartblend, 1, 8, 64);
-VAR(depthfxmargin, 0, 16, 64);
-VAR(depthfxbias, 0, 1, 64);
-
-extern void cleanupdepthfx();
-VARFP(fpdepthfx, 0, 0, 1, cleanupdepthfx());
-VARP(depthfxemuprecision, 0, 1, 1);
-VARFP(depthfxsize, 6, 7, 12, cleanupdepthfx());
-VARP(depthfx, 0, 1, 1);
-VARP(depthfxparts, 0, 1, 1);
-VARP(blurdepthfx, 0, 1, 7);
-VARP(blurdepthfxsigma, 1, 50, 200);
-VAR(depthfxscissor, 0, 2, 2);
-
-#define MAXDFXRANGES 4
-
-void *depthfxowners[MAXDFXRANGES];
-float depthfxranges[MAXDFXRANGES];
-int numdepthfxranges = 0;
-vec depthfxmin(1e16f, 1e16f, 1e16f), depthfxmax(1e16f, 1e16f, 1e16f);
-
-static struct depthfxtexture : rendertarget
-{
- const GLenum *colorformats() const
- {
- static const GLenum colorfmts[] = { GL_RG16F, GL_RGB16F, GL_RGBA, GL_RGBA8, GL_RGB, GL_RGB8, GL_FALSE };
- return &colorfmts[fpdepthfx && hasTF ? (hasTRG ? 0 : 1) : 2];
- }
-
- float eyedepth(const vec &p) const
- {
- return max(-cammatrix.transform<vec>(p).z, 0.0f);
- }
-
- void addscissorvert(const vec &v, float &sx1, float &sy1, float &sx2, float &sy2)
- {
- vec p = camprojmatrix.perspectivetransform(v);
- sx1 = min(sx1, p.x);
- sy1 = min(sy1, p.y);
- sx2 = max(sx2, p.x);
- sy2 = max(sy2, p.y);
- }
-
- bool addscissorbox(const vec ¢er, float size)
- {
- float sx1, sy1, sx2, sy2;
- calcspherescissor(center, size, sx1, sy1, sx2, sy2);
- return addblurtiles(sx1, sy1, sx2, sy2);
- }
-
- bool addscissorbox(const vec &bbmin, const vec &bbmax)
- {
- float sx1 = 1, sy1 = 1, sx2 = -1, sy2 = -1;
- loopi(8)
- {
- vec v(i&1 ? bbmax.x : bbmin.x, i&2 ? bbmax.y : bbmin.y, i&4 ? bbmax.z : bbmin.z);
- addscissorvert(v, sx1, sy1, sx2, sy2);
- }
- return addblurtiles(sx1, sy1, sx2, sy2);
- }
-
- bool screenrect() const { return true; }
- bool filter() const { return blurdepthfx!=0; }
- bool highprecision() const { return colorfmt==GL_RG16F || colorfmt==GL_RGB16F; }
- bool emulatehighprecision() const { return depthfxemuprecision && !blurdepthfx; }
-
- bool shouldrender()
- {
- extern void finddepthfxranges();
- finddepthfxranges();
- return (numdepthfxranges && scissorx1 < scissorx2 && scissory1 < scissory2);
- }
-
- bool dorender()
- {
- glClearColor(1, 1, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- depthfxing = true;
-
- extern void renderdepthobstacles(const vec &bbmin, const vec &bbmax, float scale, float *ranges, int numranges);
- float scale = depthfxscale;
- float *ranges = depthfxranges;
- int numranges = numdepthfxranges;
- if(highprecision())
- {
- scale = depthfxfpscale;
- ranges = NULL;
- numranges = 0;
- }
- else if(emulatehighprecision())
- {
- scale = depthfxfpscale;
- ranges = NULL;
- numranges = -3;
- }
- renderdepthobstacles(depthfxmin, depthfxmax, scale, ranges, numranges);
-
- depthfxing = false;
-
- return numdepthfxranges > 0;
- }
-} depthfxtex;
-
-void cleanupdepthfx()
-{
- depthfxtex.cleanup(true);
-}
-
-bool depthfxing = false;
-
-bool binddepthfxtex()
-{
- if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
- {
- glActiveTexture_(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, depthfxtex.rendertex);
- glActiveTexture_(GL_TEXTURE0);
- return true;
- }
- return false;
-}
-
-void binddepthfxparams(float blend, float minblend = 0, bool allow = true, void *owner = NULL)
-{
- if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
- {
- float scale = 0, offset = -1, texscale = 0;
- if(!depthfxtex.highprecision())
- {
- float select[4] = { 0, 0, 0, 0 };
- if(!depthfxtex.emulatehighprecision())
- {
- loopi(numdepthfxranges) if(depthfxowners[i]==owner)
- {
- select[i] = float(depthfxscale)/blend;
- scale = 1.0f/blend;
- offset = -float(depthfxranges[i] - depthfxbias)/blend;
- break;
- }
- }
- else if(allow)
- {
- select[0] = float(depthfxfpscale)/blend;
- select[1] = select[0]/256;
- select[2] = select[1]/256;
- scale = 1.0f/blend;
- offset = 0;
- }
- LOCALPARAMF(depthfxselect, select[0], select[1], select[2], select[3]);
- }
- else if(allow)
- {
- scale = 1.0f/blend;
- offset = 0;
- texscale = float(depthfxfpscale)/blend;
- }
- LOCALPARAMF(depthfxparams, scale, offset, texscale, minblend);
- }
-}
-
-void drawdepthfxtex()
-{
- if(!depthfx) return;
-
- depthfxtex.render(1<<depthfxsize, 1<<depthfxsize, blurdepthfx, blurdepthfxsigma/100.0f);
-}
-
extern void cleanuptexture(Texture *t);
extern uchar *loadalphamask(Texture *t);
extern void loadlayermasks();
-extern Texture *cubemapload(const char *name, bool mipit = true, bool msg = true, bool transient = false);
extern void loadshaders();
extern void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum format = GL_RGB, GLenum target = GL_TEXTURE_2D, bool swizzle = false);
extern void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component = GL_RGB, GLenum target = GL_TEXTURE_2D, int pw = 0, int ph = 0, int pitch = 0, bool resize = true, GLenum format = GL_FALSE, bool swizzle = false);
extern bool hasVAO, hasFBO, hasAFBO, hasDS, hasTF, hasTRG, hasTSW, hasS3TC, hasFXT1, hasLATC, hasRGTC, hasAF, hasFBB, hasUBO, hasMBR;
extern int glversion, glslversion, glcompat;
-enum { DRAWTEX_NONE = 0, DRAWTEX_ENVMAP, DRAWTEX_MINIMAP, DRAWTEX_MODELPREVIEW };
+enum { DRAWTEX_NONE = 0, DRAWTEX_MODELPREVIEW };
extern float curfov, fovy, aspect, forceaspect;
extern int drawtex;
extern bool collideface(const cube &c, int orient);
extern int genclipplane(const cube &c, int i, vec *v, plane *clip);
extern void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool collide = true);
-extern bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat = MAT_AIR, ushort nmat = MAT_AIR, ushort matmask = MATF_VOLUME);
+extern bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat = MAT_AIR, ushort nmat = MAT_AIR, ushort matmask = 0);
extern int classifyface(const cube &c, int orient, const ivec &co, int size);
extern int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat = MAT_ALPHA, ushort matmask = MAT_ALPHA);
extern int visibleorient(const cube &c, int orient);
extern void calcmerges();
extern int mergefaces(int orient, facebounds *m, int sz);
-extern void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat = MAT_AIR, ushort matmask = MATF_VOLUME);
+extern void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat = MAT_AIR, ushort matmask = 0);
static inline cubeext &ext(cube &c)
{
extern int optimizematsurfs(materialsurface *matbuf, int matsurfs);
extern void setupmaterials(int start = 0, int len = 0);
extern void rendermaterials();
-extern int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask = MATF_VOLUME);
-
-// depthfx
-extern bool depthfxing;
-
-extern void drawdepthfxtex();
+extern int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask = 0);
// server
extern vector<const char *> gameargs;
extern void updatesounds();
extern void preloadmapsounds();
-// blendmap
-extern int blendpaintmode;
-
-struct BlendMapCache;
-extern BlendMapCache *newblendmapcache();
-extern void freeblendmapcache(BlendMapCache *&cache);
-extern bool setblendmaporigin(BlendMapCache *cache, const ivec &o, int size);
-extern bool hasblendmap(BlendMapCache *cache);
-extern uchar lookupblendmap(BlendMapCache *cache, const vec &pos);
-extern void resetblendmap();
-extern void enlargeblendmap();
-extern void shrinkblendmap(int octant);
-extern void optimizeblendmap();
-extern void stoppaintblendmap();
-extern void trypaintblendmap();
-extern void renderblendbrush(GLuint tex, float x, float y, float w, float h);
-extern void renderblendbrush();
-extern bool loadblendmap(stream *f, int info);
-extern void saveblendmap(stream *f);
-extern uchar shouldsaveblendmap();
-
#endif
#endif
namespace sphere
{
-
struct vert
{
vec pos;
void startrender()
{
- if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
- {
- if(!depthfxtex.highprecision()) SETSHADER(explosionsoft8);
- else SETSHADER(explosionsoft);
- }
- else SETSHADER(explosion);
-
+ SETSHADER(explosion);
sphere::enable();
}
sphere::cleanup();
}
- int finddepthfxranges(void **owners, float *ranges, int numranges, int maxranges, vec &bbmin, vec &bbmax)
- {
- static struct fireballent : physent
- {
- fireballent()
- {
- type = ENT_CAMERA;
- }
- } e;
-
- for(listparticle *p = list; p; p = p->next)
- {
- int ts = p->fade <= 5 ? 1 : lastmillis-p->millis;
- float pmax = p->val,
- size = p->fade ? float(ts)/p->fade : 1,
- psize = (p->size + pmax * size)*WOBBLE;
- if(2*(p->size + pmax)*WOBBLE < depthfxblend ||
- (!depthfxtex.highprecision() && !depthfxtex.emulatehighprecision() && psize > depthfxscale - depthfxbias) || ) continue;
-
- e.o = p->o;
- e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = psize;
- if(!::collide(&e, vec(0, 0, 0), 0, false)) continue;
-
- if(depthfxscissor==2 && !depthfxtex.addscissorbox(p->o, psize)) continue;
-
- vec dir = camera1->o;
- dir.sub(p->o);
- float dist = dir.magnitude();
- dir.mul(psize/dist).add(p->o);
- float depth = depthfxtex.eyedepth(dir);
-
- loopk(3)
- {
- bbmin[k] = min(bbmin[k], p->o[k] - psize);
- bbmax[k] = max(bbmax[k], p->o[k] + psize);
- }
-
- int pos = numranges;
- loopi(numranges) if(depth < ranges[i]) { pos = i; break; }
- if(pos >= maxranges) continue;
-
- if(numranges > pos)
- {
- int moved = min(numranges-pos, maxranges-(pos+1));
- memmove(&ranges[pos+1], &ranges[pos], moved*sizeof(float));
- memmove(&owners[pos+1], &owners[pos], moved*sizeof(void *));
- }
- if(numranges < maxranges) numranges++;
-
- ranges[pos] = depth;
- owners[pos] = p;
- }
-
- return numranges;
- }
-
void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity)
{
pe.maxfade = max(pe.maxfade, fade);
LOCALPARAM(center, o);
LOCALPARAMF(millis, lastmillis/1000.0f);
LOCALPARAMF(blendparams, inside ? 0.5f : 4, inside ? 0.25f : 0);
- binddepthfxparams(depthfxblend, inside ? blend/(2*255.0f) : 0, 2*(p->size + pmax)*WOBBLE >= depthfxblend, p);
int passes = inside ? 2 : 1;
loopi(passes)
}
}
};
+
static fireballrenderer fireballs("packages/particles/explosion.png"), bluefireballs("packages/particles/plasma.png");
Slot *slot;
vector<const extentity *> lights;
ShadowRayCache *shadowraycache;
- BlendMapCache *blendmapcache;
bool needspace, doneworking;
SDL_cond *spacecond;
SDL_Thread *thread;
return true;
}
-static void updatelightmap(const layoutinfo &surface)
-{
- if(max(LM_PACKW, LM_PACKH) > hwtexsize || !lightmaps.inrange(surface.lmid-LMID_RESERVED)) return;
-
- LightMap &lm = lightmaps[surface.lmid-LMID_RESERVED];
- if(lm.tex < 0)
- {
- lm.offsetx = lm.offsety = 0;
- lm.tex = lightmaptexs.length();
- LightMapTexture &tex = lightmaptexs.add();
- tex.type = lm.type;
- tex.w = LM_PACKW;
- tex.h = LM_PACKH;
- tex.unlitx = lm.unlitx;
- tex.unlity = lm.unlity;
- glGenTextures(1, &tex.id);
- createtexture(tex.id, tex.w, tex.h, NULL, 3, 1, tex.type&LM_ALPHA ? GL_RGBA : GL_RGB);
- if((lm.type&LM_TYPE)==LM_BUMPMAP0 && lightmaps.inrange(surface.lmid+1-LMID_RESERVED))
- {
- LightMap &lm2 = lightmaps[surface.lmid+1-LMID_RESERVED];
- lm2.offsetx = lm2.offsety = 0;
- lm2.tex = lightmaptexs.length();
- LightMapTexture &tex2 = lightmaptexs.add();
- tex2.type = (lm.type&~LM_TYPE) | LM_BUMPMAP0;
- tex2.w = LM_PACKW;
- tex2.h = LM_PACKH;
- tex2.unlitx = lm2.unlitx;
- tex2.unlity = lm2.unlity;
- glGenTextures(1, &tex2.id);
- createtexture(tex2.id, tex2.w, tex2.h, NULL, 3, 1, GL_RGB);
- }
- }
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, LM_PACKW);
-
- glBindTexture(GL_TEXTURE_2D, lightmaptexs[lm.tex].id);
- glTexSubImage2D(GL_TEXTURE_2D, 0, lm.offsetx + surface.x, lm.offsety + surface.y, surface.w, surface.h, lm.type&LM_ALPHA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, &lm.data[(surface.y*LM_PACKW + surface.x)*lm.bpp]);
- if((lm.type&LM_TYPE)==LM_BUMPMAP0 && lightmaps.inrange(surface.lmid+1-LMID_RESERVED))
- {
- LightMap &lm2 = lightmaps[surface.lmid+1-LMID_RESERVED];
- glBindTexture(GL_TEXTURE_2D, lightmaptexs[lm2.tex].id);
- glTexSubImage2D(GL_TEXTURE_2D, 0, lm2.offsetx + surface.x, lm2.offsety + surface.y, surface.w, surface.h, GL_RGB, GL_UNSIGNED_BYTE, &lm2.data[(surface.y*LM_PACKW + surface.x)*3]);
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-}
-
-
static uint generatelumel(lightmapworker *w, const float tolerance, uint lightmask, const vector<const extentity *> &lights, const vec &target, const vec &normal, vec &sample, int x, int y)
{
vec avgray(0, 0, 0);
static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha)
{
- alpha = lookupblendmap(w->blendmapcache, pos);
+ alpha = 0;
if(w->slot->layermask)
{
static const int sdim[] = { 1, 0, 0 }, tdim[] = { 2, 2, 1 };
}
if((w->type&LM_TYPE) == LM_BUMPMAP0) memclear(w->raydata, (LM_MAXW + 4)*(LM_MAXH + 4));
- origin1.sub(vec(ystep1).add(xstep1).mul(blurlms));
- origin2.sub(vec(ystep2).add(xstep2).mul(blurlms));
+ origin1.sub(vec(ystep1).add(xstep1).mul(0));
+ origin2.sub(vec(ystep2).add(xstep2).mul(0));
int aasample = min(1 << lmaa, 4);
int stride = aasample*(w->w+1);
vec *sample = w->colordata;
uchar *amb = w->ambient;
lerpbounds start, end;
- initlerpbounds(-blurlms, -blurlms, lv, numv, start, end);
- float sidex = side0 + blurlms*sidestep;
+ initlerpbounds(-0, -0, lv, numv, start, end);
+ float sidex = side0 + 0*sidestep;
for(int y = 0; y < w->h; ++y, sidex += sidestep)
{
vec normal, nstep;
- lerpnormal(-blurlms, y - blurlms, lv, numv, start, end, normal, nstep);
+ lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep);
for(int x = 0; x < w->w; ++x, normal.add(nstep), amb += w->bpp)
{
#define EDGE_TOLERANCE(x, y) \
- (x < blurlms \
- || x+1 > w->w - blurlms \
- || y < blurlms \
- || y+1 > w->h - blurlms \
+ (x < 0 \
+ || x+1 > w->w - 0 \
+ || y < 0 \
+ || y+1 > w->h - 0 \
? edgetolerance : 1)
float t = EDGE_TOLERANCE(x, y) * tolerance;
vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2);
}
if(adaptivesample > 1 && min(w->w, w->h) >= 2) lightmask = ~lightused;
sample = w->colordata;
- initlerpbounds(-blurlms, -blurlms, lv, numv, start, end);
- sidex = side0 + blurlms*sidestep;
+ initlerpbounds(-0, -0, lv, numv, start, end);
+ sidex = side0 + 0*sidestep;
for(int y = 0; y < w->h; ++y, sidex += sidestep)
{
vec normal, nstep;
- lerpnormal(-blurlms, y - blurlms, lv, numv, start, end, normal, nstep);
+ lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep);
for(int x = 0; x < w->w; ++x, normal.add(nstep))
{
if(aasample > 1)
{
vec normal, nstep;
- lerpnormal(-blurlms, w->h - blurlms, lv, numv, start, end, normal, nstep);
+ lerpnormal(-0, w->h - 0, lv, numv, start, end, normal, nstep);
for(int x = 0; x <= w->w; ++x, normal.add(nstep))
{
float weight = 1.0f / (1.0f + 4.0f*lmaa),
cweight = weight * (lmaa == 3 ? 5.0f : 1.0f);
vec *ray = w->raydata;
- uchar *dstcolor = blurlms && (w->w > 1 || w->h > 1) ? w->blur : w->colorbuf;
+ uchar *dstcolor = 0 && (w->w > 1 || w->h > 1) ? w->blur : w->colorbuf;
uchar mincolor[4] = { 255, 255, 255, 255 }, maxcolor[4] = { 0, 0, 0, 0 };
- bvec *dstray = blurlms && (w->w > 1 || w->h > 1) ? (bvec *)w->raydata : w->raybuf;
+ bvec *dstray = 0 && (w->w > 1 || w->h > 1) ? (bvec *)w->raydata : w->raybuf;
bvec minray(255, 255, 255), maxray(0, 0, 0);
loop(y, w->h)
{
}
if(w->type&LM_ALPHA)
{
- dstcolor[3] = ambientcolor[3];
+ dstcolor[3] = 127;///TODO
mincolor[3] = min(mincolor[3], dstcolor[3]);
maxcolor[3] = max(maxcolor[3], dstcolor[3]);
}
w->lastlightmap->h = w->h = 1;
}
}
- if(blurlms && (w->w>1 || w->h>1))
- {
- blurtexture(blurlms, w->bpp, w->w, w->h, w->colorbuf, w->blur, blurlms);
- if((w->type&LM_TYPE) == LM_BUMPMAP0) blurnormals(blurlms, w->w, w->h, w->raybuf, (const bvec *)w->raydata, blurlms);
- w->lastlightmap->w = (w->w -= 2*blurlms);
- w->lastlightmap->h = (w->h -= 2*blurlms);
- }
if(mincolor[3]==255) return SURFACE_LIGHTMAP_TOP;
else if(maxcolor[3]==0) return SURFACE_LIGHTMAP_BOTTOM;
else return SURFACE_LIGHTMAP_BLEND;
case ET_LIGHT: addlight(w, light, cx, cy, cz, size, v, n, numv); break;
}
}
- if(vslot.layer && (setblendmaporigin(w->blendmapcache, ivec(cx, cy, cz), size) || slot.layermask)) return true;
+ if(vslot.layer) return true;
return w->lights.length();
}
int lw = clamp(int(ceil((cmax.x - cmin.x + 1)*lpu)), LM_MINW, LM_MAXW), lh = clamp(int(ceil((cmax.y - cmin.y + 1)*lpu)), LM_MINH, LM_MAXH);
w->w = lw;
w->h = lh;
- if(!preview)
- {
- w->w += 2*blurlms;
- w->h += 2*blurlms;
- }
if(!alloclightmap(w)) return NO_SURFACE;
vec2 cscale = vec2(cmax).sub(cmin).div(vec2(lw-1, lh-1)),
for(int k = 3; k < numverts; k++) findnormal(pos[k], planes[1], n[k]);
}
- if(shadertype&(SHADER_NORMALSLMS | SHADER_ENVMAP))
+ if(shadertype&SHADER_NORMALSLMS)
{
loopk(numverts) curlitverts[k].norm = encodenormal(n[k]);
if(!(surf.numverts&MAXFACEVERTS))
}
}
-static bool previewblends(lightmapworker *w, cube &c, const ivec &co, int size)
-{
- if(isempty(c) || c.material&MAT_ALPHA) return false;
-
- int usefacemask = 0;
- loopi(6) if(lookupvslot(c.texture[i], false).layer)
- usefacemask |= visibletris(c, i, co, size)<<(4*i);
- if(!usefacemask) return false;
-
- if(!setblendmaporigin(w->blendmapcache, co, size))
- {
- if(!c.ext) return false;
- bool blends = false;
- loopi(6) if(c.ext->surfaces[i].numverts&LAYER_BOTTOM)
- {
- c.ext->surfaces[i].brighten();
- blends = true;
- }
- return blends;
- }
-
- w->firstlightmap = w->lastlightmap = w->curlightmaps = NULL;
- w->bufstart = w->bufused = 0;
- w->c = &c;
-
- surfaceinfo surfaces[6];
- vertinfo litverts[6*2*MAXFACEVERTS];
- int numlitverts = 0;
- memcpy(surfaces, c.ext ? c.ext->surfaces : brightsurfaces, sizeof(surfaces));
- loopi(6)
- {
- int usefaces = usefacemask&0xF;
- usefacemask >>= 4;
- if(!usefaces)
- {
- surfaceinfo &surf = surfaces[i];
- int numverts = surf.totalverts();
- if(numverts)
- {
- memcpy(&litverts[numlitverts], c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
- surf.verts = numlitverts;
- numlitverts += numverts;
- }
- continue;
- }
-
- VSlot &vslot = lookupvslot(c.texture[i], false),
- &layer = lookupvslot(vslot.layer, false);
- Shader *shader = vslot.slot->shader;
- int shadertype = shader->type | layer.slot->shader->type;
-
- vertinfo *curlitverts = &litverts[numlitverts];
- int numverts = 0;
- ivec v[4];
- genfaceverts(c, i, v);
- int convex = flataxisface(c, i) ? 0 : faceconvexity(v),
- order = usefaces&4 || convex < 0 ? 1 : 0;
- ivec vo = ivec(co).mask(0xFFF).shl(3);
- curlitverts[numverts++].set(v[order].mul(size).add(vo));
- if(usefaces&1) curlitverts[numverts++].set(v[order+1].mul(size).add(vo));
- curlitverts[numverts++].set(v[order+2].mul(size).add(vo));
- if(usefaces&2) curlitverts[numverts++].set(v[(order+3)&3].mul(size).add(vo));
-
- vec pos[4], n[4], po(ivec(co).mask(~0xFFF));
- loopj(numverts) pos[j] = vec(curlitverts[j].getxyz()).mul(1.0f/8).add(po);
-
- plane planes[2];
- int numplanes = 0;
- planes[numplanes++].toplane(pos[0], pos[1], pos[2]);
- if(numverts < 4 || !convex) loopk(numverts) n[k] = planes[0];
- else
- {
- planes[numplanes++].toplane(pos[0], pos[2], pos[3]);
- vec avg = vec(planes[0]).add(planes[1]).normalize();
- n[0] = avg;
- n[1] = planes[0];
- n[2] = avg;
- for(int k = 3; k < numverts; k++) n[k] = planes[1];
- }
-
- surfaceinfo &surf = surfaces[i];
- w->slot = vslot.slot;
- w->vslot = &vslot;
- w->type = shadertype&SHADER_NORMALSLMS ? LM_BUMPMAP0|LM_ALPHA : LM_DIFFUSE|LM_ALPHA;
- w->bpp = 4;
- w->orient = i;
- w->rotate = vslot.rotation;
- int surftype = setupsurface(w, planes, numplanes, pos, n, numverts, curlitverts, true);
- switch(surftype)
- {
- case SURFACE_AMBIENT_TOP:
- surf = brightsurface;
- continue;
-
- case SURFACE_AMBIENT_BOTTOM:
- surf = brightbottomsurface;
- continue;
-
- case SURFACE_LIGHTMAP_BLEND:
- {
- if(surf.numverts == (LAYER_BLEND|numverts) &&
- surf.lmid[0] == surf.lmid[1] &&
- (surf.numverts&MAXFACEVERTS) == numverts &&
- !memcmp(curlitverts, c.ext->verts() + surf.verts, numverts*sizeof(vertinfo)) &&
- lightmaps.inrange(surf.lmid[0]-LMID_RESERVED) &&
- lightmaps[surf.lmid[0]-LMID_RESERVED].type==w->type)
- {
- vertinfo *oldverts = c.ext->verts() + surf.verts;
- layoutinfo layout;
- layout.w = w->w;
- layout.h = w->h;
- layout.x = (oldverts[0].x - curlitverts[0].x)/((USHRT_MAX+1)/LM_PACKW);
- layout.y = (oldverts[0].y - curlitverts[0].y)/((USHRT_MAX+1)/LM_PACKH);
- if(LM_PACKW - layout.x >= w->w && LM_PACKH - layout.y >= w->h)
- {
- layout.lmid = surf.lmid[0];
- copylightmap(*w->lastlightmap, layout);
- updatelightmap(layout);
- surf.verts = numlitverts;
- numlitverts += numverts;
- continue;
- }
- }
-
- surf.verts = numlitverts;
- surf.numverts = LAYER_BLEND|numverts;
- numlitverts += numverts;
- layoutinfo layout;
- if(packlightmap(*w->lastlightmap, layout)) updatelightmap(layout);
- surf.lmid[0] = surf.lmid[1] = layout.lmid;
- ushort offsetx = layout.x*((USHRT_MAX+1)/LM_PACKW), offsety = layout.y*((USHRT_MAX+1)/LM_PACKH);
- loopk(numverts)
- {
- vertinfo &v = curlitverts[k];
- v.u += offsetx;
- v.v += offsety;
- }
- continue;
- }
- }
- }
-
- setsurfaces(c, surfaces, litverts, numlitverts);
- return true;
-}
-
-static bool previewblends(lightmapworker *w, cube *c, const ivec &co, int size, const ivec &bo, const ivec &bs)
-{
- bool changed = false;
- loopoctabox(co, size, bo, bs)
- {
- ivec o(i, co, size);
- cubeext *ext = c[i].ext;
- if(ext && ext->va && ext->va->hasmerges)
- {
- changed = true;
- destroyva(ext->va);
- ext->va = NULL;
- invalidatemerges(c[i], co, size, true);
- }
- if(c[i].children ? previewblends(w, c[i].children, o, size/2, bo, bs) : previewblends(w, c[i], o, size))
- {
- changed = true;
- ext = c[i].ext;
- if(ext && ext->va)
- {
- destroyva(ext->va);
- ext->va = NULL;
- }
- }
- }
- return changed;
-}
-
-void previewblends(const ivec &bo, const ivec &bs)
-{
- loadlayermasks();
- if(lightmapworkers.empty()) lightmapworkers.add(new lightmapworker);
- lightmapworkers[0]->reset();
- if(previewblends(lightmapworkers[0], worldroot, ivec(0, 0, 0), worldsize/2, bo, bs))
- commitchanges(true);
-}
-
void cleanuplightmaps()
{
loopv(lightmaps)
colordata = new vec[4*(LM_MAXW+1 + 4)*(LM_MAXH+1 + 4)];
raydata = new vec[(LM_MAXW + 4)*(LM_MAXH + 4)];
shadowraycache = newshadowraycache();
- blendmapcache = newblendmapcache();
needspace = doneworking = false;
spacecond = NULL;
thread = NULL;
delete[] colordata;
delete[] raydata;
freeshadowraycache(shadowraycache);
- freeblendmapcache(blendmapcache);
}
void lightmapworker::cleanupthread()
}
renderbackground("computing lightmaps... (esc to abort)");
mpremip(true);
- optimizeblendmap();
loadlayermasks();
int numthreads = lightthreads > 0 ? lightthreads : numcpus;
if(numthreads > 1) preloadusedmapmodels(false, true);
extern void brightencube(cube &c);
extern void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts);
extern void setsurface(cube &c, int orient, const surfaceinfo &surf, const vertinfo *verts, int numverts);
-extern void previewblends(const ivec &bo, const ivec &bs);
struct lerpvert
{
extern void cleanupmodels();
extern void cleanupprefabs();
extern void cleanuplightmaps();
- extern void cleanupblendmap();
extern void cleanshadowmap();
- extern void cleanupdepthfx();
cleanupva();
cleanupparticles();
cleanupdecals();
cleanupprefabs();
cleanuptextures();
cleanuplightmaps();
- cleanupblendmap();
cleanshadowmap();
- cleanupdepthfx();
cleanupshaders();
cleanupgl();
const char *getmaterialdesc(int mat, const char *prefix)
{
- static const ushort matmasks[] = { MATF_VOLUME|MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA };
+ static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA };
static string desc;
desc[0] = '\0';
loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i])
{
loopi(6)
{
- static const ushort matmasks[] = { MATF_VOLUME|MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA };
+ static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA };
loopj(sizeof(matmasks)/sizeof(matmasks[0]))
{
int matmask = matmasks[j];
loopj(va->matsurfs)
{
materialsurface &m = va->matbuf[j];
- int matvol = m.material&MATF_VOLUME;
+ int matvol = 0;
if(matvol) hasmat |= 1<<m.material;
m.skip = 0;
if(skip && m.material == skip->material && m.orient == skip->orient && skip->skip < 0xFFFF)
materialsurface &m = va->matbuf[i];
if(!editmode || !showmat || drawtex)
{
- int matvol = m.material&MATF_VOLUME;
+ int matvol = 0;
if(m.visible == MATSURF_EDIT_ONLY) { i += m.skip; continue; }
}
- else if(glaring) continue;
vismats.add(&m);
}
}
MSlot *mslot = NULL;
int lastorient = -1, lastmat = -1;
bool depth = true, blended = false;
- ushort envmapped = EMID_NONE;
GLOBALPARAM(camera, camera1->o);
virtual bool load() = 0;
virtual int type() const = 0;
virtual BIH *setBIH() { return 0; }
- virtual bool envmapped() { return false; }
virtual bool skeletal() const { return false; }
virtual void setshader(Shader *shader) {}
- virtual void setenvmap(float envmapmin, float envmapmax, Texture *envmap) {}
virtual void setspec(float spec) {}
virtual void setambient(float ambient) {}
virtual void setalphatest(float alpha) {}
struct elementset
{
- ushort texture, lmid, envmap;
+ ushort texture, lmid;
uchar dim, layer;
ushort length[2], minvert[2], maxvert[2];
};
-enum
-{
- EMID_NONE = 0,
- EMID_CUSTOM,
- EMID_RESERVED
-};
-
struct materialsurface
{
ivec o;
union
{
entity *light;
- ushort envmap;
uchar ends;
};
};
};
extern cube *worldroot; // the world data. only a ptr to 8 cubes (ie: like cube.children above)
-extern int wtris, wverts, vtris, vverts, glde, gbatches, rplanes;
+extern int wtris, wverts, vtris, vverts, glde, gbatches;
extern int allocnodes, allocva, selchildcount, selchildmat;
const uint F_EMPTY = 0; // all edges in the range (0,0)
player->state = CS_EDITING;
}
cancelsel();
- stoppaintblendmap();
keyrepeat(editmode);
editing = entediting = editmode;
extern int fullbright;
od = dimension(orient),
odc = dimcoord(orient);
- bool hidecursor = g3d_windowhit(true, false) || blendpaintmode, hovering = false;
+ bool hidecursor = g3d_windowhit(true, false), hovering = false;
if(moving)
{
{
extern int hidehud;
if(!editmode || hidehud || mainmenu) return;
- if(blendpaintmode) trypaintblendmap();
}
//////////// ready changes to vertex arrays ////////////
if(filter >= 0)
{
filtermat = filter&0xFFFF;
- filtermask = filtermat&(MATF_VOLUME|MATF_INDEX) ? (int) MATF_VOLUME|MATF_INDEX : (filtermat&MATF_CLIP ? (int) MATF_CLIP : (int) filtermat);
+ filtermask = filtermat&(MATF_INDEX) ? (int) MATF_INDEX : (filtermat&MATF_CLIP ? (int) MATF_CLIP : (int) filtermat);
filtergeom = filter&~0xFFFF;
}
if(matid < 0)
}
else
{
- matmask = matid&(MATF_VOLUME|MATF_INDEX) ? 0 : (matid&MATF_CLIP ? ~MATF_CLIP : ~matid);
+ matmask = matid&MATF_INDEX ? 0 : (matid&MATF_CLIP ? ~MATF_CLIP : ~matid);
}
loopselxyz(setmat(c, matid, matmask, filtermat, filtermask, filtergeom));
}
{
VSlot &vslot = lookupvslot(texmru[ti]), *layer = NULL;
Slot &slot = *vslot.slot;
- Texture *tex = slot.sts.empty() ? notexture : slot.sts[0].t, *glowtex = NULL, *layertex = NULL;
- if(slot.texmask&(1<<TEX_GLOW))
- {
- loopvj(slot.sts) if(slot.sts[j].type==TEX_GLOW) { glowtex = slot.sts[j].t; break; }
- }
+ Texture *tex = slot.sts.empty() ? notexture : slot.sts[0].t, *layertex = NULL;
if(vslot.layer)
{
layer = &lookupvslot(vslot.layer);
}
loopk(4) { tc[k].x = tc[k].x/sx - xoff/tex->xs; tc[k].y = tc[k].y/sy - yoff/tex->ys; }
glBindTexture(GL_TEXTURE_2D, tex->id);
- loopj(glowtex ? 3 : 2)
- {
- if(j < 2) gle::color(vec(vslot.colorscale).mul(j), texpaneltimer/1000.0f);
- else
- {
- glBindTexture(GL_TEXTURE_2D, glowtex->id);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- gle::color(vslot.glowcolor, texpaneltimer/1000.0f);
- }
- gle::begin(GL_TRIANGLE_STRIP);
- gle::attribf(x, y); gle::attrib(tc[0]);
- gle::attribf(x+r, y); gle::attrib(tc[1]);
- gle::attribf(x, y+r); gle::attrib(tc[3]);
- gle::attribf(x+r, y+r); gle::attrib(tc[2]);
- xtraverts += gle::end();
- if(j==1 && layertex)
- {
- gle::color(layer->colorscale, texpaneltimer/1000.0f);
- glBindTexture(GL_TEXTURE_2D, layertex->id);
- gle::begin(GL_TRIANGLE_STRIP);
- gle::attribf(x+r/2, y+r/2); gle::attrib(tc[0]);
- gle::attribf(x+r, y+r/2); gle::attrib(tc[1]);
- gle::attribf(x+r/2, y+r); gle::attrib(tc[3]);
- gle::attribf(x+r, y+r); gle::attrib(tc[2]);
- xtraverts += gle::end();
- }
- if(!j)
- {
- r -= 10;
- x += 5;
- y += 5;
- }
- else if(j == 2) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
}
y += s+gap;
}
struct sortkey
{
- ushort tex, lmid, envmap;
+ ushort tex, lmid;
uchar dim, layer, alpha;
sortkey() {}
- sortkey(ushort tex, ushort lmid, uchar dim, uchar layer = LAYER_TOP, ushort envmap = EMID_NONE, uchar alpha = NO_ALPHA)
- : tex(tex), lmid(lmid), envmap(envmap), dim(dim), layer(layer), alpha(alpha)
+ sortkey(ushort tex, ushort lmid, uchar dim, uchar layer = LAYER_TOP, uchar alpha = NO_ALPHA)
+ : tex(tex), lmid(lmid), dim(dim), layer(layer), alpha(alpha)
{}
- bool operator==(const sortkey &o) const { return tex==o.tex && lmid==o.lmid && envmap==o.envmap && dim==o.dim && layer==o.layer && alpha==o.alpha; }
+ bool operator==(const sortkey &o) const { return tex==o.tex && lmid==o.lmid && dim==o.dim && layer==o.layer && alpha==o.alpha; }
};
struct sortval
t.tris[l][j] = addvert(vtx2);
}
}
- sortval *dst = indices.access(sortkey(k.tex, t.unlit, k.dim, k.layer, k.envmap, k.alpha));
+ sortval *dst = indices.access(sortkey(k.tex, t.unlit, k.dim, k.layer, k.alpha));
if(dst) loopl(2) loopvj(t.tris[l]) dst->tris[l].add(t.tris[l][j]);
}
}
{
if(k.lmid>=LMID_RESERVED && lightmaptexs[k.lmid].unlitx>=0)
{
- sortkey ukey(k.tex, LMID_AMBIENT, k.dim, k.layer, k.envmap, k.alpha);
+ sortkey ukey(k.tex, LMID_AMBIENT, k.dim, k.layer, k.alpha);
sortval *uval = indices.access(ukey);
if(uval && uval->unlit<=0)
{
{
if(x.lmid < y.lmid) return true;
if(x.lmid > y.lmid) return false;
- if(x.envmap < y.envmap) return true;
- if(x.envmap > y.envmap) return false;
if(x.dim < y.dim) return true;
if(x.dim > y.dim) return false;
return false;
e.lmid = t.unlit>0 ? t.unlit : k.lmid;
e.dim = k.dim;
e.layer = k.layer;
- e.envmap = k.envmap;
ushort *startbuf = curbuf;
loopl(2)
{
Slot &slot = *lookupvslot(k.tex, false).slot;
loopvj(slot.sts) va->texmask |= 1<<slot.sts[j].type;
- if(slot.shader->type&SHADER_ENVMAP) va->texmask |= 1<<TEX_ENVMAP;
}
}
normals[3] = n2;
}
-void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, ushort envmap = EMID_NONE, int grassy = 0, bool alpha = false, int layer = LAYER_TOP)
+void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, int grassy = 0, bool alpha = false, int layer = LAYER_TOP)
{
(void) grassy;
int dim = dimension(orient);
}
else
{
- v.norm = vinfo && vinfo[k].norm && envmap != EMID_NONE ? bvec(decodenormal(vinfo[k].norm)) : bvec(128, 128, 255);
+ v.norm = bvec(128, 128, 255);
v.tangent = bvec4(255, 128, 128, 255);
}
index[k] = vc.addvert(v);
if(lmid >= LMID_RESERVED) lmid = lm ? lm->tex : LMID_AMBIENT;
- sortkey key(texture, lmid, !vslot.scroll.iszero() ? dim : 3, layer == LAYER_BLEND ? LAYER_BLEND : LAYER_TOP, envmap, alpha ? (vslot.alphaback ? ALPHA_BACK : (vslot.alphafront ? ALPHA_FRONT : NO_ALPHA)) : NO_ALPHA);
+ sortkey key(texture, lmid, !vslot.scroll.iszero() ? dim : 3, layer == LAYER_BLEND ? LAYER_BLEND : LAYER_TOP, alpha ? (vslot.alphaback ? ALPHA_BACK : (vslot.alphafront ? ALPHA_FRONT : NO_ALPHA)) : NO_ALPHA);
addtris(key, orient, verts, index, numverts, convex, shadowmask, tj);
}
VSlot &vslot = lookupvslot(c.texture[i], true),
*layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, true) : NULL;
- ushort envmap = vslot.slot->shader->type&SHADER_ENVMAP ? (int) (vslot.slot->texmask&(1<<TEX_ENVMAP) ? (int) EMID_CUSTOM : (int) closestenvmap(i, co, size)) : (int) EMID_NONE,
- envmap2 = layer && layer->slot->shader->type&SHADER_ENVMAP ? (int) (layer->slot->texmask&(1<<TEX_ENVMAP) ? (int) EMID_CUSTOM : (int) closestenvmap(i, co, size)) : (int) EMID_NONE;
while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next;
int hastj = tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1) ? tj : -1;
if(!c.ext)
- addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, envmap, 0, (c.material&MAT_ALPHA)!=0);
+ addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0);
else
{
const surfaceinfo &surf = c.ext->surfaces[i];
if(!surf.numverts || surf.numverts&LAYER_TOP)
- addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, envmap, 0, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND));
+ addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND));
if(surf.numverts&LAYER_BOTTOM)
- addcubeverts(layer ? *layer : vslot, i, size, pos, convex, vslot.layer, surf.lmid[1], surf.numverts&LAYER_DUP ? verts + numverts : verts, numverts, hastj, envmap2);
+ addcubeverts(layer ? *layer : vslot, i, size, pos, convex, vslot.layer, surf.lmid[1], surf.numverts&LAYER_DUP ? verts + numverts : verts, numverts, hastj);
}
}
}
struct mergedface
{
uchar orient, lmid, numverts;
- ushort mat, tex, envmap;
+ ushort mat, tex;
vertinfo *verts;
int tjoints;
};
mf.orient = i;
mf.mat = c.material;
mf.tex = c.texture[i];
- mf.envmap = EMID_NONE;
mf.lmid = surf.lmid[0];
mf.numverts = surf.numverts;
mf.verts = c.ext->verts() + surf.verts;
VSlot &vslot = lookupvslot(mf.tex, true),
*layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, true) : NULL;
- if(vslot.slot->shader->type&SHADER_ENVMAP)
- mf.envmap = vslot.slot->texmask&(1<<TEX_ENVMAP) ? (int) EMID_CUSTOM : (int) closestenvmap(i, co, size);
- ushort envmap2 = layer && layer->slot->shader->type&SHADER_ENVMAP ? (int) (layer->slot->texmask&(1<<TEX_ENVMAP) ? (int) EMID_CUSTOM : (int) closestenvmap(i, co, size)) : (int) EMID_NONE;
if(surf.numverts&LAYER_TOP) vamerges[level].add(mf);
if(surf.numverts&LAYER_BOTTOM)
{
mf.tex = vslot.layer;
- mf.envmap = envmap2;
mf.lmid = surf.lmid[1];
mf.numverts &= ~LAYER_TOP;
if(surf.numverts&LAYER_DUP) mf.verts += numverts;
pos[i] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo);
}
VSlot &vslot = lookupvslot(mf.tex, true);
- addcubeverts(vslot, mf.orient, 1<<level, pos, 0, mf.tex, mf.lmid, mf.verts, numverts, mf.tjoints, mf.envmap, 0, (mf.mat&MAT_ALPHA)!=0, mf.numverts&LAYER_BLEND);
+ addcubeverts(vslot, mf.orient, 1<<level, pos, 0, mf.tex, mf.lmid, mf.verts, numverts, mf.tjoints, 0, (mf.mat&MAT_ALPHA)!=0, mf.numverts&LAYER_BLEND);
vahasmerges |= MERGE_USE;
}
mfl.setsize(0);
}
else fatal("Framebuffer object support is required!");
- extern int fpdepthfx;
if(ati)
{
minimizetcusage = 1;
- if(hasTF && hasTRG) fpdepthfx = 1;
// On Catalyst 10.2, issuing an occlusion query on the first draw using a given cubemap texture causes a nasty crash
ati_cubemap_bug = 1;
}
rtsharefb = 0; // work-around for strange driver stalls involving when using many FBOs
extern int filltjoints;
if(glversion < 300 && !hasext("GL_EXT_gpu_shader4")) filltjoints = 0; // DX9 or less NV cards seem to not cause many sparklies
-
- if(hasTF && hasTRG) fpdepthfx = 1;
}
else
{
if(glversion >= 300 || hasext("GL_EXT_gpu_shader4"))
{
// on DX10 or above class cards (i.e. GF8 or RadeonHD) enable expensive features
- extern int maxdynlights, depthfxsize, blurdepthfx, texcompress;
+ extern int maxdynlights, texcompress;
maxdynlights = MAXDYNLIGHTS;
- depthfxsize = 10;
- blurdepthfx = 0;
texcompress = max(texcompress, 1024 + 1);
}
}
do
{
cube &c = lookupcube(o, 0, co, csize);
- int mat = c.material&MATF_VOLUME;
- abovemat = (int) MAT_AIR;
- return o.z;
+ abovemat = (int) MAT_AIR;
+ return o.z;
o.z = co.z + csize;
}
while(o.z < worldsize);
{
if(minimized) { deferdrawtextures = true; return; }
deferdrawtextures = false;
- genenvmaps();
}
int xtraverts, xtravertsva;
rendergame(true);
renderavatar();
- if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- drawdepthfxtex();
-
if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
rendermaterials();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
- renderblendbrush();
-
rendereditcursor();
glDepthMask(GL_TRUE);
xtravertsva/1024,
glde,
gbatches,
- getnumqueries(),
- rplanes
+ getnumqueries()
};
loopi(8) if(prevstats[i]==curstats[i]) curstats[i] = nextstats[i];
COMMAND(mdldepthoffset, "i");
-void mdlenvmap(float *envmapmax, float *envmapmin, char *envmap)
-{
- checkmdl;
- loadingmodel->setenvmap(*envmapmin, *envmapmax, envmap[0] ? cubemapload(envmap) : NULL);
-}
-
-COMMAND(mdlenvmap, "ffs");
-
void mdlfullbright(float *fullbright)
{
checkmdl;
if(!m) return;
vec center(0, 0, 0), bbradius(0, 0, 0);
float radius = 0;
- bool shadow = !shadowmap && !glaring && (flags&(MDL_SHADOW|MDL_DYNSHADOW));
+ bool shadow = !shadowmap && (flags&(MDL_SHADOW|MDL_DYNSHADOW));
if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW))
{
virtual void reset() = 0;
virtual void resettracked(physent *owner) { }
virtual particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity = 0) = 0;
- virtual int adddepthfx(vec &bbmin, vec &bbmax) { return 0; }
virtual void update() { }
virtual void render() = 0;
virtual bool haswork() = 0;
typedef varenderer<PT_TAPE> taperenderer;
typedef varenderer<PT_TRAIL> trailrenderer;
-#include "depthfx.h"
#include "explosion.h"
#include "lightning.h"
: quadrenderer(texname, type|PT_SOFT, collide)
{
}
-
- int adddepthfx(vec &bbmin, vec &bbmax)
- {
- if(!depthfxtex.highprecision() && !depthfxtex.emulatehighprecision()) return 0;
- int numsoft = 0;
- loopi(numparts)
- {
- particle &p = parts[i];
- float radius = p.size*SQRT2;
- vec o, d;
- int blend, ts;
- calc(&p, blend, ts, o, d, false);
- if((depthfxscissor!=2 || depthfxtex.addscissorbox(p.o, radius)))
- {
- numsoft++;
- loopk(3)
- {
- bbmin[k] = min(bbmin[k], o[k] - radius);
- bbmax[k] = max(bbmax[k], o[k] + radius);
- }
- }
- }
- return numsoft;
- }
};
static partrenderer *parts[] =
&metervs, // meter vs.
};
-void finddepthfxranges()
-{
- depthfxmin = vec(1e16f, 1e16f, 1e16f);
- depthfxmax = vec(0, 0, 0);
- numdepthfxranges = fireballs.finddepthfxranges(depthfxowners, depthfxranges, 0, MAXDFXRANGES, depthfxmin, depthfxmax);
- numdepthfxranges = bluefireballs.finddepthfxranges(depthfxowners, depthfxranges, numdepthfxranges, MAXDFXRANGES, depthfxmin, depthfxmax);
- loopk(3)
- {
- depthfxmin[k] -= depthfxmargin;
- depthfxmax[k] += depthfxmargin;
- }
- if(depthfxparts)
- {
- loopi(sizeof(parts)/sizeof(parts[0]))
- {
- partrenderer *p = parts[i];
- if(p->type&PT_SOFT && p->adddepthfx(depthfxmin, depthfxmax))
- {
- if(!numdepthfxranges)
- {
- numdepthfxranges = 1;
- depthfxowners[0] = NULL;
- depthfxranges[0] = 0;
- }
- }
- }
- }
- if(depthfxscissor<2 && numdepthfxranges>0) depthfxtex.addscissorbox(depthfxmin, depthfxmax);
-}
-
VARFP(maxparticles, 10, 4000, 40000, initparticles());
VARFP(fewparticles, 10, 100, 40000, initparticles());
loopi(sizeof(parts)/sizeof(parts[0]))
{
- if(glaring && !(parts[i]->type&PT_GLARE)) continue;
parts[i]->update();
}
uint lastflags = PT_LERP|PT_SHADER,
flagmask = PT_LERP|PT_MOD|PT_SHADER|PT_NOTEX;
- if(binddepthfxtex()) flagmask |= PT_SOFT;
-
loopi(sizeof(parts)/sizeof(parts[0]))
{
partrenderer *p = parts[i];
{
if(flags&PT_SOFT)
{
- if(!depthfxtex.highprecision()) SETSHADER(particlesoft8);
- else SETSHADER(particlesoft);
-
- binddepthfxparams(depthfxpartblend);
+ SETSHADER(particlesoft);
}
else if(flags&PT_NOTEX) particlenotextureshader->set();
else particleshader->set();
if(e.attr3 > 0) color = colorfromattr(e.attr3);
else
{
- int mat = MAT_WATER + clamp(-e.attr3, 0, 3);
- const bvec &wfcol = { 0 };
- color = (int(wfcol[0])<<16) | (int(wfcol[1])<<8) | int(wfcol[2]);
- if(!color)
- {
- const bvec &wcol = { 0 };
- color = (int(wcol[0])<<16) | (int(wcol[1])<<8) | int(wcol[2]);
- }
+ int mat = clamp(-e.attr3, 0, 3);
+ color = 0xff7700;
}
regularsplash(PART_WATER, color, 150, 4, 200, offsetvec(e.o, e.attr2, rnd(10)), 0.6f, 2);
break;
gle::disablevertex();
}
-HVAR(blendbrushcolor, 0, 0x0000C0, 0xFFFFFF);
-
-void renderblendbrush(GLuint tex, float x, float y, float w, float h)
-{
- SETSHADER(blendbrush);
-
- gle::enablevertex();
-
- glDepthFunc(GL_LEQUAL);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
- glBindTexture(GL_TEXTURE_2D, tex);
- gle::color(vec::hexcolor(blendbrushcolor), 0.25f);
-
- LOCALPARAMF(texgenS, 1.0f/w, 0, 0, -x/w);
- LOCALPARAMF(texgenT, 0, 1.0f/h, 0, -y/h);
-
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue;
- if(va->o.x + va->size <= x || va->o.y + va->size <= y || va->o.x >= x + w || va->o.y >= y + h) continue;
-
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
-
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
-
- prev = va;
- }
-
- glDisable(GL_BLEND);
-
- glDepthFunc(GL_LESS);
-
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
-}
-
void rendershadowmapreceivers()
{
SETSHADER(shadowmapreceiver);
gle::disablevertex();
}
-void renderdepthobstacles(const vec &bbmin, const vec &bbmax, float scale, float *ranges, int numranges)
-{
- float scales[4] = { 0, 0, 0, 0 }, offsets[4] = { 0, 0, 0, 0 };
- if(numranges < 0)
- {
- SETSHADER(depthfxsplitworld);
-
- loopi(-numranges)
- {
- if(!i) scales[i] = 1.0f/scale;
- else scales[i] = scales[i-1]*256;
- }
- }
- else
- {
- SETSHADER(depthfxworld);
-
- if(!numranges) loopi(4) scales[i] = 1.0f/scale;
- else loopi(numranges)
- {
- scales[i] = 1.0f/scale;
- offsets[i] = -ranges[i]/scale;
- }
- }
- LOCALPARAMF(depthscale, scales[0], scales[1], scales[2], scales[3]);
- LOCALPARAMF(depthoffsets, offsets[0], offsets[1], offsets[2], offsets[3]);
-
- gle::enablevertex();
-
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded >= OCCLUDE_GEOM ||
- va->o.x > bbmax.x || va->o.y > bbmax.y || va->o.z > bbmax.z ||
- va->o.x + va->size < bbmin.x || va->o.y + va->size < bbmin.y || va->o.z + va->size < bbmin.z)
- continue;
-
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
-
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
- if(va->alphatris > 0)
- {
- drawvatris(va, 3*va->alphatris, va->edata + 3*(va->tris + va->blendtris));
- xtravertsva += 3*va->alphatris;
- }
-
- prev = va;
- }
-
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
-}
-
VAR(oqdist, 0, 256, 1024);
VAR(zpass, 0, 1, 1);
VAR(envpass, 0, 1, 1);
if(es.texture > b.es.texture) return 1;
if(es.lmid < b.es.lmid) return -1;
if(es.lmid > b.es.lmid) return 1;
- if(es.envmap < b.es.envmap) return -1;
- if(es.envmap > b.es.envmap) return 1;
if(es.dim < b.es.dim) return -1;
if(es.dim > b.es.dim) return 1;
return 0;
}
tmu++;
}
- if(b.vslot.slot->shader->type&SHADER_ENVMAP && b.es.envmap!=EMID_CUSTOM)
- {
- GLuint emtex = lookupenvmap(b.es.envmap);
- if(cur.textures[tmu]!=emtex)
- {
- glActiveTexture_(GL_TEXTURE0+tmu);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[tmu] = emtex);
- changed = true;
- }
- }
+
if(changed) glActiveTexture_(GL_TEXTURE0);
if(cur.dynlightmask != b.va->dynlightmask)
cur.colorscale = vslot.colorscale;
GLOBALPARAMF(colorparams, 2*vslot.colorscale.x, 2*vslot.colorscale.y, 2*vslot.colorscale.z, 1);
}
- int tmu = 2, envmaptmu = -1;
+ int tmu = 2;
if(slot.shader->type&SHADER_NORMALSLMS) tmu++;
- if(slot.shader->type&SHADER_ENVMAP) envmaptmu = tmu++;
loopvj(slot.sts)
{
Slot::Tex &t = slot.sts[j];
if(t.type==TEX_DIFFUSE || t.combined>=0) continue;
- if(t.type==TEX_ENVMAP)
+ if(cur.textures[tmu]!=t.t->id)
{
- if(envmaptmu>=0 && t.t && cur.textures[envmaptmu]!=t.t->id)
- {
- glActiveTexture_(GL_TEXTURE0+envmaptmu);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[envmaptmu] = t.t->id);
- }
- }
- else
- {
- if(cur.textures[tmu]!=t.t->id)
- {
- glActiveTexture_(GL_TEXTURE0+tmu);
- glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id);
- }
- if(++tmu >= 8) break;
+ glActiveTexture_(GL_TEXTURE0+tmu);
+ glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id);
}
+ if(++tmu >= 8) break;
}
glActiveTexture_(GL_TEXTURE0);
static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed)
{
- if(fading && !cur.blending && !cur.alphaing)
+ if(!cur.blending && !cur.alphaing)
{
if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot);
else s->setvariant(cur.visibledynlights, 2, slot, vslot);
if(!cur.alphaing) vverts += va->verts;
va->shadowed = false;
va->dynlightmask = 0;
- if(!drawtex && !glaring && !cur.alphaing)
+ if(!drawtex && !cur.alphaing)
{
va->shadowed = isshadowmapreceiver(va);
calcdynlightmask(va);
void rendergeom(void)
{
- bool mainpass = !drawtex && !glaring,
+ bool mainpass = !drawtex,
doOQ = oqfrags && oqgeom && mainpass,
doZP = doOQ && zpass,
- doSM = shadowmap && !drawtex && !glaring;
+ doSM = shadowmap && !drawtex;
renderstate cur;
if(mainpass)
{
if(!front) glCullFace(GL_BACK);
}
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, fading ? GL_FALSE : GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
{
case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break;
case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break;
- case TEX_GLOW: UNIFORMTEX("glowmap", tmu++); break;
case TEX_DECAL: UNIFORMTEX("decal", tmu++); break;
case TEX_SPEC: if(t.combined<0) UNIFORMTEX("specmap", tmu++); break;
case TEX_DEPTH: if(t.combined<0) UNIFORMTEX("depthmap", tmu++); break;
linkslotshaderparams(s.params, sh, load);
if(!sh) return;
-
- if(s.slot->texmask&(1<<TEX_GLOW))
- {
- static const char *paramname = getshaderparamname("glowcolor");
- const float *param = findslotparam(s, paramname);
- if(param) s.glowcolor = vec(param).clamp(0, 1);
- }
}
void altshader(char *origname, char *altname)
void setshader(Shader *s)
{
skelmeshgroup *g = (skelmeshgroup *)group;
- if(glaring)
- {
- if(!g->skel->usegpuskel) s->setvariant(0, 1);
- else s->setvariant(min(maxweights, g->vweights), 1);
- }
- else if(!g->skel->usegpuskel) s->set();
+ if(!g->skel->usegpuskel) s->set();
else s->setvariant(min(maxweights, g->vweights)-1, 0);
}
vector<VSlot *> vslots;
vector<Slot *> slots;
-MSlot materialslots[(MATF_VOLUME|MATF_INDEX)+1];
Slot dummyslot;
VSlot dummyvslot(&dummyslot);
COMMAND(texturereset, "i");
-void materialreset()
-{
- if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return;
- loopi((MATF_VOLUME|MATF_INDEX)+1) materialslots[i].reset();
-}
-
-COMMAND(materialreset, "");
-
static int compactedvslots = 0, compactvslotsprogress = 0, clonedvslots = 0;
static bool markingvslots = false;
resetslotshader();
slots.deletecontents();
vslots.deletecontents();
- loopi((MATF_VOLUME|MATF_INDEX)+1) materialslots[i].reset();
clonedvslots = 0;
}
{"u", TEX_UNKNOWN},
{"d", TEX_DECAL},
{"n", TEX_NORMAL},
- {"g", TEX_GLOW},
{"s", TEX_SPEC},
{"z", TEX_DEPTH},
- {"a", TEX_ALPHA},
- {"e", TEX_ENVMAP}
+ {"a", TEX_ALPHA}
};
int findslottex(const char *name)
{
if(slots.length()>=0x10000) return;
static int lastmatslot = -1;
- int tnum = findslottex(type), matslot = findmaterial(type);
+ int tnum = findslottex(type);
if(tnum<0) tnum = atoi(type);
- if(tnum==TEX_DIFFUSE) lastmatslot = matslot;
- else if(lastmatslot>=0) matslot = lastmatslot;
- else if(slots.empty()) return;
- Slot &s = matslot>=0 ? materialslots[matslot] : *(tnum!=TEX_DIFFUSE ? slots.last() : slots.add(new Slot(slots.length())));
+ Slot &s = *(tnum!=TEX_DIFFUSE ? slots.last() : slots.add(new Slot(slots.length())));
s.loaded = false;
s.texmask |= 1<<tnum;
if(s.sts.length()>=8) conoutf(CON_WARN, "warning: too many textures in slot %d", slots.length()-1);
if(tnum==TEX_DIFFUSE)
{
setslotshader(s);
- VSlot &vs = matslot >= 0 ? materialslots[matslot] : *emptyvslot(s);
+ VSlot &vs = *emptyvslot(s);
vs.reset();
vs.rotation = clamp(*rot, 0, 7);
vs.offset = ivec2(*xoffset, *yoffset).max(0);
return -1;
}
-static void addglow(ImageData &c, ImageData &g, const vec &glowcolor)
-{
- if(g.bpp < 3) { readwritergbtex(c, g, loopk(3) dst[k] = clamp(int(dst[k]) + int(src[0]*glowcolor[k]), 0, 255); ); }
- else { readwritergbtex(c, g, loopk(3) dst[k] = clamp(int(dst[k]) + int(src[k]*glowcolor[k]), 0, 255); ); }
-}
-
static void mergespec(ImageData &c, ImageData &s)
{
if(s.bpp < 3) { readwritergbatex(c, s, dst[3] = src[0]; ); }
if(t.combined >= 0) continue;
switch(t.type)
{
- case TEX_ENVMAP:
- t.t = cubemapload(t.name);
- break;
-
default:
texcombine(s, i, t, forceload);
break;
return s;
}
-MSlot &lookupmaterialslot(int index, bool load)
-{
- if(materialslots[index].sts.empty() && index&MATF_INDEX) index &= ~MATF_INDEX;
- MSlot &s = materialslots[index];
- if(load && !s.linked)
- {
- if(!s.loaded) loadslot(s, true);
- linkvslotshader(s);
- s.linked = true;
- }
- return s;
-}
-
Slot &lookupslot(int index, bool load)
{
Slot &s = slots.inrange(index) ? *slots[index] : (slots.inrange(DEFAULT_GEOM) ? *slots[DEFAULT_GEOM] : dummyslot);
{
loopv(slots) if(slots[i]->loaded) linkslotshader(*slots[i]);
loopv(vslots) if(vslots[i]->linked) linkvslotshader(*vslots[i]);
- loopi((MATF_VOLUME|MATF_INDEX)+1) if(materialslots[i].loaded)
- {
- linkslotshader(materialslots[i]);
- linkvslotshader(materialslots[i]);
- }
}
Texture *loadthumbnail(Slot &slot)
defformatstring(prefix, "<thumbnail:%.2f/%.2f/%.2f>", vslot.colorscale.x, vslot.colorscale.y, vslot.colorscale.z);
addname(name, slot, slot.sts[0], false, prefix);
}
- int glow = -1;
- if(slot.texmask&(1<<TEX_GLOW))
- {
- loopvj(slot.sts) if(slot.sts[j].type==TEX_GLOW) { glow = j; break; }
- if(glow >= 0)
- {
- defformatstring(prefix, "<glow:%.2f/%.2f/%.2f>", vslot.glowcolor.x, vslot.glowcolor.y, vslot.glowcolor.z);
- addname(name, slot, slot.sts[glow], true, prefix);
- }
- }
VSlot *layer = vslot.layer ? &lookupvslot(vslot.layer, false) : NULL;
if(layer)
{
{
ImageData s, g, l;
texturedata(s, NULL, &slot.sts[0], false);
- if(glow >= 0) texturedata(g, NULL, &slot.sts[glow], false);
if(layer) texturedata(l, NULL, &layer->slot->sts[0], false);
if(!s.data) t = slot.thumbnail = notexture;
else
if(g.data)
{
if(g.w != s.w || g.h != s.h) scaleimage(g, s.w, s.h);
- addglow(s, g, vslot.glowcolor);
}
if(l.data)
{
{
loopv(slots) slots[i]->cleanup();
loopv(vslots) vslots[i]->cleanup();
- loopi((MATF_VOLUME|MATF_INDEX)+1) materialslots[i].cleanup();
enumerate(textures, Texture, tex, cleanuptexture(&tex));
}
if(!texturedata(s, tex.name, NULL, true, &compress) || !newtexture(&tex, NULL, s, tex.clamp, tex.mipmap, false, false, compress)) return false;
break;
}
-
- case Texture::CUBEMAP:
- if(!cubemaploadwildcard(&tex, NULL, tex.mipmap, true)) return false;
- break;
}
return true;
}
{
SHADER_DEFAULT = 0,
SHADER_NORMALSLMS = 1<<0,
- SHADER_ENVMAP = 1<<1,
SHADER_OPTION = 1<<3,
SHADER_INVALID = 1<<8,
TEX_UNKNOWN,
TEX_DECAL,
TEX_NORMAL,
- TEX_GLOW,
TEX_SPEC,
TEX_DEPTH,
- TEX_ALPHA,
- TEX_ENVMAP
+ TEX_ALPHA
};
enum
int layer;
float alphafront, alphaback;
vec colorscale;
- vec glowcolor;
VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0)
{
alphafront = 0.5f;
alphaback = 0;
colorscale = vec(1, 1, 1);
- glowcolor = vec(1, 1, 1);
}
void cleanup()
renderentsphere(e, e.attr2);
break;
- case ET_NOENVMAP:
- break;
-
case ET_MAPMODEL:
case ET_PLAYERSTART:
{
{
clearoverrides();
clearmapsounds();
- resetblendmap();
resetlightmaps();
clearslots();
clearparticles();
if(worldsize > 0x1000) splitocta(worldroot, worldsize>>1);
- enlargeblendmap();
-
allchanged();
return true;
vector<extentity *> &ents = entities::getents();
loopv(ents) ents[i]->o.sub(vec(offset));
- shrinkblendmap(octant);
-
allchanged();
conoutf("shrunk map to size %d", worldscale);
int numents;
int numpvs;
int lightmaps;
- int blendmap;
int numvars;
int numvslots;
};
-struct compatheader // map file format header
-{
- char magic[4]; // "OCTA"
- int version; // any >8bit quantity is little endian
- int headersize; // sizeof(header)
- int worldsize;
- int numents;
- int numpvs;
- int lightmaps;
- int lightprecision, lighterror, lightlod;
- uchar ambient;
- uchar blendmap;
- uchar lerpangle, lerpsubdiv, lerpsubdivsize;
- uchar bumperror;
- uchar reserved[10];
- char maptitle[128];
-};
-
enum
{
MATSURF_NOT_VISIBLE = 0,
lilswap(&hdr.version, 6);
if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; }
- compatheader chdr;
- if(f->read(&hdr.blendmap, sizeof(hdr) - 7*sizeof(int)) != sizeof(hdr) - 7*sizeof(int)) {
- conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false;
- }
- lilswap(&hdr.blendmap, 2);
lilswap(&hdr.numvslots, 1);
loopi(hdr.numvars)
loopv(ents) if(ents[i]->type!=ET_EMPTY || nolms) hdr.numents++;
hdr.numpvs = 0;
hdr.lightmaps = nolms ? 0 : lightmaps.length();
- hdr.blendmap = shouldsaveblendmap();
hdr.numvars = 0;
hdr.numvslots = numvslots;
enumerate(idents, ident, id,
renderprogress(float(i+1)/lightmaps.length(), "saving lightmaps...");
}
}
- if(shouldsaveblendmap()) { renderprogress(0, "saving blendmap..."); saveblendmap(f); }
delete f;
conoutf("wrote map file %s", ogzname);
lilswap(&hdr.version, 6);
if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; }
- compatheader chdr;
- if(f->read(&hdr.blendmap, sizeof(hdr) - 7*sizeof(int)) != sizeof(hdr) - 7*sizeof(int)) {
- conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false;
- }
resetmap();
setvar("mapversion", hdr.version, true, false);
- lilswap(&hdr.blendmap, 2);
lilswap(&hdr.numvslots, 1);
renderprogress(0, "clearing world...");
f->read(lm.data, lm.bpp * LM_PACKW * LM_PACKH);
lm.finalize();
}
-
- if(hdr.blendmap) loadblendmap(f, hdr.blendmap);
}
mapcrc = f->getcrc();
LIGHT = ET_LIGHT, // lightsource, attr1 = radius, attr2 = intensity
MAPMODEL = ET_MAPMODEL, // attr1 = angle, attr2 = idx
PLAYERSTART, // attr1 = angle, attr2 = team
- ENVMAP = ET_NOENVMAP, // attr1 = radius
PARTICLES = ET_PARTICLES,
MAPSOUND = ET_SOUND,
SPOTLIGHT = ET_SPOTLIGHT,
// ET_*: the only static entity types dictated by the engine... rest are gamecode dependent
-enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_NOENVMAP, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC };
+enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC };
struct entity // persistent map entity
{
extern bool moveplayer(physent *pl, int moveres, bool local, int curtime);
extern bool collide(physent *d, const vec &dir = vec(0, 0, 0), float cutoff = 0.0f, bool playercol = true, bool insideplayercol = false);
extern bool bounce(physent *d, float secs, float elasticity, float grav);
-extern bool bounce(physent *d, float elasticity, float float grav);
+extern bool bounce(physent *d, float elasticity, float grav);
extern void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space);
extern bool overlapsdynent(const vec &o, float radius);
extern bool movecamera(physent *pl, const vec &dir, float dist, float stepdist);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <assimp/cimport.h>
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+
+void export_as_obj(const struct aiScene* scene, const char* output_filename) {
+ FILE* file = fopen(output_filename, "w");
+ if (!file) {
+ fprintf(stderr, "Error opening output file: %s\n", output_filename);
+ return;
+ }
+
+ fprintf(file, "# OBJ file exported from MD3 using Assimp\n");
+
+ // Write vertices
+ for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
+ const struct aiMesh* mesh = scene->mMeshes[m];
+ for (unsigned int v = 0; v < mesh->mNumVertices; v++) {
+ fprintf(file, "v %f %f %f\n",
+ mesh->mVertices[v].x,
+ mesh->mVertices[v].y,
+ mesh->mVertices[v].z);
+ }
+ }
+
+ // Write faces (indices)
+ unsigned int vertex_offset = 1; // OBJ indices start at 1
+ for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
+ const struct aiMesh* mesh = scene->mMeshes[m];
+ fprintf(file, "o Mesh_%d\n", m);
+
+ for (unsigned int f = 0; f < mesh->mNumFaces; f++) {
+ const struct aiFace face = mesh->mFaces[f];
+ fprintf(file, "f");
+
+ for (unsigned int i = 0; i < face.mNumIndices; i++) {
+ fprintf(file, " %u", face.mIndices[i] + vertex_offset);
+ }
+
+ fprintf(file, "\n");
+ }
+
+ vertex_offset += mesh->mNumVertices;
+ }
+
+ fclose(file);
+ printf("Successfully exported to: %s\n", output_filename);
+}
+
+int main(int argc, char** argv) {
+ if (argc != 3) {
+ printf("Usage: %s <input.md3> <output.obj>\n", argv[0]);
+ return 1;
+ }
+
+ const char* input_file = argv[1];
+ const char* output_file = argv[2];
+
+ // Import the MD3 file
+ const struct aiScene* scene = aiImportFile(
+ input_file,
+ aiProcess_Triangulate | // Ensure triangles
+ aiProcess_JoinIdenticalVertices // Combine duplicate vertices
+ );
+
+ if (!scene) {
+ fprintf(stderr, "Error loading MD3 file: %s\n", aiGetErrorString());
+ return 1;
+ }
+
+ printf("Successfully loaded MD3 file: %s\n", input_file);
+ printf("Meshes: %u\n", scene->mNumMeshes);
+
+ // Export as OBJ
+ export_as_obj(scene, output_file);
+
+ // Clean up
+ aiReleaseImport(scene);
+
+ return 0;
+}