Merge remote-tracking branch 'origin' into copy_kart_mesh
This commit is contained in:
commit
25e059dd3e
@ -1,19 +1,19 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<challenge version="2">
|
<challenge version="2">
|
||||||
<track id="jungle" laps="3"/>
|
<track id="30_chocolate" laps="3"/>
|
||||||
<mode major="single" minor="quickrace"/>
|
<mode major="single" minor="quickrace"/>
|
||||||
<requirements trophies="15"/>
|
<requirements trophies="15"/>
|
||||||
|
|
||||||
<hard>
|
<hard>
|
||||||
<karts number="5"/>
|
<karts number="5"/>
|
||||||
<requirements position="1" time="155"/>
|
<requirements position="1" time="161"/>
|
||||||
</hard>
|
</hard>
|
||||||
<medium>
|
<medium>
|
||||||
<karts number="4"/>
|
<karts number="4"/>
|
||||||
<requirements time="170"/>
|
<requirements time="177"/>
|
||||||
</medium>
|
</medium>
|
||||||
<easy>
|
<easy>
|
||||||
<karts number="4"/>
|
<karts number="4"/>
|
||||||
<requirements time="230"/>
|
<requirements time="240"/>
|
||||||
</easy>
|
</easy>
|
||||||
</challenge>
|
</challenge>
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
max="1000" />
|
max="1000" />
|
||||||
|
|
||||||
<!-- Size of the particles -->
|
<!-- Size of the particles -->
|
||||||
<size min="0.5"
|
<size min="0.3"
|
||||||
max="0.3"
|
max="0.5"
|
||||||
x-increase-factor="2.6"
|
x-increase-factor="2.6"
|
||||||
y-increase-factor="2.6" />
|
y-increase-factor="2.6" />
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<card is="Intel(R) HD Graphics 3000" os="windows" version="<9.17.11" disable="a b c"/>
|
<card is="Intel(R) HD Graphics 3000" os="windows" version="<9.17.11" disable="a b c"/>
|
||||||
<card contains="NVIDIA" os="windows" version="<344.65" disable="BufferStorage"/>
|
<card contains="NVIDIA" os="windows" version="<344.65" disable="BufferStorage"/>
|
||||||
<card contains="NVIDIA" os="linux" version="<343.22" disable="BufferStorage"/>
|
<card contains="NVIDIA" os="linux" version="<343.22" disable="BufferStorage"/>
|
||||||
|
<card contains="Mesa" os="linux" version="<10.3" disable="BufferStorage"/>
|
||||||
<card is="Intel(R) HD Graphics 3000" os="osx" version="<=9.17.10" disable="a b c"/>
|
<card is="Intel(R) HD Graphics 3000" os="osx" version="<=9.17.10" disable="a b c"/>
|
||||||
<card is="" os="bsd" version="<1.2.3" disable="a b c"/>
|
<card is="" os="bsd" version="<1.2.3" disable="a b c"/>
|
||||||
|
|
||||||
|
@ -2,37 +2,37 @@
|
|||||||
<stkgui>
|
<stkgui>
|
||||||
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
|
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="Red" text="Red"/>
|
<label id="Red" raw_text="Red"/>
|
||||||
<spacer width="25"/>
|
<spacer width="25"/>
|
||||||
<gauge id="red_slider" min_value="0" max_value="100" proportion="1"/>
|
<gauge id="red_slider" min_value="0" max_value="100" proportion="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="Green" text="Green"/>
|
<label id="Green" raw_text="Green"/>
|
||||||
<spacer width="25"/>
|
<spacer width="25"/>
|
||||||
<gauge id="green_slider" min_value="0" max_value="100" proportion="1"/>
|
<gauge id="green_slider" min_value="0" max_value="100" proportion="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="Blue" text="Blue"/>
|
<label id="Blue" raw_text="Blue"/>
|
||||||
<spacer width="25"/>
|
<spacer width="25"/>
|
||||||
<gauge id="blue_slider" min_value="0" max_value="100" proportion="1"/>
|
<gauge id="blue_slider" min_value="0" max_value="100" proportion="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="SSAO radius" text="SSAO Radius"/>
|
<label id="SSAO radius" raw_text="SSAO Radius"/>
|
||||||
<spacer width="50"/>
|
<spacer width="50"/>
|
||||||
<gauge id="ssao_radius" min_value="0" max_value="100" proportion="1" />
|
<gauge id="ssao_radius" min_value="0" max_value="100" proportion="1" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="SSAO k" text="SSAO K"/>
|
<label id="SSAO k" raw_text="SSAO K"/>
|
||||||
<spacer width="25"/>
|
<spacer width="25"/>
|
||||||
<gauge id="ssao_k" min_value="0" max_value="100" proportion="1"/>
|
<gauge id="ssao_k" min_value="0" max_value="100" proportion="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div proportion="1" width="100%" layout="horizontal-row">
|
<div proportion="1" width="100%" layout="horizontal-row">
|
||||||
<label id="SSAO Sigma" text="SSAO sigma"/>
|
<label id="SSAO Sigma" raw_text="SSAO sigma"/>
|
||||||
<spacer width="50"/>
|
<spacer width="50"/>
|
||||||
<gauge id="ssao_sigma" min_value="0" max_value="100" proportion="1"/>
|
<gauge id="ssao_sigma" min_value="0" max_value="100" proportion="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,17 +40,17 @@
|
|||||||
|
|
||||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
|
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
|
||||||
<icon-button id="test_gpwin" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_gpwin" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: GPWin" label_location="hover"/>
|
raw_text="TEST: GPWin" label_location="hover"/>
|
||||||
<icon-button id="test_gplose" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_gplose" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: GPLose" label_location="hover"/>
|
raw_text="TEST: GPLose" label_location="hover"/>
|
||||||
<icon-button id="test_unlocked" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_unlocked" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: Unlocked" label_location="hover"/>
|
raw_text="TEST: Unlocked" label_location="hover"/>
|
||||||
<icon-button id="test_unlocked2" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_unlocked2" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: Unlocked 2" label_location="hover"/>
|
raw_text="TEST: Unlocked 2" label_location="hover"/>
|
||||||
<icon-button id="test_intro" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_intro" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: Intro" label_location="hover"/>
|
raw_text="TEST: Intro" label_location="hover"/>
|
||||||
<icon-button id="test_outro" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="test_outro" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
text="TEST: Outro" label_location="hover"/>
|
raw_text="TEST: Outro" label_location="hover"/>
|
||||||
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||||
I18N="In the main screen" text="Options" label_location="hover"/>
|
I18N="In the main screen" text="Options" label_location="hover"/>
|
||||||
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"
|
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"
|
||||||
|
File diff suppressed because it is too large
Load Diff
26
data/shaders/IBL.frag
Normal file
26
data/shaders/IBL.frag
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
uniform sampler2D ntex;
|
||||||
|
uniform sampler2D dtex;
|
||||||
|
|
||||||
|
out vec4 Diff;
|
||||||
|
out vec4 Spec;
|
||||||
|
|
||||||
|
vec3 DecodeNormal(vec2 n);
|
||||||
|
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||||
|
vec3 DiffuseIBL(vec3 normal);
|
||||||
|
vec3 SpecularIBL(vec3 normal, vec3 V, float roughness);
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 uv = gl_FragCoord.xy / screen;
|
||||||
|
vec3 normal = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
|
||||||
|
|
||||||
|
Diff = vec4(0.25 * DiffuseIBL(normal), 1.);
|
||||||
|
|
||||||
|
float z = texture(dtex, uv).x;
|
||||||
|
|
||||||
|
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
|
||||||
|
vec3 eyedir = -normalize(xpos.xyz);
|
||||||
|
float specval = texture(ntex, uv).z;
|
||||||
|
|
||||||
|
Spec = vec4(.25 * SpecularIBL(normal, eyedir, specval), 1.);
|
||||||
|
}
|
@ -9,7 +9,6 @@ uniform sampler3D SHR;
|
|||||||
uniform sampler3D SHG;
|
uniform sampler3D SHG;
|
||||||
uniform sampler3D SHB;
|
uniform sampler3D SHB;
|
||||||
|
|
||||||
uniform float R_wcs = 10.;
|
|
||||||
uniform vec3 extents;
|
uniform vec3 extents;
|
||||||
uniform mat4 RHMatrix;
|
uniform mat4 RHMatrix;
|
||||||
uniform mat4 InvRHMatrix;
|
uniform mat4 InvRHMatrix;
|
||||||
|
@ -35,7 +35,7 @@ void main(void)
|
|||||||
vec3 eyedir = normalize(xpos.xyz);
|
vec3 eyedir = normalize(xpos.xyz);
|
||||||
|
|
||||||
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
|
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
|
||||||
float fEdotL = max(0., dot(SunDir, eyedir));
|
float fEdotL = clamp(dot(SunDir, eyedir), 0., 1.);
|
||||||
float fPowEdotL = pow(fEdotL, 4.);
|
float fPowEdotL = pow(fEdotL, 4.);
|
||||||
|
|
||||||
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
|
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
|
||||||
|
33
data/shaders/importance_sampling_specular.frag
Normal file
33
data/shaders/importance_sampling_specular.frag
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
uniform samplerCube tex;
|
||||||
|
uniform samplerBuffer samples;
|
||||||
|
uniform float ViewportSize;
|
||||||
|
|
||||||
|
uniform mat4 PermutationMatrix;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 uv = gl_FragCoord.xy / ViewportSize;
|
||||||
|
vec3 RayDir = 2. * vec3(uv, 1.) - 1.;
|
||||||
|
RayDir = normalize((PermutationMatrix * vec4(RayDir, 0.)).xyz);
|
||||||
|
|
||||||
|
vec4 FinalColor = vec4(0.);
|
||||||
|
vec3 up = (RayDir.y < .99) ? vec3(0., 1., 0.) : vec3(0., 0., 1.);
|
||||||
|
vec3 Tangent = normalize(cross(up, RayDir));
|
||||||
|
vec3 Bitangent = cross(RayDir, Tangent);
|
||||||
|
float weight = 0.;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
float Theta = texelFetch(samples, i).r;
|
||||||
|
float Phi = texelFetch(samples, i).g;
|
||||||
|
|
||||||
|
vec3 L = cos(Theta) * RayDir + sin(Theta) * cos(Phi) * Tangent + sin(Theta) * sin(Phi) * Bitangent;
|
||||||
|
float NdotL = clamp(dot(RayDir, L), 0., 1.);
|
||||||
|
FinalColor += textureLod(tex, L, 0.) * NdotL;
|
||||||
|
weight += NdotL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = FinalColor / weight;
|
||||||
|
}
|
@ -41,7 +41,7 @@ void main(void)
|
|||||||
vec3 eyedir = normalize(xpos.xyz);
|
vec3 eyedir = normalize(xpos.xyz);
|
||||||
|
|
||||||
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
|
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
|
||||||
float fEdotL = max(0., dot(SunDir, eyedir));
|
float fEdotL = clamp(dot(SunDir, eyedir), 0., 1.);
|
||||||
float fPowEdotL = pow(fEdotL, 4.);
|
float fPowEdotL = pow(fEdotL, 4.);
|
||||||
|
|
||||||
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
|
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
|
||||||
|
@ -31,5 +31,5 @@ void main()
|
|||||||
|
|
||||||
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
|
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * gloss + 1.);
|
EncodedNormal.z = gloss;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ in vec3 Position;
|
|||||||
in vec3 Normal;
|
in vec3 Normal;
|
||||||
in vec4 Color;
|
in vec4 Color;
|
||||||
in vec2 Texcoord;
|
in vec2 Texcoord;
|
||||||
|
in vec2 SecondTexcoord;
|
||||||
in vec3 Tangent;
|
in vec3 Tangent;
|
||||||
in vec3 Bitangent;
|
in vec3 Bitangent;
|
||||||
|
|
||||||
|
@ -19,5 +19,5 @@ void main(void)
|
|||||||
float glossmap = texture(glosstex, uv).x;
|
float glossmap = texture(glosstex, uv).x;
|
||||||
#endif
|
#endif
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * glossmap + 1.);
|
EncodedNormal.z = glossmap;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,6 @@ void main() {
|
|||||||
if (col.a < 0.5)
|
if (col.a < 0.5)
|
||||||
discard;
|
discard;
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * glossmap + 1.);
|
EncodedNormal.z = glossmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,5 +25,5 @@ void main()
|
|||||||
|
|
||||||
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
|
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * (1. - alpha) + 1.);
|
EncodedNormal.z = 1. - alpha;
|
||||||
}
|
}
|
||||||
|
@ -19,5 +19,5 @@ void main(void)
|
|||||||
{
|
{
|
||||||
float glossmap = texture(tex, uv).x;
|
float glossmap = texture(tex, uv).x;
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * glossmap + 1.);
|
EncodedNormal.z = glossmap;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,6 @@ void main() {
|
|||||||
discard;
|
discard;
|
||||||
float glossmap = texture(glosstex, uv).x;
|
float glossmap = texture(glosstex, uv).x;
|
||||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
|
||||||
EncodedNormal.z = exp2(10. * glossmap + 1.);
|
EncodedNormal.z = glossmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ out vec4 Diffuse;
|
|||||||
out vec4 Specular;
|
out vec4 Specular;
|
||||||
|
|
||||||
vec3 DecodeNormal(vec2 n);
|
vec3 DecodeNormal(vec2 n);
|
||||||
vec3 getSpecular(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
||||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -35,8 +35,8 @@ void main()
|
|||||||
// Light Direction
|
// Light Direction
|
||||||
vec3 L = -normalize(xpos.xyz - light_pos);
|
vec3 L = -normalize(xpos.xyz - light_pos);
|
||||||
|
|
||||||
float NdotL = max(0., dot(norm, L));
|
float NdotL = clamp(dot(norm, L), 0., 1.);
|
||||||
|
|
||||||
Diffuse = vec4(NdotL * light_col * att, 1.);
|
Diffuse = vec4(NdotL * light_col * att, 1.);
|
||||||
Specular = vec4(getSpecular(norm, eyedir, L, light_col, roughness) * NdotL * att, 1.);
|
Specular = vec4(SpecularBRDF(norm, eyedir, L, light_col, roughness) * NdotL * att, 1.);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ out vec4 Diff;
|
|||||||
out vec4 Spec;
|
out vec4 Spec;
|
||||||
|
|
||||||
vec3 DecodeNormal(vec2 n);
|
vec3 DecodeNormal(vec2 n);
|
||||||
vec3 getSpecular(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
||||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||||
|
|
||||||
vec3 getMostRepresentativePoint(vec3 direction, vec3 R, float angularRadius)
|
vec3 getMostRepresentativePoint(vec3 direction, vec3 R, float angularRadius)
|
||||||
@ -46,13 +46,13 @@ void main() {
|
|||||||
// Normalized on the cpu
|
// Normalized on the cpu
|
||||||
vec3 L = direction;
|
vec3 L = direction;
|
||||||
|
|
||||||
float NdotL = max(0., dot(norm, L));
|
float NdotL = clamp(dot(norm, L), 0., 1.);
|
||||||
|
|
||||||
float angle = 3.14 * sunangle / 180.;
|
float angle = 3.14 * sunangle / 180.;
|
||||||
vec3 R = reflect(-eyedir, norm);
|
vec3 R = reflect(-eyedir, norm);
|
||||||
vec3 Lightdir = getMostRepresentativePoint(direction, R, angle);
|
vec3 Lightdir = getMostRepresentativePoint(direction, R, angle);
|
||||||
|
|
||||||
vec3 Specular = getSpecular(norm, eyedir, Lightdir, col, roughness) * NdotL;
|
vec3 Specular = SpecularBRDF(norm, eyedir, Lightdir, col, roughness) * NdotL;
|
||||||
|
|
||||||
vec3 outcol = NdotL * col;
|
vec3 outcol = NdotL * col;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ out vec4 Diff;
|
|||||||
out vec4 Spec;
|
out vec4 Spec;
|
||||||
|
|
||||||
vec3 DecodeNormal(vec2 n);
|
vec3 DecodeNormal(vec2 n);
|
||||||
vec3 getSpecular(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
||||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||||
|
|
||||||
vec3 getMostRepresentativePoint(vec3 direction, vec3 R, float angularRadius)
|
vec3 getMostRepresentativePoint(vec3 direction, vec3 R, float angularRadius)
|
||||||
@ -60,13 +60,13 @@ void main() {
|
|||||||
// Normalized on the cpu
|
// Normalized on the cpu
|
||||||
vec3 L = direction;
|
vec3 L = direction;
|
||||||
|
|
||||||
float NdotL = max(0., dot(norm, L));
|
float NdotL = clamp(dot(norm, L), 0., 1.);
|
||||||
|
|
||||||
float angle = 3.14 * sunangle / 180.;
|
float angle = 3.14 * sunangle / 180.;
|
||||||
vec3 R = reflect(-eyedir, norm);
|
vec3 R = reflect(-eyedir, norm);
|
||||||
vec3 Lightdir = getMostRepresentativePoint(direction, R, angle);
|
vec3 Lightdir = getMostRepresentativePoint(direction, R, angle);
|
||||||
|
|
||||||
vec3 Specular = getSpecular(norm, eyedir, Lightdir, col, roughness) * NdotL;
|
vec3 Specular = SpecularBRDF(norm, eyedir, Lightdir, col, roughness) * NdotL;
|
||||||
|
|
||||||
|
|
||||||
vec3 outcol = NdotL * col;
|
vec3 outcol = NdotL * col;
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
// From http://www.ceng.metu.edu.tr/~akyuz/files/hdrgpu.pdf
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform sampler2D logluminancetex;
|
|
||||||
uniform float exposure = .09;
|
|
||||||
uniform float Lwhite = 1.;
|
|
||||||
uniform float vignette_weight;
|
uniform float vignette_weight;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
@ -11,25 +6,10 @@ out vec4 FragColor;
|
|||||||
vec3 getCIEYxy(vec3 rgbColor);
|
vec3 getCIEYxy(vec3 rgbColor);
|
||||||
vec3 getRGBFromCIEXxy(vec3 YxyColor);
|
vec3 getRGBFromCIEXxy(vec3 YxyColor);
|
||||||
|
|
||||||
|
|
||||||
float delta = .0001;
|
|
||||||
float saturation = 1.;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 uv = gl_FragCoord.xy / screen;
|
vec2 uv = gl_FragCoord.xy / screen;
|
||||||
vec4 col = texture(tex, uv);
|
vec4 col = texture(tex, uv);
|
||||||
float avgLw = textureLod(logluminancetex, uv, 10.).x;
|
|
||||||
avgLw = max(exp(avgLw) - delta, delta);
|
|
||||||
|
|
||||||
vec3 Cw = getCIEYxy(col.xyz);
|
|
||||||
float Lw = Cw.y;
|
|
||||||
|
|
||||||
/* Reinhard, for reference */
|
|
||||||
// float L = Lw * exposure / avgLw;
|
|
||||||
// float Ld = L * (1. + L / (Lwhite * Lwhite));
|
|
||||||
// Ld /= (1. + L);
|
|
||||||
// FragColor = vec4(Ld * pow(col.xyz / Lw, vec3(saturation)), 1.);
|
|
||||||
|
|
||||||
// Uncharted2 tonemap with Auria's custom coefficients
|
// Uncharted2 tonemap with Auria's custom coefficients
|
||||||
vec4 perChannel = (col * (6.9 * col + .5)) / (col * (5.2 * col + 1.7) + 0.06);
|
vec4 perChannel = (col * (6.9 * col + .5)) / (col * (5.2 * col + 1.7) + 0.06);
|
||||||
@ -38,7 +18,6 @@ void main()
|
|||||||
vec2 inside = uv - 0.5;
|
vec2 inside = uv - 0.5;
|
||||||
float vignette = 1. - dot(inside, inside) * vignette_weight;
|
float vignette = 1. - dot(inside, inside) * vignette_weight;
|
||||||
vignette = clamp(pow(vignette, 0.8), 0., 1.);
|
vignette = clamp(pow(vignette, 0.8), 0., 1.);
|
||||||
//vignette = clamp(vignette + vignette - 0.5, 0., 1.15);
|
|
||||||
|
|
||||||
FragColor = vec4(perChannel.xyz * vignette, col.a);
|
FragColor = vec4(perChannel.xyz * vignette, col.a);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
|
// From "An Efficient Representation for Irradiance Environment Maps" article
|
||||||
|
// See http://graphics.stanford.edu/papers/envmap/
|
||||||
|
|
||||||
|
// Coefficients are calculated in IBL.cpp
|
||||||
uniform float blueLmn[9];
|
uniform float blueLmn[9];
|
||||||
uniform float greenLmn[9];
|
uniform float greenLmn[9];
|
||||||
uniform float redLmn[9];
|
uniform float redLmn[9];
|
||||||
uniform sampler2D ntex;
|
|
||||||
uniform sampler2D dtex;
|
|
||||||
uniform samplerCube tex;
|
|
||||||
uniform mat4 TransposeViewMatrix;
|
uniform mat4 TransposeViewMatrix;
|
||||||
|
|
||||||
out vec4 Diff;
|
|
||||||
out vec4 Spec;
|
|
||||||
|
|
||||||
vec3 DecodeNormal(vec2 n);
|
|
||||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
|
||||||
|
|
||||||
mat4 getMatrix(float L[9])
|
mat4 getMatrix(float L[9])
|
||||||
{
|
{
|
||||||
float c1 = 0.429043, c2 = 0.511664, c3 = 0.743125, c4 = 0.886227, c5 = 0.247708;
|
float c1 = 0.429043, c2 = 0.511664, c3 = 0.743125, c4 = 0.886227, c5 = 0.247708;
|
||||||
@ -24,11 +19,8 @@ mat4 getMatrix(float L[9])
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
vec3 DiffuseIBL(vec3 normal)
|
||||||
{
|
{
|
||||||
vec2 uv = gl_FragCoord.xy / screen;
|
|
||||||
vec3 normal = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
|
|
||||||
|
|
||||||
// Convert normal in world space (where SH coordinates were computed)
|
// Convert normal in world space (where SH coordinates were computed)
|
||||||
vec4 extendednormal = TransposeViewMatrix * vec4(normal, 0.);
|
vec4 extendednormal = TransposeViewMatrix * vec4(normal, 0.);
|
||||||
extendednormal.w = 1.;
|
extendednormal.w = 1.;
|
||||||
@ -40,19 +32,5 @@ void main(void)
|
|||||||
float g = dot(extendednormal, gmat * extendednormal);
|
float g = dot(extendednormal, gmat * extendednormal);
|
||||||
float b = dot(extendednormal, bmat * extendednormal);
|
float b = dot(extendednormal, bmat * extendednormal);
|
||||||
|
|
||||||
Diff = max(0.25 * vec4(r, g, b, .1), vec4(0.));
|
return max(vec3(r, g, b), vec3(0.));
|
||||||
|
}
|
||||||
float z = texture(dtex, uv).x;
|
|
||||||
|
|
||||||
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
|
|
||||||
vec3 eyedir = -normalize(xpos.xyz);
|
|
||||||
vec3 sampleDirection = reflect(-eyedir, normal);
|
|
||||||
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
|
|
||||||
|
|
||||||
float specval = texture(ntex, uv).z;
|
|
||||||
// From http://graphics.cs.williams.edu/papers/EnvMipReport2013/
|
|
||||||
int texSize = textureSize(tex, 0).x;
|
|
||||||
float lodval = clamp(log2(texSize * sqrt(3.)) - .5 * log2(specval + 1.), 0., 10.);
|
|
||||||
vec4 specular = textureLod(tex, sampleDirection, lodval);
|
|
||||||
Spec = max(specular, vec4(0.));
|
|
||||||
}
|
|
11
data/shaders/utils/SpecularBRDF.frag
Normal file
11
data/shaders/utils/SpecularBRDF.frag
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Blinn Phong with emulated fresnel factor
|
||||||
|
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness)
|
||||||
|
{
|
||||||
|
float exponentroughness = exp2(10. * roughness + 1.);
|
||||||
|
// Half Light View direction
|
||||||
|
vec3 H = normalize(eyedir + lightdir);
|
||||||
|
float NdotH = clamp(dot(normal, H), 0., 1.);
|
||||||
|
float normalisationFactor = (exponentroughness + 2.) / 8.;
|
||||||
|
vec3 FresnelSchlick = color + (1.0f - color) * pow(1.0f - clamp(dot(eyedir, H), 0., 1.), 5);
|
||||||
|
return max(pow(NdotH, exponentroughness) * FresnelSchlick * normalisationFactor, vec3(0.));
|
||||||
|
}
|
11
data/shaders/utils/SpecularIBL.frag
Normal file
11
data/shaders/utils/SpecularIBL.frag
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
uniform samplerCube probe;
|
||||||
|
|
||||||
|
vec3 SpecularIBL(vec3 normal, vec3 V, float roughness)
|
||||||
|
{
|
||||||
|
vec3 sampleDirection = reflect(-V, normal);
|
||||||
|
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
|
||||||
|
|
||||||
|
// Assume 8 level of lod (ie 256x256 texture)
|
||||||
|
float lodval = 8. * (1. - roughness);
|
||||||
|
return textureLod(probe, sampleDirection, lodval).rgb;
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
vec3 getSpecular(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness)
|
|
||||||
{
|
|
||||||
// Half Light View direction
|
|
||||||
vec3 H = normalize(eyedir + lightdir);
|
|
||||||
float NdotH = max(0., dot(normal, H));
|
|
||||||
float normalisationFactor = (roughness + 2.) / 8.;
|
|
||||||
vec3 FresnelSchlick = color + (1.0f - color) * pow(1.0f - max(0., (dot(eyedir, H))), 5);
|
|
||||||
return max(pow(NdotH, roughness) * FresnelSchlick * normalisationFactor, vec3(0.));
|
|
||||||
}
|
|
@ -1581,6 +1581,20 @@ void CIrrDeviceWin32::getWindowsVersion(core::stringc& out)
|
|||||||
else
|
else
|
||||||
out.append("Microsoft Windows Server 2008 R2 ");
|
out.append("Microsoft Windows Server 2008 R2 ");
|
||||||
}
|
}
|
||||||
|
else if (osvi.dwMinorVersion == 2)
|
||||||
|
{
|
||||||
|
if (osvi.wProductType == VER_NT_WORKSTATION)
|
||||||
|
out.append("Microsoft Windows 8 ");
|
||||||
|
else
|
||||||
|
out.append("Microsoft Windows Server 2012 ");
|
||||||
|
}
|
||||||
|
else if (osvi.dwMinorVersion == 3)
|
||||||
|
{
|
||||||
|
if (osvi.wProductType == VER_NT_WORKSTATION)
|
||||||
|
out.append("Microsoft Windows 8.1 ");
|
||||||
|
else
|
||||||
|
out.append("Microsoft Windows Server 2012 R2 ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bOsVersionInfoEx)
|
if (bOsVersionInfoEx)
|
||||||
|
@ -236,7 +236,7 @@ local gzFile gz_open(path, fd, mode)
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
fd == -2 ? _wopen(path, oflag, 0666) :
|
fd == -2 ? _wopen(path, oflag, 0666) :
|
||||||
#endif
|
#endif
|
||||||
open(path, oflag, 0666));
|
_open(path, oflag, 0666));
|
||||||
if (state->fd == -1) {
|
if (state->fd == -1) {
|
||||||
free(state->path);
|
free(state->path);
|
||||||
free(state);
|
free(state);
|
||||||
|
@ -27,7 +27,7 @@ local int gz_load(state, buf, len, have)
|
|||||||
|
|
||||||
*have = 0;
|
*have = 0;
|
||||||
do {
|
do {
|
||||||
ret = read(state->fd, buf + *have, len - *have);
|
ret = _read(state->fd, buf + *have, len - *have);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
*have += ret;
|
*have += ret;
|
||||||
@ -583,7 +583,7 @@ int ZEXPORT gzclose_r(file)
|
|||||||
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
||||||
gz_error(state, Z_OK, NULL);
|
gz_error(state, Z_OK, NULL);
|
||||||
free(state->path);
|
free(state->path);
|
||||||
ret = close(state->fd);
|
ret = _close(state->fd);
|
||||||
free(state);
|
free(state);
|
||||||
return ret ? Z_ERRNO : err;
|
return ret ? Z_ERRNO : err;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ local int gz_comp(state, flush)
|
|||||||
|
|
||||||
/* write directly if requested */
|
/* write directly if requested */
|
||||||
if (state->direct) {
|
if (state->direct) {
|
||||||
got = write(state->fd, strm->next_in, strm->avail_in);
|
got = _write(state->fd, strm->next_in, strm->avail_in);
|
||||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
if (got < 0 || (unsigned)got != strm->avail_in) {
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
gz_error(state, Z_ERRNO, zstrerror());
|
||||||
return -1;
|
return -1;
|
||||||
@ -98,7 +98,7 @@ local int gz_comp(state, flush)
|
|||||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||||
have = (unsigned)(strm->next_out - state->x.next);
|
have = (unsigned)(strm->next_out - state->x.next);
|
||||||
if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
|
if (have && ((got = _write(state->fd, state->x.next, have)) < 0 ||
|
||||||
(unsigned)got != have)) {
|
(unsigned)got != have)) {
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
gz_error(state, Z_ERRNO, zstrerror());
|
||||||
return -1;
|
return -1;
|
||||||
@ -558,7 +558,7 @@ int ZEXPORT gzclose_w(file)
|
|||||||
}
|
}
|
||||||
gz_error(state, Z_OK, NULL);
|
gz_error(state, Z_OK, NULL);
|
||||||
free(state->path);
|
free(state->path);
|
||||||
if (close(state->fd) == -1)
|
if (_close(state->fd) == -1)
|
||||||
ret = Z_ERRNO;
|
ret = Z_ERRNO;
|
||||||
free(state);
|
free(state);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -466,7 +466,6 @@ bool AddonsManager::anyAddonsInstalled() const
|
|||||||
*/
|
*/
|
||||||
bool AddonsManager::install(const Addon &addon)
|
bool AddonsManager::install(const Addon &addon)
|
||||||
{
|
{
|
||||||
bool success=true;
|
|
||||||
file_manager->checkAndCreateDirForAddons(addon.getDataDir());
|
file_manager->checkAndCreateDirForAddons(addon.getDataDir());
|
||||||
|
|
||||||
//extract the zip in the addons folder called like the addons name
|
//extract the zip in the addons folder called like the addons name
|
||||||
@ -474,7 +473,7 @@ bool AddonsManager::install(const Addon &addon)
|
|||||||
std::string from = file_manager->getAddonsFile("tmp/"+base_name);
|
std::string from = file_manager->getAddonsFile("tmp/"+base_name);
|
||||||
std::string to = addon.getDataDir();
|
std::string to = addon.getDataDir();
|
||||||
|
|
||||||
success = extract_zip(from, to);
|
bool success = extract_zip(from, to);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
// TODO: show a message in the interface
|
// TODO: show a message in the interface
|
||||||
|
@ -235,6 +235,7 @@ void determineOSVersion()
|
|||||||
case 0x0600: m_os_version="Windows Vista"; break;
|
case 0x0600: m_os_version="Windows Vista"; break;
|
||||||
case 0x0601: m_os_version="Windows 7"; break;
|
case 0x0601: m_os_version="Windows 7"; break;
|
||||||
case 0x0602: m_os_version="Windows 8"; break;
|
case 0x0602: m_os_version="Windows 8"; break;
|
||||||
|
case 0x0603: m_os_version="Windows 8_1"; break;
|
||||||
default: {
|
default: {
|
||||||
m_os_version = StringUtils::insertValues("Windows %d",
|
m_os_version = StringUtils::insertValues("Windows %d",
|
||||||
windows_version);
|
windows_version);
|
||||||
|
@ -749,8 +749,9 @@ namespace UserConfigParams
|
|||||||
PARAM_PREFIX BoolUserConfigParam m_always_show_login_screen
|
PARAM_PREFIX BoolUserConfigParam m_always_show_login_screen
|
||||||
PARAM_DEFAULT( BoolUserConfigParam(false, "always_show_login_screen",
|
PARAM_DEFAULT( BoolUserConfigParam(false, "always_show_login_screen",
|
||||||
"Always show the login screen even if last player's session was saved."));
|
"Always show the login screen even if last player's session was saved."));
|
||||||
// ---- Online gameplay related
|
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Online gameplay related
|
||||||
PARAM_PREFIX GroupUserConfigParam m_online_group
|
PARAM_PREFIX GroupUserConfigParam m_online_group
|
||||||
PARAM_DEFAULT( GroupUserConfigParam("OnlinePlay",
|
PARAM_DEFAULT( GroupUserConfigParam("OnlinePlay",
|
||||||
"Everything related to online play.") );
|
"Everything related to online play.") );
|
||||||
@ -767,6 +768,12 @@ namespace UserConfigParams
|
|||||||
&m_online_group,
|
&m_online_group,
|
||||||
"Version of the server API to use."));
|
"Version of the server API to use."));
|
||||||
|
|
||||||
|
PARAM_PREFIX BoolUserConfigParam m_verify_peer
|
||||||
|
PARAM_DEFAULT(BoolUserConfigParam(1, "verify-peer", &m_online_group,
|
||||||
|
"If curl should check peer address. Should always be enabled,"
|
||||||
|
"unless there are authentication problems."));
|
||||||
|
|
||||||
|
|
||||||
// ---- Addon server related entries
|
// ---- Addon server related entries
|
||||||
PARAM_PREFIX GroupUserConfigParam m_addon_group
|
PARAM_PREFIX GroupUserConfigParam m_addon_group
|
||||||
PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews",
|
PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews",
|
||||||
|
334
src/graphics/IBL.cpp
Normal file
334
src/graphics/IBL.cpp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
#include "IBL.hpp"
|
||||||
|
#include "gl_headers.hpp"
|
||||||
|
#include "shaders.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z)
|
||||||
|
{
|
||||||
|
switch (face)
|
||||||
|
{
|
||||||
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||||
|
x = 1.;
|
||||||
|
y = -i;
|
||||||
|
z = -j;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||||
|
x = -1.;
|
||||||
|
y = -i;
|
||||||
|
z = j;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||||
|
x = j;
|
||||||
|
y = 1.;
|
||||||
|
z = i;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||||
|
x = j;
|
||||||
|
y = -1;
|
||||||
|
z = -i;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||||
|
x = j;
|
||||||
|
y = -i;
|
||||||
|
z = 1;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||||
|
x = -j;
|
||||||
|
y = -i;
|
||||||
|
z = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm = sqrt(x * x + y * y + z * z);
|
||||||
|
x /= norm, y /= norm, z /= norm;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void getYml(GLenum face, size_t edge_size,
|
||||||
|
float *Y00,
|
||||||
|
float *Y1minus1, float *Y10, float *Y11,
|
||||||
|
float *Y2minus2, float *Y2minus1, float *Y20, float *Y21, float *Y22)
|
||||||
|
{
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int i = 0; i < int(edge_size); i++)
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < edge_size; j++)
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
float fi = float(i), fj = float(j);
|
||||||
|
fi /= edge_size, fj /= edge_size;
|
||||||
|
fi = 2 * fi - 1, fj = 2 * fj - 1;
|
||||||
|
getXYZ(face, fi, fj, x, y, z);
|
||||||
|
|
||||||
|
// constant part of Ylm
|
||||||
|
float c00 = 0.282095f;
|
||||||
|
float c1minus1 = 0.488603f;
|
||||||
|
float c10 = 0.488603f;
|
||||||
|
float c11 = 0.488603f;
|
||||||
|
float c2minus2 = 1.092548f;
|
||||||
|
float c2minus1 = 1.092548f;
|
||||||
|
float c21 = 1.092548f;
|
||||||
|
float c20 = 0.315392f;
|
||||||
|
float c22 = 0.546274f;
|
||||||
|
|
||||||
|
size_t idx = i * edge_size + j;
|
||||||
|
|
||||||
|
Y00[idx] = c00;
|
||||||
|
Y1minus1[idx] = c1minus1 * y;
|
||||||
|
Y10[idx] = c10 * z;
|
||||||
|
Y11[idx] = c11 * x;
|
||||||
|
Y2minus2[idx] = c2minus2 * x * y;
|
||||||
|
Y2minus1[idx] = c2minus1 * y * z;
|
||||||
|
Y21[idx] = c21 * x * z;
|
||||||
|
Y20[idx] = c20 * (3 * z * z - 1);
|
||||||
|
Y22[idx] = c22 * (x * x - y * y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void projectSH(Color *CubemapFace[6], size_t edge_size,
|
||||||
|
float *Y00[],
|
||||||
|
float *Y1minus1[], float *Y10[], float *Y11[],
|
||||||
|
float *Y2minus2[], float *Y2minus1[], float * Y20[], float *Y21[], float *Y22[],
|
||||||
|
float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
blueSHCoeff[i] = 0;
|
||||||
|
greenSHCoeff[i] = 0;
|
||||||
|
redSHCoeff[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float wh = float(edge_size * edge_size);
|
||||||
|
for (unsigned face = 0; face < 6; face++)
|
||||||
|
{
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int i = 0; i < int(edge_size); i++)
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < edge_size; j++)
|
||||||
|
{
|
||||||
|
int idx = i * edge_size + j;
|
||||||
|
float fi = float(i), fj = float(j);
|
||||||
|
fi /= edge_size, fj /= edge_size;
|
||||||
|
fi = 2 * fi - 1, fj = 2 * fj - 1;
|
||||||
|
|
||||||
|
|
||||||
|
float d = sqrt(fi * fi + fj * fj + 1);
|
||||||
|
|
||||||
|
// Constant obtained by projecting unprojected ref values
|
||||||
|
float solidangle = 2.75f / (wh * pow(d, 1.5f));
|
||||||
|
// pow(., 2.2) to convert from srgb
|
||||||
|
float b = CubemapFace[face][edge_size * i + j].Blue;
|
||||||
|
float g = CubemapFace[face][edge_size * i + j].Green;
|
||||||
|
float r = CubemapFace[face][edge_size * i + j].Red;
|
||||||
|
|
||||||
|
blueSHCoeff[0] += b * Y00[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[1] += b * Y1minus1[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[2] += b * Y10[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[3] += b * Y11[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[4] += b * Y2minus2[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[5] += b * Y2minus1[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[6] += b * Y20[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[7] += b * Y21[face][idx] * solidangle;
|
||||||
|
blueSHCoeff[8] += b * Y22[face][idx] * solidangle;
|
||||||
|
|
||||||
|
greenSHCoeff[0] += g * Y00[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[1] += g * Y1minus1[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[2] += g * Y10[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[3] += g * Y11[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[4] += g * Y2minus2[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[5] += g * Y2minus1[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[6] += g * Y20[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[7] += g * Y21[face][idx] * solidangle;
|
||||||
|
greenSHCoeff[8] += g * Y22[face][idx] * solidangle;
|
||||||
|
|
||||||
|
|
||||||
|
redSHCoeff[0] += r * Y00[face][idx] * solidangle;
|
||||||
|
redSHCoeff[1] += r * Y1minus1[face][idx] * solidangle;
|
||||||
|
redSHCoeff[2] += r * Y10[face][idx] * solidangle;
|
||||||
|
redSHCoeff[3] += r * Y11[face][idx] * solidangle;
|
||||||
|
redSHCoeff[4] += r * Y2minus2[face][idx] * solidangle;
|
||||||
|
redSHCoeff[5] += r * Y2minus1[face][idx] * solidangle;
|
||||||
|
redSHCoeff[6] += r * Y20[face][idx] * solidangle;
|
||||||
|
redSHCoeff[7] += r * Y21[face][idx] * solidangle;
|
||||||
|
redSHCoeff[8] += r * Y22[face][idx] * solidangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SphericalHarmonics(Color *CubemapFace[6], size_t edge_size, float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff)
|
||||||
|
{
|
||||||
|
float *Y00[6];
|
||||||
|
float *Y1minus1[6];
|
||||||
|
float *Y10[6];
|
||||||
|
float *Y11[6];
|
||||||
|
float *Y2minus2[6];
|
||||||
|
float *Y2minus1[6];
|
||||||
|
float *Y20[6];
|
||||||
|
float *Y21[6];
|
||||||
|
float *Y22[6];
|
||||||
|
|
||||||
|
for (unsigned face = 0; face < 6; face++)
|
||||||
|
{
|
||||||
|
Y00[face] = new float[edge_size * edge_size];
|
||||||
|
Y1minus1[face] = new float[edge_size * edge_size];
|
||||||
|
Y10[face] = new float[edge_size * edge_size];
|
||||||
|
Y11[face] = new float[edge_size * edge_size];
|
||||||
|
Y2minus2[face] = new float[edge_size * edge_size];
|
||||||
|
Y2minus1[face] = new float[edge_size * edge_size];
|
||||||
|
Y20[face] = new float[edge_size * edge_size];
|
||||||
|
Y21[face] = new float[edge_size * edge_size];
|
||||||
|
Y22[face] = new float[edge_size * edge_size];
|
||||||
|
|
||||||
|
getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, edge_size, Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]);
|
||||||
|
}
|
||||||
|
|
||||||
|
projectSH(CubemapFace, edge_size,
|
||||||
|
Y00,
|
||||||
|
Y1minus1, Y10, Y11,
|
||||||
|
Y2minus2, Y2minus1, Y20, Y21, Y22,
|
||||||
|
blueSHCoeff, greenSHCoeff, redSHCoeff
|
||||||
|
);
|
||||||
|
|
||||||
|
for (unsigned face = 0; face < 6; face++)
|
||||||
|
{
|
||||||
|
delete[] Y00[face];
|
||||||
|
delete[] Y1minus1[face];
|
||||||
|
delete[] Y10[face];
|
||||||
|
delete[] Y11[face];
|
||||||
|
delete[] Y2minus2[face];
|
||||||
|
delete[] Y2minus1[face];
|
||||||
|
delete[] Y20[face];
|
||||||
|
delete[] Y21[face];
|
||||||
|
delete[] Y22[face];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html
|
||||||
|
/** Returns the index-th pair from Hammersley set of pseudo random set.
|
||||||
|
Hammersley set is a uniform distribution between 0 and 1 for 2 components.
|
||||||
|
We use the natural indexation on the set to avoid storing the whole set.
|
||||||
|
\param index of the pair
|
||||||
|
\param size of the set. */
|
||||||
|
std::pair<float, float> HammersleySequence(int index, int samples)
|
||||||
|
{
|
||||||
|
float InvertedBinaryRepresentation = 0.;
|
||||||
|
for (size_t i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
InvertedBinaryRepresentation += ((index >> i) & 0x1) * powf(.5, (float) (i + 1.));
|
||||||
|
}
|
||||||
|
return std::make_pair(float(index) / float(samples), InvertedBinaryRepresentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns a pseudo random (theta, phi) generated from a probability density function modeled after Phong function.
|
||||||
|
\param a pseudo random float pair from a uniform density function between 0 and 1.
|
||||||
|
\param exponent from the Phong formula. */
|
||||||
|
std::pair<float, float> ImportanceSamplingPhong(std::pair<float, float> Seeds, float exponent)
|
||||||
|
{
|
||||||
|
return std::make_pair(acosf(powf(Seeds.first, 1.f / (exponent + 1.f))), 2.f * 3.14f * Seeds.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
core::matrix4 getPermutationMatrix(size_t indexX, float valX, size_t indexY, float valY, size_t indexZ, float valZ)
|
||||||
|
{
|
||||||
|
core::matrix4 resultMat;
|
||||||
|
float *M = resultMat.pointer();
|
||||||
|
memset(M, 0, 16 * sizeof(float));
|
||||||
|
assert(indexX < 4);
|
||||||
|
assert(indexY < 4);
|
||||||
|
assert(indexZ < 4);
|
||||||
|
M[indexX] = valX;
|
||||||
|
M[4 + indexY] = valY;
|
||||||
|
M[8 + indexZ] = valZ;
|
||||||
|
return resultMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint generateSpecularCubemap(GLuint probe)
|
||||||
|
{
|
||||||
|
GLuint cubemap_texture;
|
||||||
|
|
||||||
|
glGenTextures(1, &cubemap_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap_texture);
|
||||||
|
size_t cubemap_size = 256;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, cubemap_size, cubemap_size, 0, GL_BGRA, GL_FLOAT, 0);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||||
|
|
||||||
|
GLuint fbo;
|
||||||
|
glGenFramebuffers(1, &fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
glViewport(0, 0, cubemap_size, cubemap_size);
|
||||||
|
GLenum bufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glDrawBuffers(1, bufs);
|
||||||
|
glUseProgram(UtilShader::SpecularIBLGenerator::getInstance()->Program);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
core::matrix4 M[6] = {
|
||||||
|
getPermutationMatrix(2, -1., 1, -1., 0, 1.),
|
||||||
|
getPermutationMatrix(2, 1., 1, -1., 0, -1.),
|
||||||
|
getPermutationMatrix(0, 1., 2, 1., 1, 1.),
|
||||||
|
getPermutationMatrix(0, 1., 2, -1., 1, -1.),
|
||||||
|
getPermutationMatrix(0, 1., 1, -1., 2, 1.),
|
||||||
|
getPermutationMatrix(0, -1., 1, -1., 2, -1.),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned level = 0; level < 8; level++)
|
||||||
|
{
|
||||||
|
// Blinn Phong can be approximated by Phong with 4x the specular coefficient
|
||||||
|
// See http://seblagarde.wordpress.com/2012/03/29/relationship-between-phong-and-blinn-lighting-model/
|
||||||
|
// NOTE : Removed because it makes too sharp reflexion
|
||||||
|
float roughness = (8 - level) * pow(2.f, 10.f) / 8.f;
|
||||||
|
float viewportSize = float(1 << (8 - level));
|
||||||
|
|
||||||
|
float *tmp = new float[2048];
|
||||||
|
for (unsigned i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
std::pair<float, float> sample = ImportanceSamplingPhong(HammersleySequence(i, 1024), roughness);
|
||||||
|
tmp[2 * i] = sample.first;
|
||||||
|
tmp[2 * i + 1] = sample.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glActiveTexture(GL_TEXTURE0 + UtilShader::SpecularIBLGenerator::getInstance()->TU_Samples);
|
||||||
|
GLuint sampleTex, sampleBuffer;
|
||||||
|
glGenBuffers(1, &sampleBuffer);
|
||||||
|
glBindBuffer(GL_TEXTURE_BUFFER, sampleBuffer);
|
||||||
|
glBufferData(GL_TEXTURE_BUFFER, 2048 * sizeof(float), tmp, GL_STATIC_DRAW);
|
||||||
|
glGenTextures(1, &sampleTex);
|
||||||
|
glBindTexture(GL_TEXTURE_BUFFER, sampleTex);
|
||||||
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, sampleBuffer);
|
||||||
|
glBindVertexArray(SharedObject::FullScreenQuadVAO);
|
||||||
|
|
||||||
|
for (unsigned face = 0; face < 6; face++)
|
||||||
|
{
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap_texture, level);
|
||||||
|
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
assert(status == GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
|
||||||
|
UtilShader::SpecularIBLGenerator::getInstance()->SetTextureUnits(probe);
|
||||||
|
UtilShader::SpecularIBLGenerator::getInstance()->setUniforms(M[face], viewportSize);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
glActiveTexture(GL_TEXTURE0 + UtilShader::SpecularIBLGenerator::getInstance()->TU_Samples);
|
||||||
|
glBindBuffer(GL_TEXTURE_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||||
|
|
||||||
|
delete[] tmp;
|
||||||
|
glDeleteTextures(1, &sampleTex);
|
||||||
|
glDeleteBuffers(1, &sampleBuffer);
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glDeleteFramebuffers(1, &fbo);
|
||||||
|
return cubemap_texture;
|
||||||
|
}
|
21
src/graphics/IBL.hpp
Normal file
21
src/graphics/IBL.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef IBL_HPP
|
||||||
|
#define IBL_HPP
|
||||||
|
|
||||||
|
#include "gl_headers.hpp"
|
||||||
|
|
||||||
|
struct Color
|
||||||
|
{
|
||||||
|
float Red;
|
||||||
|
float Green;
|
||||||
|
float Blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Generate the 9 first SH coefficients for each color channel
|
||||||
|
using the cubemap provided by CubemapFace.
|
||||||
|
* \param textures sequence of 6 square textures.
|
||||||
|
* \param row/columns count of textures.
|
||||||
|
*/
|
||||||
|
void SphericalHarmonics(Color *CubemapFace[6], size_t edge_size, float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff);
|
||||||
|
|
||||||
|
GLuint generateSpecularCubemap(GLuint probe);
|
||||||
|
#endif
|
@ -182,8 +182,10 @@ unsigned GPUTimer::elapsedTimeus()
|
|||||||
|
|
||||||
FrameBuffer::FrameBuffer() {}
|
FrameBuffer::FrameBuffer() {}
|
||||||
|
|
||||||
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h, bool layered) :
|
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h,
|
||||||
RenderTargets(RTTs), DepthTexture(0), width(w), height(h), fbolayer(0)
|
bool layered)
|
||||||
|
: fbolayer(0), RenderTargets(RTTs), DepthTexture(0),
|
||||||
|
width(w), height(h)
|
||||||
{
|
{
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
@ -201,8 +203,10 @@ RenderTargets(RTTs), DepthTexture(0), width(w), height(h), fbolayer(0)
|
|||||||
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
|
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, GLuint DS, size_t w, size_t h, bool layered) :
|
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, GLuint DS, size_t w,
|
||||||
RenderTargets(RTTs), DepthTexture(DS), width(w), height(h), fbolayer(0)
|
size_t h, bool layered)
|
||||||
|
: fbolayer(0), RenderTargets(RTTs), DepthTexture(DS), width(w),
|
||||||
|
height(h)
|
||||||
{
|
{
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
@ -84,7 +84,9 @@ public:
|
|||||||
Version(const std::string &driver_version, const std::string &card_name)
|
Version(const std::string &driver_version, const std::string &card_name)
|
||||||
{
|
{
|
||||||
m_version.clear();
|
m_version.clear();
|
||||||
|
|
||||||
// Intel card: driver version = "3.1.0 - Build 9.17.10.3517"
|
// Intel card: driver version = "3.1.0 - Build 9.17.10.3517"
|
||||||
|
// ---------------------------------------------------------
|
||||||
if (StringUtils::startsWith(card_name, "Intel"))
|
if (StringUtils::startsWith(card_name, "Intel"))
|
||||||
{
|
{
|
||||||
std::vector<std::string> s = StringUtils::split(driver_version, '-');
|
std::vector<std::string> s = StringUtils::split(driver_version, '-');
|
||||||
@ -95,6 +97,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nvidia: driver_version = "4.3.0 NVIDIA 340.58"
|
||||||
|
// ----------------------------------------------
|
||||||
|
if (driver_version.find("NVIDIA") != std::string::npos)
|
||||||
|
{
|
||||||
|
std::vector<std::string> s = StringUtils::split(driver_version, ' ');
|
||||||
|
if (s.size() == 3)
|
||||||
|
{
|
||||||
|
convertVersionString(s[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Log::warn("Graphics", "Can not find version for '%s' '%s' - ignored.",
|
Log::warn("Graphics", "Can not find version for '%s' '%s' - ignored.",
|
||||||
driver_version.c_str(), card_name.c_str());
|
driver_version.c_str(), card_name.c_str());
|
||||||
|
|
||||||
|
@ -610,9 +610,6 @@ void IrrDriver::initDevice()
|
|||||||
m_mrt.clear();
|
m_mrt.clear();
|
||||||
m_mrt.reallocate(2);
|
m_mrt.reallocate(2);
|
||||||
|
|
||||||
glGenQueries(1, &m_lensflare_query);
|
|
||||||
m_query_issued = false;
|
|
||||||
|
|
||||||
scene::IMesh * sphere = m_scene_manager->getGeometryCreator()->createSphereMesh(1, 16, 16);
|
scene::IMesh * sphere = m_scene_manager->getGeometryCreator()->createSphereMesh(1, 16, 16);
|
||||||
for (unsigned i = 0; i < sphere->getMeshBufferCount(); ++i)
|
for (unsigned i = 0; i < sphere->getMeshBufferCount(); ++i)
|
||||||
{
|
{
|
||||||
@ -635,13 +632,6 @@ void IrrDriver::initDevice()
|
|||||||
|
|
||||||
sphere->drop();
|
sphere->drop();
|
||||||
|
|
||||||
m_lensflare = new scene::CLensFlareSceneNode(NULL, m_scene_manager, -1);
|
|
||||||
video::ITexture * const tex = getTexture(FileManager::TEXTURE,
|
|
||||||
"lensflare.png" );
|
|
||||||
if (!tex) Log::fatal("irr_driver", "Cannot find lens flare texture");
|
|
||||||
m_lensflare->setMaterialTexture(0, tex);
|
|
||||||
m_lensflare->setAutomaticCulling(scene::EAC_OFF);
|
|
||||||
|
|
||||||
m_suncam = m_scene_manager->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false);
|
m_suncam = m_scene_manager->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false);
|
||||||
m_suncam->grab();
|
m_suncam->grab();
|
||||||
m_suncam->setParent(NULL);
|
m_suncam->setParent(NULL);
|
||||||
@ -1396,6 +1386,7 @@ scene::ISceneNode *IrrDriver::addSkyBox(const std::vector<video::ITexture*> &tex
|
|||||||
SkyboxTextures = texture;
|
SkyboxTextures = texture;
|
||||||
SphericalHarmonicsTextures = sphericalHarmonics;
|
SphericalHarmonicsTextures = sphericalHarmonics;
|
||||||
SkyboxCubeMap = 0;
|
SkyboxCubeMap = 0;
|
||||||
|
SkyboxSpecularProbe = 0;
|
||||||
m_SH_dirty = true;
|
m_SH_dirty = true;
|
||||||
return m_scene_manager->addSkyBoxSceneNode(texture[0], texture[1],
|
return m_scene_manager->addSkyBoxSceneNode(texture[0], texture[1],
|
||||||
texture[2], texture[3],
|
texture[2], texture[3],
|
||||||
@ -1408,8 +1399,12 @@ void IrrDriver::suppressSkyBox()
|
|||||||
SphericalHarmonicsTextures.clear();
|
SphericalHarmonicsTextures.clear();
|
||||||
m_SH_dirty = true;
|
m_SH_dirty = true;
|
||||||
if ((SkyboxCubeMap) && (!ProfileWorld::isNoGraphics()))
|
if ((SkyboxCubeMap) && (!ProfileWorld::isNoGraphics()))
|
||||||
|
{
|
||||||
glDeleteTextures(1, &SkyboxCubeMap);
|
glDeleteTextures(1, &SkyboxCubeMap);
|
||||||
|
glDeleteTextures(1, &SkyboxSpecularProbe);
|
||||||
|
}
|
||||||
SkyboxCubeMap = 0;
|
SkyboxCubeMap = 0;
|
||||||
|
SkyboxSpecularProbe = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -2568,9 +2563,6 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos, float energy,
|
|||||||
//m_sun_interposer->setPosition(pos);
|
//m_sun_interposer->setPosition(pos);
|
||||||
//m_sun_interposer->updateAbsolutePosition();
|
//m_sun_interposer->updateAbsolutePosition();
|
||||||
|
|
||||||
m_lensflare->setPosition(pos);
|
|
||||||
m_lensflare->updateAbsolutePosition();
|
|
||||||
|
|
||||||
m_suncam->setPosition(pos);
|
m_suncam->setPosition(pos);
|
||||||
m_suncam->updateAbsolutePosition();
|
m_suncam->updateAbsolutePosition();
|
||||||
|
|
||||||
|
@ -254,6 +254,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GLuint SkyboxCubeMap;
|
GLuint SkyboxCubeMap;
|
||||||
|
GLuint SkyboxSpecularProbe;
|
||||||
/** A simple class to store video resolutions. */
|
/** A simple class to store video resolutions. */
|
||||||
class VideoMode
|
class VideoMode
|
||||||
{
|
{
|
||||||
@ -386,10 +387,7 @@ private:
|
|||||||
unsigned object_count[PASS_COUNT];
|
unsigned object_count[PASS_COUNT];
|
||||||
unsigned poly_count[PASS_COUNT];
|
unsigned poly_count[PASS_COUNT];
|
||||||
u32 m_renderpass;
|
u32 m_renderpass;
|
||||||
u32 m_lensflare_query;
|
|
||||||
bool m_query_issued;
|
|
||||||
class STKMeshSceneNode *m_sun_interposer;
|
class STKMeshSceneNode *m_sun_interposer;
|
||||||
scene::CLensFlareSceneNode *m_lensflare;
|
|
||||||
scene::ICameraSceneNode *m_suncam;
|
scene::ICameraSceneNode *m_suncam;
|
||||||
core::vector3df m_sundirection;
|
core::vector3df m_sundirection;
|
||||||
video::SColorf m_suncolor;
|
video::SColorf m_suncolor;
|
||||||
|
@ -27,8 +27,9 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,255,255),
|
ParticleKind::ParticleKind(const std::string &file)
|
||||||
m_max_start_color(255,255,255,255), m_name(file)
|
: m_min_start_color(255,255,255,255),
|
||||||
|
m_max_start_color(255,255,255,255), m_name(file)
|
||||||
{
|
{
|
||||||
// ---- Initial values to prevent readin uninitialized values
|
// ---- Initial values to prevent readin uninitialized values
|
||||||
m_max_size = 0.5f;
|
m_max_size = 0.5f;
|
||||||
@ -52,7 +53,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
|||||||
m_fade_away_end = -1.0f;
|
m_fade_away_end = -1.0f;
|
||||||
m_force_lost_to_gravity_time = 1000;
|
m_force_lost_to_gravity_time = 1000;
|
||||||
m_emission_decay_rate = 0;
|
m_emission_decay_rate = 0;
|
||||||
m_has_scale_affector = NULL;
|
m_has_scale_affector = false;
|
||||||
m_scale_affector_factor_x = 0.0f;
|
m_scale_affector_factor_x = 0.0f;
|
||||||
m_scale_affector_factor_y = 0.0f;
|
m_scale_affector_factor_y = 0.0f;
|
||||||
m_wind_speed = 0;
|
m_wind_speed = 0;
|
||||||
|
@ -113,7 +113,7 @@ public:
|
|||||||
* @param file Name of the file to load (no full path)
|
* @param file Name of the file to load (no full path)
|
||||||
* @throw std::runtime_error If the file cannot be found or is heavily malformed
|
* @throw std::runtime_error If the file cannot be found or is heavily malformed
|
||||||
*/
|
*/
|
||||||
ParticleKind(const std::string file);
|
ParticleKind(const std::string &file);
|
||||||
virtual ~ParticleKind() {}
|
virtual ~ParticleKind() {}
|
||||||
|
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ public:
|
|||||||
|
|
||||||
bool randomizeInitialY() const { return m_randomize_initial_y; }
|
bool randomizeInitialY() const { return m_randomize_initial_y; }
|
||||||
|
|
||||||
std::string getName() const { return m_name; }
|
const std::string& getName() const { return m_name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -228,12 +228,12 @@ void PostProcessing::renderEnvMap(const float *bSHCoeff, const float *gSHCoeff,
|
|||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
|
||||||
glUseProgram(FullScreenShader::EnvMapShader::getInstance()->Program);
|
glUseProgram(FullScreenShader::IBLShader::getInstance()->Program);
|
||||||
glBindVertexArray(SharedObject::FullScreenQuadVAO);
|
glBindVertexArray(SharedObject::FullScreenQuadVAO);
|
||||||
|
|
||||||
FullScreenShader::EnvMapShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), skybox);
|
FullScreenShader::IBLShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), skybox);
|
||||||
core::matrix4 TVM = irr_driver->getViewMatrix().getTransposed();
|
core::matrix4 TVM = irr_driver->getViewMatrix().getTransposed();
|
||||||
FullScreenShader::EnvMapShader::getInstance()->setUniforms(TVM, std::vector<float>(bSHCoeff, bSHCoeff + 9), std::vector<float>(gSHCoeff, gSHCoeff + 9), std::vector<float>(rSHCoeff, rSHCoeff + 9));
|
FullScreenShader::IBLShader::getInstance()->setUniforms(TVM, std::vector<float>(bSHCoeff, bSHCoeff + 9), std::vector<float>(gSHCoeff, gSHCoeff + 9), std::vector<float>(rSHCoeff, rSHCoeff + 9));
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
@ -62,8 +62,6 @@ private:
|
|||||||
|
|
||||||
video::ITexture *m_areamap;
|
video::ITexture *m_areamap;
|
||||||
|
|
||||||
u32 m_sunpixels;
|
|
||||||
|
|
||||||
void setMotionBlurCenterY(const u32 num, const float y);
|
void setMotionBlurCenterY(const u32 num, const float y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -107,8 +105,6 @@ public:
|
|||||||
|
|
||||||
/** Use motion blur for a short time */
|
/** Use motion blur for a short time */
|
||||||
void giveBoost(unsigned int cam_index);
|
void giveBoost(unsigned int cam_index);
|
||||||
|
|
||||||
void setSunPixels(const u32 in) { m_sunpixels = in; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HEADER_POST_PROCESSING_HPP
|
#endif // HEADER_POST_PROCESSING_HPP
|
||||||
|
@ -440,12 +440,14 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po
|
|||||||
|
|
||||||
if (getRH())
|
if (getRH())
|
||||||
{
|
{
|
||||||
|
glDisable(GL_BLEND);
|
||||||
m_rtts->getFBO(FBO_COLORS).Bind();
|
m_rtts->getFBO(FBO_COLORS).Bind();
|
||||||
m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2], rh_matrix, rh_extend);
|
m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2], rh_matrix, rh_extend);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGI())
|
if (getGI())
|
||||||
{
|
{
|
||||||
|
glDisable(GL_BLEND);
|
||||||
m_rtts->getFBO(FBO_COLORS).Bind();
|
m_rtts->getFBO(FBO_COLORS).Bind();
|
||||||
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
|
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
|
||||||
}
|
}
|
||||||
@ -576,29 +578,6 @@ void IrrDriver::computeSunVisibility()
|
|||||||
{
|
{
|
||||||
hasgodrays = World::getWorld()->getTrack()->hasGodRays();
|
hasgodrays = World::getWorld()->getTrack()->hasGodRays();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UserConfigParams::m_light_shaft && hasgodrays)
|
|
||||||
{
|
|
||||||
GLuint res = 0;
|
|
||||||
if (m_query_issued)
|
|
||||||
glGetQueryObjectuiv(m_lensflare_query, GL_QUERY_RESULT, &res);
|
|
||||||
m_post_processing->setSunPixels(res);
|
|
||||||
|
|
||||||
// Prepare the query for the next frame.
|
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
||||||
glBeginQuery(GL_SAMPLES_PASSED_ARB, m_lensflare_query);
|
|
||||||
m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID);
|
|
||||||
m_scene_manager->drawAll(scene::ESNRP_CAMERA);
|
|
||||||
irr_driver->setPhase(GLOW_PASS);
|
|
||||||
m_sun_interposer->render();
|
|
||||||
glEndQuery(GL_SAMPLES_PASSED_ARB);
|
|
||||||
m_query_issued = true;
|
|
||||||
|
|
||||||
m_lensflare->setStrength(res / 4000.0f);
|
|
||||||
|
|
||||||
// Make sure the color mask is reset
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrrDriver::renderParticles()
|
void IrrDriver::renderParticles()
|
||||||
@ -836,13 +815,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
|||||||
memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));
|
memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));
|
||||||
|
|
||||||
m_suncam->render();
|
m_suncam->render();
|
||||||
const core::vector3df &camdir = (camnode->getTarget() - camnode->getAbsolutePosition()).normalize();
|
|
||||||
const core::vector3df &sundir = (m_suncam->getTarget() - m_suncam->getAbsolutePosition()).normalize();
|
|
||||||
const core::vector3df &up = camdir.crossProduct(sundir).normalize();
|
|
||||||
if (up.getLength())
|
|
||||||
m_suncam->setUpVector(up);
|
|
||||||
m_suncam->render();
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < 4; i++)
|
for (unsigned i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (m_shadow_camnodes[i])
|
if (m_shadow_camnodes[i])
|
||||||
|
@ -155,7 +155,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
|||||||
|
|
||||||
{
|
{
|
||||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
|
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
|
||||||
m_post_processing->renderEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff, SkyboxCubeMap);
|
m_post_processing->renderEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff, SkyboxSpecularProbe);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render sunlight if and only if track supports shadow
|
// Render sunlight if and only if track supports shadow
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "graphics/IBL.hpp"
|
||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/shaders.hpp"
|
#include "graphics/shaders.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
@ -6,88 +7,6 @@
|
|||||||
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
|
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
|
||||||
|
|
||||||
static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z)
|
|
||||||
{
|
|
||||||
switch (face)
|
|
||||||
{
|
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
|
||||||
x = 1.;
|
|
||||||
y = -i;
|
|
||||||
z = -j;
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
|
||||||
x = -1.;
|
|
||||||
y = -i;
|
|
||||||
z = j;
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
|
||||||
x = j;
|
|
||||||
y = 1.;
|
|
||||||
z = i;
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
|
||||||
x = j;
|
|
||||||
y = -1;
|
|
||||||
z = -i;
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
|
||||||
x = j;
|
|
||||||
y = -i;
|
|
||||||
z = 1;
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
|
||||||
x = -j;
|
|
||||||
y = -i;
|
|
||||||
z = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
float norm = sqrt(x * x + y * y + z * z);
|
|
||||||
x /= norm, y /= norm, z /= norm;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getYml(GLenum face, size_t width, size_t height,
|
|
||||||
float *Y00,
|
|
||||||
float *Y1minus1, float *Y10, float *Y11,
|
|
||||||
float *Y2minus2, float *Y2minus1, float *Y20, float *Y21, float *Y22)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (unsigned j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
float x, y, z;
|
|
||||||
float fi = float(i), fj = float(j);
|
|
||||||
fi /= width, fj /= height;
|
|
||||||
fi = 2 * fi - 1, fj = 2 * fj - 1;
|
|
||||||
getXYZ(face, fi, fj, x, y, z);
|
|
||||||
|
|
||||||
// constant part of Ylm
|
|
||||||
float c00 = 0.282095f;
|
|
||||||
float c1minus1 = 0.488603f;
|
|
||||||
float c10 = 0.488603f;
|
|
||||||
float c11 = 0.488603f;
|
|
||||||
float c2minus2 = 1.092548f;
|
|
||||||
float c2minus1 = 1.092548f;
|
|
||||||
float c21 = 1.092548f;
|
|
||||||
float c20 = 0.315392f;
|
|
||||||
float c22 = 0.546274f;
|
|
||||||
|
|
||||||
size_t idx = i * height + j;
|
|
||||||
|
|
||||||
Y00[idx] = c00;
|
|
||||||
Y1minus1[idx] = c1minus1 * y;
|
|
||||||
Y10[idx] = c10 * z;
|
|
||||||
Y11[idx] = c11 * x;
|
|
||||||
Y2minus2[idx] = c2minus2 * x * y;
|
|
||||||
Y2minus1[idx] = c2minus1 * y * z;
|
|
||||||
Y21[idx] = c21 * x * z;
|
|
||||||
Y20[idx] = c20 * (3 * z * z - 1);
|
|
||||||
Y22[idx] = c22 * (x * x - y * y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static float getTexelValue(unsigned i, unsigned j, size_t width, size_t height, float *Coeff, float *Y00, float *Y1minus1, float *Y10, float *Y11,
|
static float getTexelValue(unsigned i, unsigned j, size_t width, size_t height, float *Coeff, float *Y00, float *Y1minus1, float *Y10, float *Y11,
|
||||||
float *Y2minus2, float * Y2minus1, float * Y20, float *Y21, float *Y22)
|
float *Y2minus2, float * Y2minus1, float * Y20, float *Y21, float *Y22)
|
||||||
{
|
{
|
||||||
@ -130,77 +49,6 @@ static void unprojectSH(float *output[], size_t width, size_t height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void projectSH(float *color[], size_t width, size_t height,
|
|
||||||
float *Y00[],
|
|
||||||
float *Y1minus1[], float *Y10[], float *Y11[],
|
|
||||||
float *Y2minus2[], float *Y2minus1[], float * Y20[], float *Y21[], float *Y22[],
|
|
||||||
float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < 9; i++)
|
|
||||||
{
|
|
||||||
blueSHCoeff[i] = 0;
|
|
||||||
greenSHCoeff[i] = 0;
|
|
||||||
redSHCoeff[i] = 0;
|
|
||||||
}
|
|
||||||
float wh = float(width * height);
|
|
||||||
for (unsigned face = 0; face < 6; face++)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (unsigned j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
size_t idx = i * height + j;
|
|
||||||
float fi = float(i), fj = float(j);
|
|
||||||
fi /= width, fj /= height;
|
|
||||||
fi = 2 * fi - 1, fj = 2 * fj - 1;
|
|
||||||
|
|
||||||
|
|
||||||
float d = sqrt(fi * fi + fj * fj + 1);
|
|
||||||
|
|
||||||
// Constant obtained by projecting unprojected ref values
|
|
||||||
float solidangle = 2.75f / (wh * pow(d, 1.5f));
|
|
||||||
// pow(., 2.2) to convert from srgb
|
|
||||||
float b = pow(color[face][4 * height * i + 4 * j] / 255.f, 2.2f);
|
|
||||||
float g = pow(color[face][4 * height * i + 4 * j + 1] / 255.f, 2.2f);
|
|
||||||
float r = pow(color[face][4 * height * i + 4 * j + 2] / 255.f, 2.2f);
|
|
||||||
|
|
||||||
assert(b >= 0.);
|
|
||||||
|
|
||||||
blueSHCoeff[0] += b * Y00[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[1] += b * Y1minus1[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[2] += b * Y10[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[3] += b * Y11[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[4] += b * Y2minus2[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[5] += b * Y2minus1[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[6] += b * Y20[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[7] += b * Y21[face][idx] * solidangle;
|
|
||||||
blueSHCoeff[8] += b * Y22[face][idx] * solidangle;
|
|
||||||
|
|
||||||
greenSHCoeff[0] += g * Y00[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[1] += g * Y1minus1[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[2] += g * Y10[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[3] += g * Y11[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[4] += g * Y2minus2[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[5] += g * Y2minus1[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[6] += g * Y20[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[7] += g * Y21[face][idx] * solidangle;
|
|
||||||
greenSHCoeff[8] += g * Y22[face][idx] * solidangle;
|
|
||||||
|
|
||||||
|
|
||||||
redSHCoeff[0] += r * Y00[face][idx] * solidangle;
|
|
||||||
redSHCoeff[1] += r * Y1minus1[face][idx] * solidangle;
|
|
||||||
redSHCoeff[2] += r * Y10[face][idx] * solidangle;
|
|
||||||
redSHCoeff[3] += r * Y11[face][idx] * solidangle;
|
|
||||||
redSHCoeff[4] += r * Y2minus2[face][idx] * solidangle;
|
|
||||||
redSHCoeff[5] += r * Y2minus1[face][idx] * solidangle;
|
|
||||||
redSHCoeff[6] += r * Y20[face][idx] * solidangle;
|
|
||||||
redSHCoeff[7] += r * Y21[face][idx] * solidangle;
|
|
||||||
redSHCoeff[8] += r * Y22[face][idx] * solidangle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void displayCoeff(float *SHCoeff)
|
static void displayCoeff(float *SHCoeff)
|
||||||
{
|
{
|
||||||
@ -210,7 +58,7 @@ static void displayCoeff(float *SHCoeff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only for 9 coefficients
|
// Only for 9 coefficients
|
||||||
static void testSH(unsigned char *color[6], size_t width, size_t height,
|
/*static void testSH(unsigned char *color[6], size_t width, size_t height,
|
||||||
float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff)
|
float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff)
|
||||||
{
|
{
|
||||||
float *Y00[6];
|
float *Y00[6];
|
||||||
@ -250,7 +98,7 @@ static void testSH(unsigned char *color[6], size_t width, size_t height,
|
|||||||
getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, width, height, Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]);
|
getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, width, height, Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* blueSHCoeff[0] = 0.54,
|
blueSHCoeff[0] = 0.54,
|
||||||
blueSHCoeff[1] = .6, blueSHCoeff[2] = -.27, blueSHCoeff[3] = .01,
|
blueSHCoeff[1] = .6, blueSHCoeff[2] = -.27, blueSHCoeff[3] = .01,
|
||||||
blueSHCoeff[4] = -.12, blueSHCoeff[5] = -.47, blueSHCoeff[6] = -.15, blueSHCoeff[7] = .14, blueSHCoeff[8] = -.3;
|
blueSHCoeff[4] = -.12, blueSHCoeff[5] = -.47, blueSHCoeff[6] = -.15, blueSHCoeff[7] = .14, blueSHCoeff[8] = -.3;
|
||||||
greenSHCoeff[0] = .44,
|
greenSHCoeff[0] = .44,
|
||||||
@ -267,12 +115,12 @@ static void testSH(unsigned char *color[6], size_t width, size_t height,
|
|||||||
printf("Red:\n");
|
printf("Red:\n");
|
||||||
displayCoeff(redSHCoeff);*/
|
displayCoeff(redSHCoeff);*/
|
||||||
|
|
||||||
projectSH(testoutput, width, height,
|
/* projectSH(testoutput, width, height,
|
||||||
Y00,
|
Y00,
|
||||||
Y1minus1, Y10, Y11,
|
Y1minus1, Y10, Y11,
|
||||||
Y2minus2, Y2minus1, Y20, Y21, Y22,
|
Y2minus2, Y2minus1, Y20, Y21, Y22,
|
||||||
blueSHCoeff, greenSHCoeff, redSHCoeff
|
blueSHCoeff, greenSHCoeff, redSHCoeff
|
||||||
);
|
);*/
|
||||||
|
|
||||||
//printf("Blue:\n");
|
//printf("Blue:\n");
|
||||||
//displayCoeff(blueSHCoeff);
|
//displayCoeff(blueSHCoeff);
|
||||||
@ -319,7 +167,7 @@ static void testSH(unsigned char *color[6], size_t width, size_t height,
|
|||||||
printf("Red:\n");
|
printf("Red:\n");
|
||||||
displayCoeff(redSHCoeff);
|
displayCoeff(redSHCoeff);
|
||||||
|
|
||||||
printf("\nAfter projection\n\n");*/
|
printf("\nAfter projection\n\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -346,7 +194,7 @@ static void testSH(unsigned char *color[6], size_t width, size_t height,
|
|||||||
delete[] Y21[face];
|
delete[] Y21[face];
|
||||||
delete[] Y22[face];
|
delete[] Y22[face];
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void swapPixels(char *old_img, char *new_img, unsigned stride, unsigned old_i, unsigned old_j, unsigned new_i, unsigned new_j)
|
void swapPixels(char *old_img, char *new_img, unsigned stride, unsigned old_i, unsigned old_j, unsigned new_i, unsigned new_j)
|
||||||
{
|
{
|
||||||
@ -356,6 +204,7 @@ void swapPixels(char *old_img, char *new_img, unsigned stride, unsigned old_i, u
|
|||||||
new_img[4 * (stride * new_i + new_j) + 3] = old_img[4 * (stride * old_i + old_j) + 3];
|
new_img[4 * (stride * new_i + new_j) + 3] = old_img[4 * (stride * old_i + old_j) + 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Generate an opengl cubemap texture from 6 2d textures.
|
/** Generate an opengl cubemap texture from 6 2d textures.
|
||||||
Out of legacy the sequence of textures maps to :
|
Out of legacy the sequence of textures maps to :
|
||||||
- 1st texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
|
- 1st texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
|
||||||
@ -431,6 +280,7 @@ void IrrDriver::generateSkyboxCubemap()
|
|||||||
|
|
||||||
assert(SkyboxTextures.size() == 6);
|
assert(SkyboxTextures.size() == 6);
|
||||||
SkyboxCubeMap = generateCubeMapFromTextures(SkyboxTextures);
|
SkyboxCubeMap = generateCubeMapFromTextures(SkyboxTextures);
|
||||||
|
SkyboxSpecularProbe = generateSpecularCubemap(SkyboxCubeMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrrDriver::generateDiffuseCoefficients()
|
void IrrDriver::generateDiffuseCoefficients()
|
||||||
@ -440,16 +290,18 @@ void IrrDriver::generateDiffuseCoefficients()
|
|||||||
m_SH_dirty = false;
|
m_SH_dirty = false;
|
||||||
const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 };
|
const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 };
|
||||||
|
|
||||||
|
unsigned sh_w = 0, sh_h = 0;
|
||||||
|
unsigned char *sh_rgba[6];
|
||||||
|
|
||||||
if (SphericalHarmonicsTextures.size() == 6)
|
if (SphericalHarmonicsTextures.size() == 6)
|
||||||
{
|
{
|
||||||
unsigned sh_w = 0, sh_h = 0;
|
|
||||||
for (unsigned i = 0; i < 6; i++)
|
for (unsigned i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
sh_w = MAX2(sh_w, SphericalHarmonicsTextures[i]->getOriginalSize().Width);
|
sh_w = MAX2(sh_w, SphericalHarmonicsTextures[i]->getOriginalSize().Width);
|
||||||
sh_h = MAX2(sh_h, SphericalHarmonicsTextures[i]->getOriginalSize().Height);
|
sh_h = MAX2(sh_h, SphericalHarmonicsTextures[i]->getOriginalSize().Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *sh_rgba[6];
|
|
||||||
for (unsigned i = 0; i < 6; i++)
|
for (unsigned i = 0; i < 6; i++)
|
||||||
sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];
|
sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];
|
||||||
for (unsigned i = 0; i < 6; i++)
|
for (unsigned i = 0; i < 6; i++)
|
||||||
@ -468,24 +320,19 @@ void IrrDriver::generateDiffuseCoefficients()
|
|||||||
delete image;
|
delete image;
|
||||||
}
|
}
|
||||||
|
|
||||||
testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < 6; i++)
|
|
||||||
delete[] sh_rgba[i];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int sh_w = 16;
|
sh_w = 16;
|
||||||
int sh_h = 16;
|
sh_h = 16;
|
||||||
|
|
||||||
video::SColor ambient = m_scene_manager->getAmbientLight().toSColor();
|
video::SColor ambient = m_scene_manager->getAmbientLight().toSColor();
|
||||||
|
|
||||||
unsigned char *sh_rgba[6];
|
|
||||||
for (unsigned i = 0; i < 6; i++)
|
for (unsigned i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];
|
sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];
|
||||||
|
|
||||||
for (int j = 0; j < sh_w * sh_h * 4; j += 4)
|
for (unsigned j = 0; j < sh_w * sh_h * 4; j += 4)
|
||||||
{
|
{
|
||||||
sh_rgba[i][j] = ambient.getBlue();
|
sh_rgba[i][j] = ambient.getBlue();
|
||||||
sh_rgba[i][j + 1] = ambient.getGreen();
|
sh_rgba[i][j + 1] = ambient.getGreen();
|
||||||
@ -493,9 +340,31 @@ void IrrDriver::generateDiffuseCoefficients()
|
|||||||
sh_rgba[i][j + 3] = 255;
|
sh_rgba[i][j + 3] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff);
|
// Convert to float texture
|
||||||
|
Color *FloatTexCube[6];
|
||||||
|
for (unsigned i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
FloatTexCube[i] = new Color[sh_w * sh_h];
|
||||||
|
for (unsigned j = 0; j < sh_w * sh_h; j++)
|
||||||
|
{
|
||||||
|
FloatTexCube[i][j].Blue = powf(float(0xFF & sh_rgba[i][4 * j]) / 255.f, 2.2f);
|
||||||
|
FloatTexCube[i][j].Green = powf(float(0xFF & sh_rgba[i][4 * j + 1]) / 255.f, 2.2f);
|
||||||
|
FloatTexCube[i][j].Red = powf(float(0xFF & sh_rgba[i][4 * j + 2]) / 255.f, 2.2f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SphericalHarmonics(FloatTexCube, sh_w, blueSHCoeff, greenSHCoeff, redSHCoeff);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
delete[] sh_rgba[i];
|
||||||
|
delete[] FloatTexCube[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SphericalHarmonicsTextures.size() != 6)
|
||||||
|
{
|
||||||
// Diffuse env map is x 0.25, compensate
|
// Diffuse env map is x 0.25, compensate
|
||||||
for (unsigned i = 0; i < 9; i++)
|
for (unsigned i = 0; i < 9; i++)
|
||||||
{
|
{
|
||||||
@ -503,19 +372,7 @@ void IrrDriver::generateDiffuseCoefficients()
|
|||||||
greenSHCoeff[i] *= 4;
|
greenSHCoeff[i] *= 4;
|
||||||
redSHCoeff[i] *= 4;
|
redSHCoeff[i] *= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < 6; i++)
|
|
||||||
delete[] sh_rgba[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*for (unsigned i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, ConvolutedSkyboxCubeMap);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
|
void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
|
||||||
|
@ -147,8 +147,6 @@ GLuint LoadShader(const char * file, unsigned type)
|
|||||||
char versionString[20];
|
char versionString[20];
|
||||||
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
|
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
|
||||||
std::string Code = versionString;
|
std::string Code = versionString;
|
||||||
if (irr_driver->hasVSLayerExtension())
|
|
||||||
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
|
|
||||||
if (UserConfigParams::m_azdo)
|
if (UserConfigParams::m_azdo)
|
||||||
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
||||||
else
|
else
|
||||||
@ -889,6 +887,20 @@ unsigned getGLSLVersion()
|
|||||||
return irr_driver->getGLSLVersion();
|
return irr_driver->getGLSLVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace UtilShader
|
||||||
|
{
|
||||||
|
SpecularIBLGenerator::SpecularIBLGenerator()
|
||||||
|
{
|
||||||
|
Program = LoadProgram(OBJECT,
|
||||||
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/importance_sampling_specular.frag").c_str());
|
||||||
|
AssignUniforms("PermutationMatrix", "ViewportSize");
|
||||||
|
TU_Samples = 1;
|
||||||
|
AssignSamplerNames(Program, 0, "tex");
|
||||||
|
AssignTextureUnit(Program, TexUnit(TU_Samples, "samples"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MeshShader
|
namespace MeshShader
|
||||||
{
|
{
|
||||||
// Solid Normal and depth pass shaders
|
// Solid Normal and depth pass shaders
|
||||||
@ -1426,7 +1438,7 @@ namespace LightShader
|
|||||||
Program = LoadProgram(OBJECT,
|
Program = LoadProgram(OBJECT,
|
||||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getSpecular.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlight.frag").c_str());
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlight.frag").c_str());
|
||||||
|
|
||||||
@ -1625,7 +1637,7 @@ namespace FullScreenShader
|
|||||||
Program = LoadProgram(OBJECT,
|
Program = LoadProgram(OBJECT,
|
||||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getSpecular.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlight.frag").c_str());
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlight.frag").c_str());
|
||||||
|
|
||||||
@ -1633,15 +1645,17 @@ namespace FullScreenShader
|
|||||||
AssignUniforms("direction", "col");
|
AssignUniforms("direction", "col");
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvMapShader::EnvMapShader()
|
IBLShader::IBLShader()
|
||||||
{
|
{
|
||||||
Program = LoadProgram(OBJECT,
|
Program = LoadProgram(OBJECT,
|
||||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/diffuseenvmap.frag").c_str());
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/DiffuseIBL.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularIBL.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/IBL.frag").c_str());
|
||||||
AssignUniforms("TransposeViewMatrix", "blueLmn[0]", "greenLmn[0]", "redLmn[0]");
|
AssignUniforms("TransposeViewMatrix", "blueLmn[0]", "greenLmn[0]", "redLmn[0]");
|
||||||
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "tex");
|
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "probe");
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowedSunLightShader::ShadowedSunLightShader()
|
ShadowedSunLightShader::ShadowedSunLightShader()
|
||||||
@ -1649,7 +1663,7 @@ namespace FullScreenShader
|
|||||||
Program = LoadProgram(OBJECT,
|
Program = LoadProgram(OBJECT,
|
||||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getSpecular.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
|
||||||
|
|
||||||
|
@ -48,6 +48,13 @@ public:
|
|||||||
static void init();
|
static void init();
|
||||||
static void setUniforms(const irr::video::SColor &);
|
static void setUniforms(const irr::video::SColor &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SpecularIBLGenerator : public ShaderHelperSingleton<SpecularIBLGenerator, core::matrix4, float >, public TextureRead<Trilinear_cubemap>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLuint TU_Samples;
|
||||||
|
SpecularIBLGenerator();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -411,10 +418,10 @@ public:
|
|||||||
SunLightShader();
|
SunLightShader();
|
||||||
};
|
};
|
||||||
|
|
||||||
class EnvMapShader : public ShaderHelperSingleton<EnvMapShader, core::matrix4, std::vector<float>, std::vector<float>, std::vector<float> >, public TextureRead<Nearest_Filtered, Nearest_Filtered, Trilinear_cubemap>
|
class IBLShader : public ShaderHelperSingleton<IBLShader, core::matrix4, std::vector<float>, std::vector<float>, std::vector<float> >, public TextureRead<Nearest_Filtered, Nearest_Filtered, Trilinear_cubemap>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EnvMapShader();
|
IBLShader();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
||||||
|
@ -146,12 +146,11 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
|||||||
delta.normalize();
|
delta.normalize();
|
||||||
delta *= m_width*0.5f;
|
delta *= m_width*0.5f;
|
||||||
|
|
||||||
float distance = 0.0f;
|
|
||||||
Vec3 start = m_left[m_current]->getCenterStart();
|
Vec3 start = m_left[m_current]->getCenterStart();
|
||||||
Vec3 newPoint = (raycast_left + raycast_right)/2;
|
Vec3 newPoint = (raycast_left + raycast_right)/2;
|
||||||
// this linear distance does not account for the kart turning, it's true,
|
// this linear distance does not account for the kart turning, it's true,
|
||||||
// but it produces good enough results
|
// but it produces good enough results
|
||||||
distance = (newPoint - start).length();
|
float distance = (newPoint - start).length();
|
||||||
|
|
||||||
m_left [m_current]->add(raycast_left-delta, raycast_left+delta,
|
m_left [m_current]->add(raycast_left-delta, raycast_left+delta,
|
||||||
distance);
|
distance);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/material.hpp"
|
#include "graphics/material.hpp"
|
||||||
#include "graphics/material_manager.hpp"
|
#include "graphics/material_manager.hpp"
|
||||||
|
#include "graphics/stkmeshscenenode.hpp"
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "karts/controller/controller.hpp"
|
#include "karts/controller/controller.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
@ -42,21 +43,17 @@
|
|||||||
*/
|
*/
|
||||||
SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
||||||
{
|
{
|
||||||
video::SMaterial m;
|
|
||||||
m.BackfaceCulling = false;
|
|
||||||
m.MaterialType = video::EMT_SOLID;
|
|
||||||
|
|
||||||
Material *material = material_manager->getMaterial("slipstream.png");
|
Material *material = material_manager->getMaterial("slipstream.png");
|
||||||
m.setTexture(0, material->getTexture());
|
|
||||||
m.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
m.setFlag(video::EMF_COLOR_MATERIAL, true);
|
|
||||||
|
|
||||||
m.ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
|
createMesh(material);
|
||||||
|
|
||||||
m.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
|
||||||
|
|
||||||
createMesh(m);
|
|
||||||
m_node = irr_driver->addMesh(m_mesh, "splistream");
|
m_node = irr_driver->addMesh(m_mesh, "splistream");
|
||||||
|
|
||||||
|
scene::IMeshBuffer* buffer = m_mesh->getMeshBuffer(0);
|
||||||
|
material->setMaterialProperties(&buffer->getMaterial(), buffer);
|
||||||
|
|
||||||
|
STKMeshSceneNode* stk_node = dynamic_cast<STKMeshSceneNode*>(m_node);
|
||||||
|
if (stk_node != NULL)
|
||||||
|
stk_node->setReloadEachFrame(true);
|
||||||
m_mesh->drop();
|
m_mesh->drop();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -155,7 +152,7 @@ void SlipStream::reset()
|
|||||||
* texture coordniates.
|
* texture coordniates.
|
||||||
* \param material The material to use.
|
* \param material The material to use.
|
||||||
*/
|
*/
|
||||||
void SlipStream::createMesh(const video::SMaterial &material)
|
void SlipStream::createMesh(Material* material)
|
||||||
{
|
{
|
||||||
// All radius, starting with the one closest to the kart (and
|
// All radius, starting with the one closest to the kart (and
|
||||||
// widest) to the one furthest away. A 0 indicates the end of the list
|
// widest) to the one furthest away. A 0 indicates the end of the list
|
||||||
@ -200,7 +197,7 @@ void SlipStream::createMesh(const video::SMaterial &material)
|
|||||||
const unsigned int last_segment = 14;
|
const unsigned int last_segment = 14;
|
||||||
const float f = 2*M_PI/float(num_segments);
|
const float f = 2*M_PI/float(num_segments);
|
||||||
scene::SMeshBuffer *buffer = new scene::SMeshBuffer();
|
scene::SMeshBuffer *buffer = new scene::SMeshBuffer();
|
||||||
buffer->Material = material;
|
buffer->getMaterial().TextureLayer[0].Texture = material->getTexture();
|
||||||
for(unsigned int j=0; j<num_circles; j++)
|
for(unsigned int j=0; j<num_circles; j++)
|
||||||
{
|
{
|
||||||
float curr_distance = distance[j]-distance[0];
|
float curr_distance = distance[j]-distance[0];
|
||||||
@ -237,6 +234,15 @@ void SlipStream::createMesh(const video::SMaterial &material)
|
|||||||
}
|
}
|
||||||
} // for j<num_circles-1
|
} // for j<num_circles-1
|
||||||
|
|
||||||
|
material->setMaterialProperties(&buffer->getMaterial(), buffer);
|
||||||
|
if (!irr_driver->isGLSL())
|
||||||
|
{
|
||||||
|
buffer->Material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
buffer->Material.setFlag(video::EMF_COLOR_MATERIAL, true);
|
||||||
|
buffer->Material.ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
|
||||||
|
//buffer->Material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
mesh->addMeshBuffer(buffer);
|
mesh->addMeshBuffer(buffer);
|
||||||
mesh->recalculateBoundingBox();
|
mesh->recalculateBoundingBox();
|
||||||
@ -386,7 +392,7 @@ void SlipStream::update(float dt)
|
|||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// Define this to get slipstream effect shown even when the karts are
|
// Define this to get slipstream effect shown even when the karts are
|
||||||
// not moving. This is useful for debugging the graphics of SS-ing.
|
// not moving. This is useful for debugging the graphics of SS-ing.
|
||||||
#undef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
//#define DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||||
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||||
if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed() *
|
if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed() *
|
||||||
m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
|
m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
|
||||||
|
@ -32,6 +32,7 @@ using namespace irr;
|
|||||||
|
|
||||||
class AbstractKart;
|
class AbstractKart;
|
||||||
class Quad;
|
class Quad;
|
||||||
|
class Material;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup graphics
|
* \ingroup graphics
|
||||||
@ -80,7 +81,7 @@ private:
|
|||||||
** overtake the right kart. */
|
** overtake the right kart. */
|
||||||
AbstractKart* m_target_kart;
|
AbstractKart* m_target_kart;
|
||||||
|
|
||||||
void createMesh(const video::SMaterial &m);
|
void createMesh(Material* material);
|
||||||
void setDebugColor(const video::SColor &color);
|
void setDebugColor(const video::SColor &color);
|
||||||
public:
|
public:
|
||||||
SlipStream (AbstractKart* kart);
|
SlipStream (AbstractKart* kart);
|
||||||
|
@ -34,11 +34,7 @@ TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE typ
|
|||||||
{
|
{
|
||||||
if (type == irr_driver->getShader(ES_DISPLACE))
|
if (type == irr_driver->getShader(ES_DISPLACE))
|
||||||
return TM_DISPLACEMENT;
|
return TM_DISPLACEMENT;
|
||||||
video::E_BLEND_FACTOR srcFact, DstFact;
|
if (material->getShaderType() == Material::SHADERTYPE_ADDITIVE)
|
||||||
video::E_MODULATE_FUNC mod;
|
|
||||||
u32 alpha;
|
|
||||||
unpack_textureBlendFunc(srcFact, DstFact, mod, alpha, MaterialTypeParam);
|
|
||||||
if (DstFact == video::EBF_ONE || type == video::EMT_TRANSPARENT_ADD_COLOR)
|
|
||||||
return TM_ADDITIVE;
|
return TM_ADDITIVE;
|
||||||
return TM_DEFAULT;
|
return TM_DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,8 @@ void STKMeshSceneNode::updateNoGL()
|
|||||||
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam, material);
|
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam, material);
|
||||||
if (!immediate_draw)
|
if (!immediate_draw)
|
||||||
TransparentMesh[TranspMat].push_back(&mesh);
|
TransparentMesh[TranspMat].push_back(&mesh);
|
||||||
|
else
|
||||||
|
additive = (TranspMat == TM_ADDITIVE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -370,7 +372,10 @@ void STKMeshSceneNode::render()
|
|||||||
{
|
{
|
||||||
if (update_each_frame)
|
if (update_each_frame)
|
||||||
updatevbo();
|
updatevbo();
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
if (additive)
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
else
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@ protected:
|
|||||||
bool isMaterialInitialized;
|
bool isMaterialInitialized;
|
||||||
bool isGLInitialized;
|
bool isGLInitialized;
|
||||||
bool immediate_draw;
|
bool immediate_draw;
|
||||||
|
bool additive;
|
||||||
bool update_each_frame;
|
bool update_each_frame;
|
||||||
bool isDisplacement;
|
bool isDisplacement;
|
||||||
bool isGlow;
|
bool isGlow;
|
||||||
|
@ -288,7 +288,7 @@ namespace GUIEngine
|
|||||||
|
|
||||||
\n
|
\n
|
||||||
\subsection prop2 PROP_TEXT
|
\subsection prop2 PROP_TEXT
|
||||||
<em> Name in XML files: </em> \c "text"
|
<em> Name in XML files: </em> \c "text" or "raw_text" ("text" is translated, "raw_text" is not)
|
||||||
|
|
||||||
gives text (a label) to the widget where supported. Ribbon-grids give a
|
gives text (a label) to the widget where supported. Ribbon-grids give a
|
||||||
special meaning to this parameter, see ribbon-grid docs above.
|
special meaning to this parameter, see ribbon-grid docs above.
|
||||||
|
@ -126,7 +126,7 @@ void createLabel(const Message *message)
|
|||||||
* position of the message. */
|
* position of the message. */
|
||||||
void updatePosition()
|
void updatePosition()
|
||||||
{
|
{
|
||||||
if (g_all_messages.size() == 0) return;
|
if (g_all_messages.empty()) return;
|
||||||
Message *last = g_all_messages.top();
|
Message *last = g_all_messages.top();
|
||||||
createLabel(last);
|
createLabel(last);
|
||||||
} // updatePosition
|
} // updatePosition
|
||||||
@ -139,7 +139,7 @@ void updatePosition()
|
|||||||
void add(MessageType mt, const irr::core::stringw &message)
|
void add(MessageType mt, const irr::core::stringw &message)
|
||||||
{
|
{
|
||||||
Message *m = new Message(mt, message);
|
Message *m = new Message(mt, message);
|
||||||
if(g_all_messages.size()==0)
|
if(g_all_messages.empty())
|
||||||
{
|
{
|
||||||
// Indicate that there is a new message, which should
|
// Indicate that there is a new message, which should
|
||||||
// which needs a new label etc. to be computed.
|
// which needs a new label etc. to be computed.
|
||||||
@ -157,7 +157,7 @@ void add(MessageType mt, const irr::core::stringw &message)
|
|||||||
*/
|
*/
|
||||||
void update(float dt)
|
void update(float dt)
|
||||||
{
|
{
|
||||||
if(g_all_messages.size()==0) return;
|
if(g_all_messages.empty()) return;
|
||||||
|
|
||||||
g_current_display_time += dt;
|
g_current_display_time += dt;
|
||||||
if(g_current_display_time > g_max_display_time)
|
if(g_current_display_time > g_max_display_time)
|
||||||
@ -165,7 +165,7 @@ void update(float dt)
|
|||||||
Message *last = g_all_messages.top();
|
Message *last = g_all_messages.top();
|
||||||
g_all_messages.pop();
|
g_all_messages.pop();
|
||||||
delete last;
|
delete last;
|
||||||
if(g_all_messages.size()==0) return;
|
if(g_all_messages.empty()) return;
|
||||||
g_current_display_time = -1.0f;
|
g_current_display_time = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,6 +232,13 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
|||||||
widget.m_is_text_rtl = (translations->isRTLLanguage() && widget.m_text != text);
|
widget.m_is_text_rtl = (translations->isRTLLanguage() && widget.m_text != text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wchar_t* raw_text = xml->getAttributeValue(L"raw_text");
|
||||||
|
|
||||||
|
if (raw_text != NULL)
|
||||||
|
{
|
||||||
|
widget.m_text = raw_text;
|
||||||
|
}
|
||||||
|
|
||||||
if (parent != NULL)
|
if (parent != NULL)
|
||||||
{
|
{
|
||||||
widget.setParent(parent);
|
widget.setParent(parent);
|
||||||
|
@ -236,7 +236,8 @@ void ListWidget::addItem(const std::string& internal_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
void ListWidget::renameCell(const int row_index, const int col_index, const irr::core::stringw newName, const int icon)
|
void ListWidget::renameCell(const int row_index, const int col_index,
|
||||||
|
const irr::core::stringw &newName, const int icon)
|
||||||
{
|
{
|
||||||
// May only be called AFTER this widget has been add()ed
|
// May only be called AFTER this widget has been add()ed
|
||||||
assert(m_element != NULL);
|
assert(m_element != NULL);
|
||||||
@ -251,13 +252,15 @@ void ListWidget::renameCell(const int row_index, const int col_index, const irr:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
void ListWidget::renameItem(const int row_index, const irr::core::stringw newName, const int icon)
|
void ListWidget::renameItem(const int row_index,
|
||||||
|
const irr::core::stringw &newName, const int icon)
|
||||||
{
|
{
|
||||||
renameCell(row_index, 0, newName, icon);
|
renameCell(row_index, 0, newName, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
void ListWidget::renameItem(const std::string & internal_name, const irr::core::stringw newName, const int icon)
|
void ListWidget::renameItem(const std::string &internal_name,
|
||||||
|
const irr::core::stringw &newName, const int icon)
|
||||||
{
|
{
|
||||||
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
||||||
assert(list != NULL);
|
assert(list != NULL);
|
||||||
@ -456,7 +459,7 @@ EventPropagation ListWidget::transmitEvent(Widget* w,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
int ListWidget::getItemID(const std::string internalName) const
|
int ListWidget::getItemID(const std::string &internalName) const
|
||||||
{
|
{
|
||||||
const CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
const CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
||||||
assert(list != NULL);
|
assert(list != NULL);
|
||||||
|
@ -167,7 +167,7 @@ namespace GUIEngine
|
|||||||
/**
|
/**
|
||||||
* \brief Finds the ID of the item that has a given internal name
|
* \brief Finds the ID of the item that has a given internal name
|
||||||
*/
|
*/
|
||||||
int getItemID(const std::string internalName) const;
|
int getItemID(const std::string &internalName) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief change the selected item
|
* \brief change the selected item
|
||||||
@ -180,20 +180,23 @@ namespace GUIEngine
|
|||||||
* \brief rename an item and/or change its icon based on its ID
|
* \brief rename an item and/or change its icon based on its ID
|
||||||
* \pre may only be called after the widget has been added to the screen with add()
|
* \pre may only be called after the widget has been added to the screen with add()
|
||||||
*/
|
*/
|
||||||
void renameCell(const int row_num, const int col_num, const irr::core::stringw newName, const int icon=-1);
|
void renameCell(const int row_num, const int col_num,
|
||||||
|
const irr::core::stringw &newName, const int icon=-1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* renames first cell only
|
* renames first cell only
|
||||||
*/
|
*/
|
||||||
void renameItem(const int row_num, const irr::core::stringw newName, const int icon=-1);
|
void renameItem(const int row_num,
|
||||||
void renameItem(const std::string & internal_name, const irr::core::stringw newName, const int icon=-1);
|
const irr::core::stringw &newName, const int icon=-1);
|
||||||
|
void renameItem(const std::string & internal_name,
|
||||||
|
const irr::core::stringw &newName, const int icon=-1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief rename an item and/or change its icon based on its internal name
|
* \brief rename an item and/or change its icon based on its internal name
|
||||||
* \pre may only be called after the widget has been added to the screen with add()
|
* \pre may only be called after the widget has been added to the screen with add()
|
||||||
*/
|
*/
|
||||||
void renameCell(const std::string internalName, const int col_num, const irr::core::stringw newName,
|
void renameCell(const std::string internalName, const int col_num,
|
||||||
const int icon=-1)
|
const irr::core::stringw &newName, const int icon=-1)
|
||||||
{
|
{
|
||||||
const int id = getItemID(internalName);
|
const int id = getItemID(internalName);
|
||||||
assert(id != -1);
|
assert(id != -1);
|
||||||
@ -211,14 +214,14 @@ namespace GUIEngine
|
|||||||
* \brief Make an item red to mark an error, for instance
|
* \brief Make an item red to mark an error, for instance
|
||||||
* \pre may only be called after the widget has been added to the screen with add()
|
* \pre may only be called after the widget has been added to the screen with add()
|
||||||
*/
|
*/
|
||||||
void markItemRed(const std::string internalName, bool red=true)
|
void markItemRed(const std::string &internalName, bool red=true)
|
||||||
{
|
{
|
||||||
const int id = getItemID(internalName);
|
const int id = getItemID(internalName);
|
||||||
assert(id != -1);
|
assert(id != -1);
|
||||||
markItemRed( id, red );
|
markItemRed( id, red );
|
||||||
}
|
}
|
||||||
|
|
||||||
void markItemBlue(const std::string internalName, bool blue=true)
|
void markItemBlue(const std::string &internalName, bool blue=true)
|
||||||
{
|
{
|
||||||
const int id = getItemID(internalName);
|
const int id = getItemID(internalName);
|
||||||
assert(id != -1);
|
assert(id != -1);
|
||||||
|
@ -212,7 +212,7 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
|||||||
m_model_view->setRotateContinuously( 35.0f );
|
m_model_view->setRotateContinuously( 35.0f );
|
||||||
|
|
||||||
// ---- Kart name label
|
// ---- Kart name label
|
||||||
m_kart_name = new LabelWidget(true, true);
|
m_kart_name = new LabelWidget(false, true);
|
||||||
m_kart_name->setText(props->getName(), false);
|
m_kart_name->setText(props->getName(), false);
|
||||||
m_kart_name->m_properties[PROP_TEXT_ALIGN] = "center";
|
m_kart_name->m_properties[PROP_TEXT_ALIGN] = "center";
|
||||||
m_kart_name->m_properties[PROP_ID] =
|
m_kart_name->m_properties[PROP_ID] =
|
||||||
|
@ -373,7 +373,7 @@ void RibbonWidget::add()
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void RibbonWidget::addTextChild(const wchar_t* text, const std::string id)
|
void RibbonWidget::addTextChild(const wchar_t* text, const std::string &id)
|
||||||
{
|
{
|
||||||
// This method should only be called BEFORE a widget is added
|
// This method should only be called BEFORE a widget is added
|
||||||
assert(m_element == NULL);
|
assert(m_element == NULL);
|
||||||
|
@ -166,7 +166,7 @@ namespace GUIEngine
|
|||||||
* \pre only valid for ribbons that take text-only contents
|
* \pre only valid for ribbons that take text-only contents
|
||||||
* (e.g. tab bars)
|
* (e.g. tab bars)
|
||||||
*/
|
*/
|
||||||
void addTextChild(const wchar_t* text, const std::string id);
|
void addTextChild(const wchar_t* text, const std::string &id);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Dynamically (at runtime) add an icon item to this ribbon.
|
/** \brief Dynamically (at runtime) add an icon item to this ribbon.
|
||||||
|
@ -163,11 +163,11 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
|
|||||||
{
|
{
|
||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
// I18N: Name of the black button on xbox controller
|
// I18N: Name of the black button on xbox controller
|
||||||
case 2: return _("Black");
|
case 2: return _("Black");
|
||||||
case 3: return "X";
|
case 3: return "X";
|
||||||
case 4: return "Y";
|
case 4: return "Y";
|
||||||
// I18N: Name of the white button on xbox controller
|
// I18N: Name of the white button on xbox controller
|
||||||
case 5: return _("White");
|
case 5: return _("White");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,15 +175,25 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
|
|||||||
{
|
{
|
||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 2: return _("Left trigger");
|
case 2: return _("Left trigger");
|
||||||
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb right")
|
// I18N: name of buttons on gamepads
|
||||||
: _("Right thumb left");
|
case 3: return (ad == Input::AD_POSITIVE) ? _("Right thumb right")
|
||||||
case 4: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
|
// I18N: name of buttons on gamepads
|
||||||
: _("Right thumb up");
|
: _("Right thumb left");
|
||||||
|
case // I18N: name of buttons on gamepads
|
||||||
|
4: return (ad == Input::AD_POSITIVE) ? _("Right thumb down")
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
|
: _("Right thumb up");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 5: return _("Right trigger");
|
case 5: return _("Right trigger");
|
||||||
case 6: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
// I18N: name of buttons on gamepads
|
||||||
|
case 6: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
: _("DPad left");
|
: _("DPad left");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 7: return (ad == Input::AD_POSITIVE) ? _("DPad down")
|
case 7: return (ad == Input::AD_POSITIVE) ? _("DPad down")
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
: _("DPad up");
|
: _("DPad up");
|
||||||
} // switch
|
} // switch
|
||||||
} // stickmotion
|
} // stickmotion
|
||||||
@ -198,11 +208,17 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
|
|||||||
case 1: return "B";
|
case 1: return "B";
|
||||||
case 2: return "X";
|
case 2: return "X";
|
||||||
case 3: return "Y";
|
case 3: return "Y";
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 4: return _("Left bumper");
|
case 4: return _("Left bumper");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 5: return _("Right bumper");
|
case 5: return _("Right bumper");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 6: return _("Back");
|
case 6: return _("Back");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 7: return _("Start");
|
case 7: return _("Start");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 8: return _("Left thumb button");
|
case 8: return _("Left thumb button");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case 9: return _("Right thumb button");
|
case 9: return _("Right thumb button");
|
||||||
default: return DeviceConfig::getBindingAsString(action);
|
default: return DeviceConfig::getBindingAsString(action);
|
||||||
} // switch
|
} // switch
|
||||||
@ -211,19 +227,33 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
|
|||||||
{
|
{
|
||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
case 0: return (ad==Input::AD_POSITIVE) ? _("Left thumb right")
|
case 0: return (ad==Input::AD_POSITIVE) ? _("Left thumb right")
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
: _("Left thumb left");
|
: _("Left thumb left");
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
case 1: return (ad==Input::AD_POSITIVE) ? _("Left thumb down")
|
case 1: return (ad==Input::AD_POSITIVE) ? _("Left thumb down")
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
: _("Left thumb up");
|
: _("Left thumb up");
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
case 2: return (ad==Input::AD_POSITIVE) ? _("Left trigger")
|
case 2: return (ad==Input::AD_POSITIVE) ? _("Left trigger")
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
: _("Right trigger");
|
: _("Right trigger");
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
|
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
: _("Right thumb up");
|
: _("Right thumb up");
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
case 4: return (ad==Input::AD_POSITIVE) ? _("Right thumb right")
|
case 4: return (ad==Input::AD_POSITIVE) ? _("Right thumb right")
|
||||||
|
// I18N: name of stick on gamepads
|
||||||
: _("Right thumb left");
|
: _("Right thumb left");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case Input::HAT_H_ID: return (ad == Input::AD_POSITIVE) ? _("DPad up")
|
case Input::HAT_H_ID: return (ad == Input::AD_POSITIVE) ? _("DPad up")
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
: _("DPad down");
|
: _("DPad down");
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
case Input::HAT_V_ID: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
case Input::HAT_V_ID: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
||||||
|
// I18N: name of buttons on gamepads
|
||||||
: _("DPad left");
|
: _("DPad left");
|
||||||
} // switch
|
} // switch
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ const void XMLNode::getNodes(const std::string &s, std::vector<XMLNode*>& out) c
|
|||||||
*/
|
*/
|
||||||
int XMLNode::get(const std::string &attribute, std::string *value) const
|
int XMLNode::get(const std::string &attribute, std::string *value) const
|
||||||
{
|
{
|
||||||
if(m_attributes.size()==0) return 0;
|
if(m_attributes.empty()) return 0;
|
||||||
std::map<std::string, core::stringw>::const_iterator o;
|
std::map<std::string, core::stringw>::const_iterator o;
|
||||||
o = m_attributes.find(attribute);
|
o = m_attributes.find(attribute);
|
||||||
if(o==m_attributes.end()) return 0;
|
if(o==m_attributes.end()) return 0;
|
||||||
@ -184,7 +184,7 @@ int XMLNode::get(const std::string &attribute, std::string *value) const
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
int XMLNode::get(const std::string &attribute, core::stringw *value) const
|
int XMLNode::get(const std::string &attribute, core::stringw *value) const
|
||||||
{
|
{
|
||||||
if(m_attributes.size()==0) return 0;
|
if(m_attributes.empty()) return 0;
|
||||||
std::map<std::string, core::stringw>::const_iterator o;
|
std::map<std::string, core::stringw>::const_iterator o;
|
||||||
o = m_attributes.find(attribute);
|
o = m_attributes.find(attribute);
|
||||||
if(o==m_attributes.end()) return 0;
|
if(o==m_attributes.end()) return 0;
|
||||||
|
@ -57,7 +57,7 @@ const char* inet_ntop(int af, const void* src, char* dst, int cnt)
|
|||||||
FILE* STKHost::m_log_file = NULL;
|
FILE* STKHost::m_log_file = NULL;
|
||||||
pthread_mutex_t STKHost::m_log_mutex;
|
pthread_mutex_t STKHost::m_log_mutex;
|
||||||
|
|
||||||
void STKHost::logPacket(const NetworkString ns, bool incoming)
|
void STKHost::logPacket(const NetworkString &ns, bool incoming)
|
||||||
{
|
{
|
||||||
if (m_log_file == NULL)
|
if (m_log_file == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -69,7 +69,7 @@ class STKHost
|
|||||||
* \param incoming : True if the packet comes from a peer.
|
* \param incoming : True if the packet comes from a peer.
|
||||||
* False if it's sent to a peer.
|
* False if it's sent to a peer.
|
||||||
*/
|
*/
|
||||||
static void logPacket(const NetworkString ns, bool incoming);
|
static void logPacket(const NetworkString &ns, bool incoming);
|
||||||
|
|
||||||
/*! \brief Thread function checking if data is received.
|
/*! \brief Thread function checking if data is received.
|
||||||
* This function tries to get data from network low-level functions as
|
* This function tries to get data from network low-level functions as
|
||||||
|
@ -177,9 +177,24 @@ namespace Online
|
|||||||
struct curl_slist *chunk = NULL;
|
struct curl_slist *chunk = NULL;
|
||||||
chunk = curl_slist_append(chunk, "Host: api.stkaddons.net");
|
chunk = curl_slist_append(chunk, "Host: api.stkaddons.net");
|
||||||
curl_easy_setopt(m_curl_session, CURLOPT_HTTPHEADER, chunk);
|
curl_easy_setopt(m_curl_session, CURLOPT_HTTPHEADER, chunk);
|
||||||
curl_easy_setopt(m_curl_session, CURLOPT_CAINFO,
|
CURLcode error = curl_easy_setopt(m_curl_session, CURLOPT_CAINFO,
|
||||||
file_manager->getAsset("web.tuxfamily.org.pem").c_str());
|
file_manager->getAsset("web.tuxfamily.org.pem").c_str());
|
||||||
curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYPEER, 1L);
|
if (error != CURLE_OK)
|
||||||
|
{
|
||||||
|
Log::error("HTTPRequest", "Error setting CAINFO to '%s'",
|
||||||
|
file_manager->getAsset("web.tuxfamily.org.pem").c_str());
|
||||||
|
Log::error("HTTPRequest", "Error %d: '%s'.", error,
|
||||||
|
curl_easy_strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case that there are authentication problems (e.g. on osx)
|
||||||
|
// disable peer verification. Not ideal, but still better than
|
||||||
|
// no encryption.
|
||||||
|
if (UserConfigParams::m_verify_peer)
|
||||||
|
curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||||
|
else
|
||||||
|
curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYHOST, 0L);
|
curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
}
|
}
|
||||||
} // prepareOperation
|
} // prepareOperation
|
||||||
|
@ -232,8 +232,6 @@ btScalar btKart::rayCast(unsigned int index)
|
|||||||
|
|
||||||
updateWheelTransformsWS( wheel,false);
|
updateWheelTransformsWS( wheel,false);
|
||||||
|
|
||||||
btScalar depth = -1;
|
|
||||||
|
|
||||||
btScalar max_susp_len = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius
|
btScalar max_susp_len = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius
|
||||||
+ wheel.m_maxSuspensionTravelCm*0.01f;
|
+ wheel.m_maxSuspensionTravelCm*0.01f;
|
||||||
|
|
||||||
@ -255,7 +253,7 @@ btScalar btKart::rayCast(unsigned int index)
|
|||||||
|
|
||||||
wheel.m_raycastInfo.m_groundObject = 0;
|
wheel.m_raycastInfo.m_groundObject = 0;
|
||||||
|
|
||||||
depth = raylen * rayResults.m_distFraction;
|
btScalar depth = raylen * rayResults.m_distFraction;
|
||||||
if (object && depth < max_susp_len)
|
if (object && depth < max_susp_len)
|
||||||
{
|
{
|
||||||
wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
|
wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
|
||||||
@ -719,8 +717,6 @@ struct btWheelContactPoint
|
|||||||
btScalar btKart::calcRollingFriction(btWheelContactPoint& contactPoint)
|
btScalar btKart::calcRollingFriction(btWheelContactPoint& contactPoint)
|
||||||
{
|
{
|
||||||
|
|
||||||
btScalar j1=0.f;
|
|
||||||
|
|
||||||
const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
|
const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
|
||||||
|
|
||||||
btVector3 rel_pos1 = contactPosWorld
|
btVector3 rel_pos1 = contactPosWorld
|
||||||
@ -737,7 +733,7 @@ btScalar btKart::calcRollingFriction(btWheelContactPoint& contactPoint)
|
|||||||
btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
|
btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
|
||||||
|
|
||||||
// calculate j that moves us to zero relative velocity
|
// calculate j that moves us to zero relative velocity
|
||||||
j1 = -vrel * contactPoint.m_jacDiagABInv;
|
btScalar j1 = -vrel * contactPoint.m_jacDiagABInv;
|
||||||
btSetMin(j1, maxImpulse);
|
btSetMin(j1, maxImpulse);
|
||||||
btSetMax(j1, -maxImpulse);
|
btSetMax(j1, -maxImpulse);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ private:
|
|||||||
/** Tests if two collision pairs involve the same objects. This test
|
/** Tests if two collision pairs involve the same objects. This test
|
||||||
* is simplified (i.e. no test if p.b==a and p.a==b) since the
|
* is simplified (i.e. no test if p.b==a and p.a==b) since the
|
||||||
* elements are sorted. */
|
* elements are sorted. */
|
||||||
bool operator==(const CollisionPair p)
|
bool operator==(const CollisionPair &p)
|
||||||
{
|
{
|
||||||
return (p.m_up[0]==m_up[0] && p.m_up[1]==m_up[1]);
|
return (p.m_up[0]==m_up[0] && p.m_up[1]==m_up[1]);
|
||||||
} // operator==
|
} // operator==
|
||||||
|
@ -175,10 +175,10 @@ void HighscoreManager::saveHighscores()
|
|||||||
* Returns the high scores entry for a specific type of race.
|
* Returns the high scores entry for a specific type of race.
|
||||||
* Creates one if none exists yet.
|
* Creates one if none exists yet.
|
||||||
*/
|
*/
|
||||||
Highscores* HighscoreManager::getHighscores(const Highscores::HighscoreType highscore_type,
|
Highscores* HighscoreManager::getHighscores(const Highscores::HighscoreType &highscore_type,
|
||||||
int num_karts,
|
int num_karts,
|
||||||
const RaceManager::Difficulty difficulty,
|
const RaceManager::Difficulty difficulty,
|
||||||
const std::string trackName,
|
const std::string &trackName,
|
||||||
const int number_of_laps,
|
const int number_of_laps,
|
||||||
const bool reverse)
|
const bool reverse)
|
||||||
{
|
{
|
||||||
|
@ -49,10 +49,10 @@ public:
|
|||||||
HighscoreManager();
|
HighscoreManager();
|
||||||
~HighscoreManager();
|
~HighscoreManager();
|
||||||
void saveHighscores();
|
void saveHighscores();
|
||||||
Highscores *getHighscores(const Highscores::HighscoreType highscore_type,
|
Highscores *getHighscores(const Highscores::HighscoreType &highscore_type,
|
||||||
int num_karts,
|
int num_karts,
|
||||||
const RaceManager::Difficulty difficulty,
|
const RaceManager::Difficulty difficulty,
|
||||||
const std::string trackName,
|
const std::string &trackName,
|
||||||
const int number_of_laps,
|
const int number_of_laps,
|
||||||
const bool reverse);
|
const bool reverse);
|
||||||
}; // HighscoreManager
|
}; // HighscoreManager
|
||||||
|
@ -26,14 +26,14 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
Highscores::Highscores(const HighscoreType highscore_type,
|
Highscores::Highscores(const HighscoreType &highscore_type,
|
||||||
int num_karts,
|
int num_karts,
|
||||||
const RaceManager::Difficulty difficulty,
|
const RaceManager::Difficulty &difficulty,
|
||||||
const std::string trackName,
|
const std::string &track_name,
|
||||||
const int number_of_laps,
|
const int number_of_laps,
|
||||||
const bool reverse)
|
const bool reverse)
|
||||||
{
|
{
|
||||||
m_track = trackName;
|
m_track = track_name;
|
||||||
m_highscore_type = highscore_type;
|
m_highscore_type = highscore_type;
|
||||||
m_number_of_karts = num_karts;
|
m_number_of_karts = num_karts;
|
||||||
m_difficulty = difficulty;
|
m_difficulty = difficulty;
|
||||||
@ -135,10 +135,10 @@ void Highscores::writeEntry(UTFWriter &writer)
|
|||||||
} // writeEntry
|
} // writeEntry
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
int Highscores::matches(HighscoreType highscore_type,
|
int Highscores::matches(const HighscoreType &highscore_type,
|
||||||
int num_karts, RaceManager::Difficulty difficulty,
|
int num_karts, const RaceManager::Difficulty &difficulty,
|
||||||
const std::string track, const int number_of_laps,
|
const std::string &track, const int number_of_laps,
|
||||||
const bool reverse)
|
const bool reverse)
|
||||||
{
|
{
|
||||||
return (m_highscore_type == highscore_type &&
|
return (m_highscore_type == highscore_type &&
|
||||||
m_track == track &&
|
m_track == track &&
|
||||||
|
@ -53,9 +53,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
/** Creates a new entry
|
/** Creates a new entry
|
||||||
*/
|
*/
|
||||||
Highscores (const Highscores::HighscoreType highscore_type,
|
Highscores (const Highscores::HighscoreType &highscore_type,
|
||||||
int num_karts, const RaceManager::Difficulty difficulty,
|
int num_karts, const RaceManager::Difficulty &difficulty,
|
||||||
const std::string trackName, const int number_of_laps,
|
const std::string &trackName, const int number_of_laps,
|
||||||
const bool reverse);
|
const bool reverse);
|
||||||
/** Creates an entry from a file
|
/** Creates an entry from a file
|
||||||
*/
|
*/
|
||||||
@ -63,9 +63,9 @@ public:
|
|||||||
|
|
||||||
void readEntry (const XMLNode &node);
|
void readEntry (const XMLNode &node);
|
||||||
void writeEntry(UTFWriter &writer);
|
void writeEntry(UTFWriter &writer);
|
||||||
int matches (HighscoreType highscore_type, int num_karts,
|
int matches (const HighscoreType &highscore_type, int num_karts,
|
||||||
const RaceManager::Difficulty difficulty,
|
const RaceManager::Difficulty &difficulty,
|
||||||
const std::string track, const int number_of_laps,
|
const std::string &track, const int number_of_laps,
|
||||||
const bool reverse);
|
const bool reverse);
|
||||||
int addData (const std::string& kart_name,
|
int addData (const std::string& kart_name,
|
||||||
const irr::core::stringw& name, const float time);
|
const irr::core::stringw& name, const float time);
|
||||||
|
@ -798,7 +798,7 @@ void RaceManager::startSingleRace(const std::string &track_ident,
|
|||||||
bool from_overworld)
|
bool from_overworld)
|
||||||
{
|
{
|
||||||
StateManager::get()->enterGameState();
|
StateManager::get()->enterGameState();
|
||||||
setTrack(track_ident.c_str());
|
setTrack(track_ident);
|
||||||
|
|
||||||
if (num_laps != -1) setNumLaps( num_laps );
|
if (num_laps != -1) setNumLaps( num_laps );
|
||||||
|
|
||||||
|
@ -43,4 +43,4 @@ FILE* ReplayBase::openReplayFile(bool writeable)
|
|||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
} // openReplayFilen
|
} // openReplayFile
|
||||||
|
@ -57,7 +57,7 @@ void CreateServerScreen::loadedFromFile()
|
|||||||
|
|
||||||
m_name_widget = getWidget<TextBoxWidget>("name");
|
m_name_widget = getWidget<TextBoxWidget>("name");
|
||||||
assert(m_name_widget != NULL);
|
assert(m_name_widget != NULL);
|
||||||
m_name_widget->setText(PlayerManager::getCurrentOnlineUserName() + _("'s server"));
|
m_name_widget->setText(_("%s's server", PlayerManager::getCurrentOnlineUserName()));
|
||||||
m_max_players_widget = getWidget<SpinnerWidget>("max_players");
|
m_max_players_widget = getWidget<SpinnerWidget>("max_players");
|
||||||
assert(m_max_players_widget != NULL);
|
assert(m_max_players_widget != NULL);
|
||||||
m_max_players_widget->setValue(8);
|
m_max_players_widget->setValue(8);
|
||||||
|
@ -348,10 +348,9 @@ void AddonsLoading::doInstall()
|
|||||||
{
|
{
|
||||||
delete m_download_request;
|
delete m_download_request;
|
||||||
m_download_request = NULL;
|
m_download_request = NULL;
|
||||||
bool error=false;
|
|
||||||
|
|
||||||
assert(!m_addon.isInstalled() || m_addon.needsUpdate());
|
assert(!m_addon.isInstalled() || m_addon.needsUpdate());
|
||||||
error = !addons_manager->install(m_addon);
|
bool error = !addons_manager->install(m_addon);
|
||||||
if(error)
|
if(error)
|
||||||
{
|
{
|
||||||
core::stringw msg = StringUtils::insertValues(
|
core::stringw msg = StringUtils::insertValues(
|
||||||
@ -386,9 +385,7 @@ void AddonsLoading::doUninstall()
|
|||||||
{
|
{
|
||||||
delete m_download_request;
|
delete m_download_request;
|
||||||
m_download_request = NULL;
|
m_download_request = NULL;
|
||||||
bool error=false;
|
bool error = !addons_manager->uninstall(m_addon);
|
||||||
|
|
||||||
error = !addons_manager->uninstall(m_addon);
|
|
||||||
if(error)
|
if(error)
|
||||||
{
|
{
|
||||||
Log::warn("Addons", "Directory '%s' can not be removed.",
|
Log::warn("Addons", "Directory '%s' can not be removed.",
|
||||||
|
@ -68,25 +68,28 @@ MessageDialog::~MessageDialog()
|
|||||||
// ------------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void MessageDialog::doInit(MessageDialogType type,
|
void MessageDialog::doInit(MessageDialogType type,
|
||||||
IConfirmDialogListener* listener, bool own_listener)
|
IConfirmDialogListener* listener, bool own_listener)
|
||||||
{
|
{
|
||||||
if (StateManager::get()->getGameState() == GUIEngine::GAME)
|
if (StateManager::get()->getGameState() == GUIEngine::GAME)
|
||||||
{
|
{
|
||||||
World::getWorld()->schedulePause(World::IN_GAME_MENU_PHASE);
|
World::getWorld()->schedulePause(World::IN_GAME_MENU_PHASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_type = type;
|
||||||
loadFromFile("confirm_dialog.stkgui");
|
|
||||||
|
|
||||||
m_listener = listener;
|
m_listener = listener;
|
||||||
m_own_listener = own_listener;
|
m_own_listener = own_listener;
|
||||||
|
|
||||||
|
loadFromFile("confirm_dialog.stkgui");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDialog::loadedFromFile()
|
||||||
|
{
|
||||||
LabelWidget* message = getWidget<LabelWidget>("title");
|
LabelWidget* message = getWidget<LabelWidget>("title");
|
||||||
message->setText( m_msg.c_str(), false );
|
message->setText( m_msg.c_str(), false );
|
||||||
|
|
||||||
// If the dialog is a simple 'OK' dialog, then hide the "Yes" button and
|
// If the dialog is a simple 'OK' dialog, then hide the "Yes" button and
|
||||||
// change "Cancel" to "OK"
|
// change "Cancel" to "OK"
|
||||||
if (type == MessageDialog::MESSAGE_DIALOG_OK)
|
if (m_type == MessageDialog::MESSAGE_DIALOG_OK)
|
||||||
{
|
{
|
||||||
ButtonWidget* yesbtn = getWidget<ButtonWidget>("confirm");
|
ButtonWidget* yesbtn = getWidget<ButtonWidget>("confirm");
|
||||||
yesbtn->setVisible(false);
|
yesbtn->setVisible(false);
|
||||||
@ -95,13 +98,13 @@ void MessageDialog::doInit(MessageDialogType type,
|
|||||||
cancelbtn->setText(_("OK"));
|
cancelbtn->setText(_("OK"));
|
||||||
cancelbtn->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
cancelbtn->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||||
}
|
}
|
||||||
else if (type == MessageDialog::MESSAGE_DIALOG_YESNO)
|
else if (m_type == MessageDialog::MESSAGE_DIALOG_YESNO)
|
||||||
{
|
{
|
||||||
ButtonWidget* cancelbtn = getWidget<ButtonWidget>("cancel");
|
ButtonWidget* cancelbtn = getWidget<ButtonWidget>("cancel");
|
||||||
cancelbtn->setText(_("No"));
|
cancelbtn->setText(_("No"));
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (type == MessageDialog::MESSAGE_DIALOG_OK_CANCEL)
|
else if (m_type == MessageDialog::MESSAGE_DIALOG_OK_CANCEL)
|
||||||
{
|
{
|
||||||
// In case of a OK_CANCEL dialog, change the text from 'Yes' to 'Ok'
|
// In case of a OK_CANCEL dialog, change the text from 'Yes' to 'Ok'
|
||||||
ButtonWidget* yesbtn = getWidget<ButtonWidget>("confirm");
|
ButtonWidget* yesbtn = getWidget<ButtonWidget>("confirm");
|
||||||
@ -109,7 +112,6 @@ void MessageDialog::doInit(MessageDialogType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void MessageDialog::onEnterPressedInternal()
|
void MessageDialog::onEnterPressedInternal()
|
||||||
|
@ -64,6 +64,8 @@ public:
|
|||||||
enum MessageDialogType { MESSAGE_DIALOG_OK, MESSAGE_DIALOG_CONFIRM,
|
enum MessageDialogType { MESSAGE_DIALOG_OK, MESSAGE_DIALOG_CONFIRM,
|
||||||
MESSAGE_DIALOG_OK_CANCEL, MESSAGE_DIALOG_YESNO };
|
MESSAGE_DIALOG_OK_CANCEL, MESSAGE_DIALOG_YESNO };
|
||||||
|
|
||||||
|
MessageDialogType m_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
IConfirmDialogListener* m_listener;
|
IConfirmDialogListener* m_listener;
|
||||||
@ -96,6 +98,8 @@ public:
|
|||||||
virtual void load();
|
virtual void load();
|
||||||
|
|
||||||
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
|
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
|
||||||
|
|
||||||
|
virtual void loadedFromFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ void UserInfoDialog::sendFriendRequest()
|
|||||||
true, false);
|
true, false);
|
||||||
ProfileManager::get()->getProfileByID(id)->setRelationInfo(info);
|
ProfileManager::get()->getProfileByID(id)->setRelationInfo(info);
|
||||||
OnlineProfileFriends::getInstance()->refreshFriendsList();
|
OnlineProfileFriends::getInstance()->refreshFriendsList();
|
||||||
info_text = _("Friend request send!");
|
info_text = _("Friend request sent!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -482,7 +482,7 @@ void UserInfoDialog::onUpdate(float dt)
|
|||||||
bool enter_profile = m_enter_profile;
|
bool enter_profile = m_enter_profile;
|
||||||
ModalDialog::dismiss();
|
ModalDialog::dismiss();
|
||||||
if (enter_profile)
|
if (enter_profile)
|
||||||
StateManager::get()->replaceTopMostScreen(OnlineProfileAchievements::getInstance());
|
StateManager::get()->replaceTopMostScreen(TabOnlineProfileAchievements::getInstance());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} // onUpdate
|
} // onUpdate
|
||||||
|
@ -854,8 +854,7 @@ void KartSelectionScreen::updateKartWidgetModel(uint8_t widget_id,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_kart_widgets[widget_id].m_kart_name
|
m_kart_widgets[widget_id].m_kart_name
|
||||||
->setText(_("Locked : solve active challenges to gain "
|
->setText(_("Locked : solve active challenges to gain access to more!"), false );
|
||||||
"access to more!"), false );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1446,8 +1445,7 @@ void KartSelectionScreen::setKartsFromCurrentGroup()
|
|||||||
const KartProperties* prop = karts.get(i);
|
const KartProperties* prop = karts.get(i);
|
||||||
if (PlayerManager::getCurrentPlayer()->isLocked(prop->getIdent()))
|
if (PlayerManager::getCurrentPlayer()->isLocked(prop->getIdent()))
|
||||||
{
|
{
|
||||||
w->addItem(_("Locked : solve active challenges to gain access "
|
w->addItem(_("Locked : solve active challenges to gain access to more!"),
|
||||||
"to more!"),
|
|
||||||
ID_LOCKED + prop->getIdent(),
|
ID_LOCKED + prop->getIdent(),
|
||||||
prop->getAbsoluteIconFile(), LOCKED_BADGE,
|
prop->getAbsoluteIconFile(), LOCKED_BADGE,
|
||||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||||
|
@ -105,7 +105,7 @@ void OnlineProfileBase::init()
|
|||||||
m_header->setText(_("Your profile"), false);
|
m_header->setText(_("Your profile"), false);
|
||||||
else if (m_visiting_profile)
|
else if (m_visiting_profile)
|
||||||
{
|
{
|
||||||
m_header->setText(m_visiting_profile->getUserName() + _("'s profile"), false);
|
m_header->setText(_("%s's profile", m_visiting_profile->getUserName()), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Log::error("OnlineProfileBase", "No visting profile");
|
Log::error("OnlineProfileBase", "No visting profile");
|
||||||
|
@ -837,12 +837,11 @@ void RaceGUI::drawLap(const AbstractKart* kart,
|
|||||||
- m_lap_width - 10;
|
- m_lap_width - 10;
|
||||||
pos.LowerRightCorner.X = viewport.LowerRightCorner.X;
|
pos.LowerRightCorner.X = viewport.LowerRightCorner.X;
|
||||||
|
|
||||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
|
||||||
static video::SColor color = video::SColor(255, 255, 255, 255);
|
static video::SColor color = video::SColor(255, 255, 255, 255);
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << lap + 1 << "/" << race_manager->getNumLaps();
|
out << lap + 1 << "/" << race_manager->getNumLaps();
|
||||||
|
|
||||||
font = GUIEngine::getHighresDigitFont();
|
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||||
font->setScale(scaling.Y < 1.0f ? 0.5f: 1.0f);
|
font->setScale(scaling.Y < 1.0f ? 0.5f: 1.0f);
|
||||||
font->draw(out.str().c_str(), pos, color);
|
font->draw(out.str().c_str(), pos, color);
|
||||||
font->setScale(1.0f);
|
font->setScale(1.0f);
|
||||||
|
@ -219,11 +219,9 @@ void RaceGUIOverworld::drawTrophyPoints()
|
|||||||
core::rect<s32> pos(UserConfigParams::m_width - dist_from_right, 10,
|
core::rect<s32> pos(UserConfigParams::m_width - dist_from_right, 10,
|
||||||
UserConfigParams::m_width , 50);
|
UserConfigParams::m_width , 50);
|
||||||
|
|
||||||
bool vcenter = false;
|
|
||||||
|
|
||||||
gui::ScalableFont* font = GUIEngine::getFont();
|
gui::ScalableFont* font = GUIEngine::getFont();
|
||||||
|
|
||||||
vcenter = true;
|
bool vcenter = true;
|
||||||
|
|
||||||
const int size = UserConfigParams::m_width/20;
|
const int size = UserConfigParams::m_width/20;
|
||||||
core::rect<s32> dest(size, pos.UpperLeftCorner.Y,
|
core::rect<s32> dest(size, pos.UpperLeftCorner.Y,
|
||||||
|
@ -111,8 +111,14 @@ void BaseUserScreen::init()
|
|||||||
|
|
||||||
// Select the current player. That can only be done after
|
// Select the current player. That can only be done after
|
||||||
// updateItemDisplay is called.
|
// updateItemDisplay is called.
|
||||||
if(current_player_index != -1)
|
if (current_player_index != -1)
|
||||||
selectUser(current_player_index);
|
{
|
||||||
|
// Only set focus in case of non-tabbed version (so that keyboard
|
||||||
|
// or gamepad navigation with tabs works as expected, i.e. you can
|
||||||
|
// select the next tab without having to go up to the tab list first.
|
||||||
|
if(!getWidget<RibbonWidget>("options_choice"))
|
||||||
|
selectUser(current_player_index);
|
||||||
|
}
|
||||||
// no current player found
|
// no current player found
|
||||||
// The first player is the most frequently used, so select it
|
// The first player is the most frequently used, so select it
|
||||||
else if (PlayerManager::get()->getNumPlayers() > 0)
|
else if (PlayerManager::get()->getNumPlayers() > 0)
|
||||||
@ -586,8 +592,8 @@ void BaseUserScreen::unloaded()
|
|||||||
*/
|
*/
|
||||||
void TabbedUserScreen::init()
|
void TabbedUserScreen::init()
|
||||||
{
|
{
|
||||||
RibbonWidget* tab_bar = this->getWidget<RibbonWidget>("options_choice");
|
RibbonWidget* tab_bar = getWidget<RibbonWidget>("options_choice");
|
||||||
if (tab_bar != NULL) tab_bar->select("tab_players", PLAYER_ID_GAME_MASTER);
|
if (tab_bar) tab_bar->select("tab_players", PLAYER_ID_GAME_MASTER);
|
||||||
tab_bar->getRibbonChildren()[0].setTooltip( _("Graphics") );
|
tab_bar->getRibbonChildren()[0].setTooltip( _("Graphics") );
|
||||||
tab_bar->getRibbonChildren()[1].setTooltip( _("Audio") );
|
tab_bar->getRibbonChildren()[1].setTooltip( _("Audio") );
|
||||||
tab_bar->getRibbonChildren()[2].setTooltip(_("User Interface"));
|
tab_bar->getRibbonChildren()[2].setTooltip(_("User Interface"));
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
namespace tinygettext {
|
namespace tinygettext {
|
||||||
|
|
||||||
static bool has_suffix(const std::string& lhs, const std::string rhs)
|
static bool has_suffix(const std::string& lhs, const std::string &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.length() < rhs.length())
|
if (lhs.length() < rhs.length())
|
||||||
return false;
|
return false;
|
||||||
|
@ -223,7 +223,7 @@ next:
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool has_prefix(const std::string& lhs, const std::string rhs)
|
static bool has_prefix(const std::string& lhs, const std::string &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.length() < rhs.length())
|
if (lhs.length() < rhs.length())
|
||||||
return false;
|
return false;
|
||||||
|
@ -122,7 +122,7 @@ void CheckStructure::update(float dt)
|
|||||||
* \param int kart_index For which the status should be changed.
|
* \param int kart_index For which the status should be changed.
|
||||||
* \param change_state How to change the state (active, deactivate, toggle).
|
* \param change_state How to change the state (active, deactivate, toggle).
|
||||||
*/
|
*/
|
||||||
void CheckStructure::changeStatus(const std::vector<int> indices,
|
void CheckStructure::changeStatus(const std::vector<int> &indices,
|
||||||
int kart_index,
|
int kart_index,
|
||||||
ChangeState change_state)
|
ChangeState change_state)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ private:
|
|||||||
|
|
||||||
enum ChangeState {CS_DEACTIVATE, CS_ACTIVATE, CS_TOGGLE};
|
enum ChangeState {CS_DEACTIVATE, CS_ACTIVATE, CS_TOGGLE};
|
||||||
|
|
||||||
void changeStatus(const std::vector<int> indices, int kart_index,
|
void changeStatus(const std::vector<int> &indices, int kart_index,
|
||||||
ChangeState change_state);
|
ChangeState change_state);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -45,13 +45,13 @@ void ModelDefinitionLoader::addModelDefinition(const XMLNode* xml)
|
|||||||
std::string lodgroup;
|
std::string lodgroup;
|
||||||
xml->get("lod_group", &lodgroup);
|
xml->get("lod_group", &lodgroup);
|
||||||
|
|
||||||
bool tangent = false;
|
bool skeletal_animation = false;
|
||||||
xml->get("tangents", &tangent);
|
xml->get("skeletal-animation", &skeletal_animation);
|
||||||
|
|
||||||
std::string model_name;
|
std::string model_name;
|
||||||
xml->get("model", &model_name);
|
xml->get("model", &model_name);
|
||||||
|
|
||||||
m_lod_groups[lodgroup].push_back(ModelDefinition(xml, (int)lod_distance, model_name, tangent));
|
m_lod_groups[lodgroup].push_back(ModelDefinition(xml, (int)lod_distance, model_name, false, skeletal_animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -72,28 +72,51 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
|
|||||||
lod_node->updateAbsolutePosition();
|
lod_node->updateAbsolutePosition();
|
||||||
for (unsigned int m=0; m<group.size(); m++)
|
for (unsigned int m=0; m<group.size(); m++)
|
||||||
{
|
{
|
||||||
// TODO: check whether the mesh contains animations or not?
|
if (group[m].m_skeletal_animation)
|
||||||
scene::IMesh* a_mesh = irr_driver->getMesh(group[m].m_model_file);
|
|
||||||
|
|
||||||
if (!a_mesh)
|
|
||||||
{
|
{
|
||||||
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
|
scene::IAnimatedMesh* a_mesh = irr_driver->getAnimatedMesh(group[m].m_model_file);
|
||||||
group[m].m_model_file.c_str());
|
if (!a_mesh)
|
||||||
continue;
|
{
|
||||||
|
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
|
||||||
|
group[m].m_model_file.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
irr_driver->setAllMaterialFlags(a_mesh);
|
||||||
|
|
||||||
|
a_mesh->grab();
|
||||||
|
//cache.push_back(a_mesh);
|
||||||
|
irr_driver->grabAllTextures(a_mesh);
|
||||||
|
m_track->addCachedMesh(a_mesh);
|
||||||
|
scene::IAnimatedMeshSceneNode* scene_node = irr_driver->addAnimatedMesh(a_mesh, group[m].m_model_file);
|
||||||
|
|
||||||
|
m_track->handleAnimatedTextures(scene_node, *group[m].m_xml);
|
||||||
|
|
||||||
|
lod_node->add(group[m].m_distance, scene_node, true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scene::IMesh* a_mesh = irr_driver->getMesh(group[m].m_model_file);
|
||||||
|
if (!a_mesh)
|
||||||
|
{
|
||||||
|
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
|
||||||
|
group[m].m_model_file.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
|
a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
|
||||||
irr_driver->setAllMaterialFlags(a_mesh);
|
irr_driver->setAllMaterialFlags(a_mesh);
|
||||||
|
|
||||||
a_mesh->grab();
|
a_mesh->grab();
|
||||||
//cache.push_back(a_mesh);
|
//cache.push_back(a_mesh);
|
||||||
irr_driver->grabAllTextures(a_mesh);
|
irr_driver->grabAllTextures(a_mesh);
|
||||||
m_track->addCachedMesh(a_mesh);
|
m_track->addCachedMesh(a_mesh);
|
||||||
scene::IMeshSceneNode* scene_node = irr_driver->addMesh(a_mesh, group[m].m_model_file);
|
scene::IMeshSceneNode* scene_node = irr_driver->addMesh(a_mesh, group[m].m_model_file);
|
||||||
|
|
||||||
m_track->handleAnimatedTextures( scene_node, *group[m].m_xml );
|
m_track->handleAnimatedTextures(scene_node, *group[m].m_xml);
|
||||||
|
|
||||||
lod_node->add( group[m].m_distance, scene_node, true );
|
lod_node->add(group[m].m_distance, scene_node, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -42,26 +42,30 @@ namespace irr
|
|||||||
struct ModelDefinition
|
struct ModelDefinition
|
||||||
{
|
{
|
||||||
std::string m_model_file;
|
std::string m_model_file;
|
||||||
bool m_tangent;
|
bool m_tangent; // obsolete, TODO remove
|
||||||
const XMLNode* m_xml;
|
const XMLNode* m_xml;
|
||||||
|
|
||||||
/** For LOD */
|
/** For LOD */
|
||||||
int m_distance;
|
int m_distance;
|
||||||
|
|
||||||
|
bool m_skeletal_animation;
|
||||||
|
|
||||||
/** Constructor to allow storing this in STL containers */
|
/** Constructor to allow storing this in STL containers */
|
||||||
ModelDefinition()
|
ModelDefinition()
|
||||||
{
|
{
|
||||||
m_tangent = false;
|
m_tangent = false;
|
||||||
|
m_skeletal_animation = false;
|
||||||
m_distance = 0;
|
m_distance = 0;
|
||||||
m_xml = NULL;
|
m_xml = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelDefinition(const XMLNode* xml, int distance, std::string& model, bool tangent)
|
ModelDefinition(const XMLNode* xml, int distance, std::string& model, bool tangent, bool skeletal_animation)
|
||||||
{
|
{
|
||||||
m_model_file = model;
|
m_model_file = model;
|
||||||
m_tangent = tangent;
|
m_tangent = tangent;
|
||||||
m_xml = xml;
|
m_xml = xml;
|
||||||
m_distance = distance;
|
m_distance = distance;
|
||||||
|
m_skeletal_animation = skeletal_animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ModelDefinition()
|
~ModelDefinition()
|
||||||
|
@ -48,7 +48,7 @@ QuadGraph *QuadGraph::m_quad_graph = NULL;
|
|||||||
* \param graph_file_name Name of the file describing the actual graph
|
* \param graph_file_name Name of the file describing the actual graph
|
||||||
*/
|
*/
|
||||||
QuadGraph::QuadGraph(const std::string &quad_file_name,
|
QuadGraph::QuadGraph(const std::string &quad_file_name,
|
||||||
const std::string graph_file_name,
|
const std::string &graph_file_name,
|
||||||
const bool reverse) : m_reverse(reverse)
|
const bool reverse) : m_reverse(reverse)
|
||||||
{
|
{
|
||||||
m_node = NULL;
|
m_node = NULL;
|
||||||
|
@ -94,7 +94,7 @@ private:
|
|||||||
const video::SColor *lap_color=NULL);
|
const video::SColor *lap_color=NULL);
|
||||||
unsigned int getStartNode() const;
|
unsigned int getStartNode() const;
|
||||||
QuadGraph (const std::string &quad_file_name,
|
QuadGraph (const std::string &quad_file_name,
|
||||||
const std::string graph_file_name,
|
const std::string &graph_file_name,
|
||||||
const bool reverse);
|
const bool reverse);
|
||||||
~QuadGraph ();
|
~QuadGraph ();
|
||||||
public:
|
public:
|
||||||
@ -139,7 +139,7 @@ public:
|
|||||||
// ----------------------------------------------------------------------==
|
// ----------------------------------------------------------------------==
|
||||||
/** Creates a QuadGraph instance. */
|
/** Creates a QuadGraph instance. */
|
||||||
static void create(const std::string &quad_file_name,
|
static void create(const std::string &quad_file_name,
|
||||||
const std::string graph_file_name,
|
const std::string &graph_file_name,
|
||||||
const bool reverse)
|
const bool reverse)
|
||||||
{
|
{
|
||||||
assert(m_quad_graph==NULL);
|
assert(m_quad_graph==NULL);
|
||||||
|
@ -898,8 +898,11 @@ void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who)
|
|||||||
InputDevice* device = input_manager->getDeviceManager()->getLatestUsedDevice();
|
InputDevice* device = input_manager->getDeviceManager()->getLatestUsedDevice();
|
||||||
DeviceConfig* config = device->getConfiguration();
|
DeviceConfig* config = device->getConfiguration();
|
||||||
irr::core::stringw fire = config->getBindingAsString(PA_FIRE);
|
irr::core::stringw fire = config->getBindingAsString(PA_FIRE);
|
||||||
|
irr::core::stringw back = config->getBindingAsString(PA_LOOK_BACK);
|
||||||
|
|
||||||
new TutorialMessageDialog(_("Press <B> to look behind, to fire the weapon with <%s> while pressing <B> to to fire behind!", fire),
|
new TutorialMessageDialog(
|
||||||
|
_("Press <%s> to look behind, and fire the weapon with <%s> while "
|
||||||
|
"pressing <%s> to fire behind!", back, fire, back),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
else if (m_action == "tutorial_nitro_collect")
|
else if (m_action == "tutorial_nitro_collect")
|
||||||
|
@ -382,7 +382,7 @@ void Profiler::draw()
|
|||||||
video::SColor(255, 0, 255, 255)
|
video::SColor(255, 0, 255, 255)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hovered_markers.size() == 0)
|
if (hovered_markers.empty())
|
||||||
{
|
{
|
||||||
float curr_val = 0;
|
float curr_val = 0;
|
||||||
for (unsigned i = 0; i < Q_LAST; i++)
|
for (unsigned i = 0; i < Q_LAST; i++)
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
namespace StringUtils
|
namespace StringUtils
|
||||||
{
|
{
|
||||||
bool hasSuffix(const std::string& lhs, const std::string rhs)
|
bool hasSuffix(const std::string& lhs, const std::string &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.length() < rhs.length())
|
if (lhs.length() < rhs.length())
|
||||||
return false;
|
return false;
|
||||||
|
@ -32,7 +32,7 @@ namespace StringUtils
|
|||||||
{
|
{
|
||||||
int versionToInt(const std::string &s);
|
int versionToInt(const std::string &s);
|
||||||
|
|
||||||
bool hasSuffix(const std::string& lhs, const std::string rhs);
|
bool hasSuffix(const std::string& lhs, const std::string &rhs);
|
||||||
bool startsWith(const std::string& str, const std::string& prefix);
|
bool startsWith(const std::string& str, const std::string& prefix);
|
||||||
|
|
||||||
/** Return the filename part of a path */
|
/** Return the filename part of a path */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user