Merge remote-tracking branch 'upstream/master' into walldriving
Conflicts: src/graphics/irr_driver.cpp src/karts/kart.cpp
This commit is contained in:
commit
732c3a4b2f
@ -35,6 +35,14 @@
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
<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"
|
||||
text="TEST: GPWin" label_location="hover"/>
|
||||
<icon-button id="test_gplose" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||
text="TEST: GPLose" label_location="hover"/>
|
||||
<icon-button id="test_unlocked" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||
text="TEST: Unlocked" label_location="hover"/>
|
||||
<icon-button id="test_unlocked2" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||
text="TEST: Unlocked 2" label_location="hover"/>
|
||||
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||
I18N="Main menu button" text="Options" label_location="hover"/>
|
||||
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"
|
||||
|
@ -21,8 +21,13 @@
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
uniform float time;
|
||||
|
||||
#if __VERSION__ >= 330
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
#else
|
||||
in vec3 Position;
|
||||
in vec2 Texcoord;
|
||||
#endif
|
||||
out vec2 uv;
|
||||
|
||||
void main()
|
||||
|
@ -1,6 +1,7 @@
|
||||
uniform sampler2D displacement_tex;
|
||||
uniform sampler2D mask_tex;
|
||||
uniform sampler2D color_tex;
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 dir;
|
||||
uniform vec2 dir2;
|
||||
|
||||
@ -64,5 +65,8 @@ void main()
|
||||
float mask = texture(mask_tex, tc + shift).x;
|
||||
tc += (mask < 1.) ? vec2(0.) : shift;
|
||||
|
||||
FragColor = texture(color_tex, tc);
|
||||
vec4 col = texture(color_tex, tc);
|
||||
vec4 blend_tex = texture(tex, uv);
|
||||
col.rgb = blend_tex.rgb * blend_tex.a + (1. - blend_tex.a) * col.rgb;
|
||||
FragColor = vec4(col.rgb, 1.);
|
||||
}
|
||||
|
@ -78,8 +78,8 @@ void main()
|
||||
col += texture(tex, uv + (vec2(0.0, 0.4) * offset) * blur * 0.4);
|
||||
|
||||
col = vec4(col.rgb / 41.0, col.a);
|
||||
depth = clamp((FragPos.z/280), 0., 1.);
|
||||
depth = (1 - depth);
|
||||
depth = clamp(max(1.1666 - (FragPos.z/240.0), FragPos.z - 2000.0), 0., 1.);
|
||||
|
||||
vec3 final = colOriginal.rgb * depth + col.rgb * (1 - depth);
|
||||
|
||||
FragColor = vec4(final, colOriginal.a);
|
||||
|
@ -18,6 +18,7 @@ layout (std140) uniform MatrixesData
|
||||
#if __VERSION__ >= 330
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
|
||||
layout(location = 7) in vec3 Origin;
|
||||
@ -26,6 +27,7 @@ layout(location = 9) in vec3 Scale;
|
||||
#else
|
||||
in vec3 Position;
|
||||
in vec3 Normal;
|
||||
in vec4 Color;
|
||||
in vec2 Texcoord;
|
||||
|
||||
in vec3 Origin;
|
||||
@ -35,6 +37,7 @@ in vec3 Scale;
|
||||
|
||||
out vec3 nor;
|
||||
out vec2 uv;
|
||||
out vec4 color;
|
||||
|
||||
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
|
||||
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
|
||||
@ -46,4 +49,5 @@ void main(void)
|
||||
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.);
|
||||
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
|
||||
uv = Texcoord;
|
||||
color = Color.zyxw;
|
||||
}
|
||||
|
@ -25,20 +25,17 @@ uniform float boost_amount;
|
||||
|
||||
// The color buffer to use.
|
||||
uniform sampler2D color_buffer;
|
||||
uniform sampler2D dtex;
|
||||
|
||||
// Center (in texture coordinates) at which the kart is. A small circle
|
||||
// around this center is not blurred (see mask_radius below)
|
||||
uniform vec2 center;
|
||||
|
||||
// The direction to which the blurring aims at
|
||||
uniform vec2 direction;
|
||||
|
||||
// Radius of mask around the character in which no blurring happens
|
||||
// so that the kart doesn't get blurred.
|
||||
uniform float mask_radius;
|
||||
|
||||
// Maximum height of texture used
|
||||
uniform float max_tex_height;
|
||||
uniform mat4 previous_viewproj;
|
||||
|
||||
layout (std140) uniform MatrixesData
|
||||
{
|
||||
@ -55,42 +52,44 @@ out vec4 FragColor;
|
||||
// Number of samples used for blurring
|
||||
#define NB_SAMPLES 8
|
||||
|
||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texcoords = gl_FragCoord.xy / screen;
|
||||
vec2 texcoords = gl_FragCoord.xy / screen;
|
||||
|
||||
// Sample the color buffer
|
||||
vec3 color = texture(color_buffer, texcoords).rgb;
|
||||
// Sample the color buffer
|
||||
vec3 color = texture(color_buffer, texcoords).rgb;
|
||||
|
||||
// Compute the blur direction.
|
||||
// IMPORTANT: we don't normalize it so that it avoids a glitch around 'center',
|
||||
// plus it naturally scales the motion blur in a cool way :)
|
||||
vec2 blur_dir = direction - texcoords;
|
||||
float z = texture(dtex, texcoords).x;
|
||||
vec4 ViewPos = getPosFromUVDepth(vec3(texcoords, z), InverseProjectionMatrix);
|
||||
vec4 OldScreenPos = previous_viewproj * InverseViewMatrix * ViewPos;
|
||||
OldScreenPos /= OldScreenPos.w;
|
||||
OldScreenPos = .5 * OldScreenPos + .5;
|
||||
|
||||
// Compute the blurring factor:
|
||||
// - apply the mask, i.e. no blurring in a small circle around the kart
|
||||
float blur_factor = max(0.0, length(texcoords - center) - mask_radius);
|
||||
// Compute the blur direction.
|
||||
// IMPORTANT: we don't normalize it so that it avoids a glitch around 'center',
|
||||
// plus it naturally scales the motion blur in a cool way :)
|
||||
vec2 blur_dir = texcoords - OldScreenPos.xy;
|
||||
|
||||
// - avoid blurring the top of the screen
|
||||
blur_factor *= (max_tex_height - texcoords.t);
|
||||
// Compute the blurring factor:
|
||||
// - apply the mask, i.e. no blurring in a small circle around the kart
|
||||
float blur_factor = max(0.0, length(texcoords - center) - mask_radius);
|
||||
|
||||
// - apply the boost amount
|
||||
blur_factor *= boost_amount;
|
||||
// - apply the boost amount
|
||||
blur_factor *= boost_amount;
|
||||
|
||||
// Scale the blur direction
|
||||
blur_dir *= blur_factor;
|
||||
// Scale the blur direction
|
||||
blur_dir *= blur_factor;
|
||||
|
||||
// Compute the blur
|
||||
vec2 inc_vec = blur_dir / vec2(NB_SAMPLES);
|
||||
vec2 blur_texcoords = texcoords + inc_vec;
|
||||
for(int i=1 ; i < NB_SAMPLES ; i++)
|
||||
{
|
||||
color += texture(color_buffer, blur_texcoords).rgb;
|
||||
blur_texcoords += inc_vec;
|
||||
}
|
||||
color /= vec3(NB_SAMPLES);
|
||||
FragColor = vec4(color, 1.0);
|
||||
|
||||
// Keep this commented line for debugging:
|
||||
//FragColor = vec4(blur_factor, blur_factor, blur_factor, 0.0);
|
||||
// Compute the blur
|
||||
vec2 inc_vec = blur_dir / vec2(NB_SAMPLES);
|
||||
vec2 blur_texcoords = texcoords - inc_vec * NB_SAMPLES / 2;
|
||||
for(int i=1 ; i < NB_SAMPLES ; i++)
|
||||
{
|
||||
color += texture(color_buffer, blur_texcoords).rgb;
|
||||
blur_texcoords += inc_vec;
|
||||
}
|
||||
color /= vec3(NB_SAMPLES);
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
@ -1,18 +1,15 @@
|
||||
uniform sampler2D Albedo;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 color = texture(Albedo, uv);
|
||||
vec4 col = texture(Albedo, uv);
|
||||
col.xyz *= pow(color.xyz, vec3(2.2));
|
||||
vec3 LightFactor = getLightFactor(1.);
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
FragColor = vec4(col.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ uniform sampler2D tex;
|
||||
|
||||
in vec2 uv;
|
||||
in vec3 nor;
|
||||
in vec4 color;
|
||||
layout (location = 0) out vec3 RSMColor;
|
||||
layout (location = 1) out vec3 RSMNormals;
|
||||
|
||||
void main()
|
||||
{
|
||||
RSMColor = texture(tex, uv).xyz;
|
||||
RSMColor = texture(tex, uv).xyz * color.rgb;
|
||||
RSMNormals = .5 * normalize(nor) + .5;
|
||||
}
|
||||
|
@ -11,10 +11,12 @@ uniform mat4 TextureMatrix =
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
|
||||
out vec3 nor;
|
||||
out vec2 uv;
|
||||
out vec4 color;
|
||||
|
||||
|
||||
void main(void)
|
||||
@ -24,4 +26,5 @@ void main(void)
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
|
||||
nor = (vec4(Normal, 0.)).xyz;
|
||||
uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy;
|
||||
color = Color.zyxw;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ uniform sampler2D tex;
|
||||
uniform sampler2D logluminancetex;
|
||||
uniform float exposure = .09;
|
||||
uniform float Lwhite = 1.;
|
||||
uniform float vignette_weight = 0.;
|
||||
|
||||
layout (std140) uniform MatrixesData
|
||||
{
|
||||
@ -43,12 +44,11 @@ void main()
|
||||
// Uncharted2 tonemap with Auria's custom coefficients
|
||||
vec4 perChannel = (col * (6.9 * col + .5)) / (col * (5.2 * col + 1.7) + 0.06);
|
||||
perChannel = pow(perChannel, vec4(2.2));
|
||||
|
||||
|
||||
vec2 inside = uv - 0.5;
|
||||
float vignette = 1 - dot(inside, inside);
|
||||
float vignette = 1. - dot(inside, inside) * vignette_weight;
|
||||
vignette = clamp(pow(vignette, 0.8), 0., 1.);
|
||||
//vignette = clamp(vignette + vignette - 0.5, 0., 1.15);
|
||||
|
||||
|
||||
FragColor = vec4(perChannel.xyz * vignette, col.a);
|
||||
}
|
||||
|
@ -1,18 +1,15 @@
|
||||
uniform sampler2D tex;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 Color = texture(tex, uv) * pow(color, vec4(2.2));
|
||||
vec4 Color = texture(tex, uv);
|
||||
Color.xyz *= pow(color.xyz, vec3(2.2));
|
||||
Color.a *= color.a;
|
||||
// Premultiply alpha
|
||||
FragColor = vec4(Color.rgb * Color.a, Color.a);
|
||||
}
|
||||
|
@ -18,31 +18,28 @@ layout (std140) uniform MatrixesData
|
||||
vec2 screen;
|
||||
};
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 diffusecolor = texture(tex, uv) * pow(color, vec4(2.2));
|
||||
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
|
||||
tmp = 2. * tmp - 1.;
|
||||
vec4 diffusecolor = texture(tex, uv);
|
||||
diffusecolor.xyz *= pow(color.xyz, vec3(2.2));
|
||||
diffusecolor.a *= color.a;
|
||||
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
|
||||
tmp = 2. * tmp - 1.;
|
||||
|
||||
vec4 xpos = vec4(tmp, 1.0);
|
||||
xpos = InverseProjectionMatrix * xpos;
|
||||
xpos.xyz /= xpos.w;
|
||||
vec4 xpos = vec4(tmp, 1.0);
|
||||
xpos = InverseProjectionMatrix * xpos;
|
||||
xpos.xyz /= xpos.w;
|
||||
|
||||
float dist = length(xpos.xyz);
|
||||
float fog = smoothstep(start, end, dist);
|
||||
float dist = length(xpos.xyz);
|
||||
float fog = smoothstep(start, end, dist);
|
||||
|
||||
fog = min(fog, fogmax);
|
||||
fog = min(fog, fogmax);
|
||||
|
||||
vec4 color = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog));
|
||||
FragColor = vec4(color.rgb * color.a, color.a);
|
||||
vec4 finalcolor = vec4(col, 0.) * fog + diffusecolor *(1. - fog);
|
||||
FragColor = vec4(finalcolor.rgb * finalcolor.a, finalcolor.a);
|
||||
}
|
||||
|
@ -12,5 +12,5 @@ varying vec2 uv;
|
||||
void main()
|
||||
{
|
||||
vec4 res = texture(tex, uv);
|
||||
FragColor = vec4(res.xyz * color.xyz / 255., res.a);
|
||||
FragColor = res * color / 255.;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@
|
||||
<!-- Default values for all karts
|
||||
============================ -->
|
||||
<general-kart-defaults>
|
||||
|
||||
|
||||
<!-- Camera: Distance between kart and camera.
|
||||
forward-up-angle: Angle between camera and plane of kart (pitch)
|
||||
when the camera is pointing forward
|
||||
@ -162,57 +162,6 @@
|
||||
shown. -->
|
||||
<jump animation-time="0.5" />
|
||||
|
||||
<!-- If a kart starts within the specified time after 'go',
|
||||
it receives the corresponding bonus from 'boost'. Those
|
||||
fields must have the same size, and must be sorted by
|
||||
increasing times. -->
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "6 3" />
|
||||
|
||||
<!-- Rescue: time: How long it takes the kart to be raised.
|
||||
height: how height the kart will be raised before it is
|
||||
dropped back onto the track.
|
||||
vert rescue offset: used to raise karts a bit higher before
|
||||
releasing them on the ground after a rescue. Used to avoid
|
||||
resetting karts into the track. Not sure if this is still
|
||||
necessary. -->
|
||||
<rescue vert-offset="0.0" time="1.2" height="2"/>
|
||||
|
||||
<!-- Nitro: engine-force: additional engine power
|
||||
consumption: nitro consumption - heavier characters can be set
|
||||
to need more nitro than lighter character.
|
||||
small-container: how much energy a small container gives.
|
||||
big-container: how much energy a big container gives.
|
||||
max-speed-increase: How much the speed of a kart might exceed
|
||||
its maximum speed (in m/s).
|
||||
duration: How long the increased speed will be valid after
|
||||
the kart stops using nitro (and the fade-out-time starts).
|
||||
fade-out-time: Duration during which the increased maximum
|
||||
speed due to nitro fades out.
|
||||
max: How much nitro a kart can store.
|
||||
-->
|
||||
<nitro engine-force="500" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2" max="20"/>
|
||||
|
||||
<!-- Bubble gum data:
|
||||
time: How long the bubblegum lasts.
|
||||
speed-fraction: To what fraction of top-speed the speed is reduced.
|
||||
torque: To rotate the kart somewhat.
|
||||
fade-in-time: How quick the slowdown takes effect.
|
||||
-->
|
||||
<bubblegum time="1" speed-fraction="0.3" torque="500" fade-in-time="0.01"/>
|
||||
|
||||
<!-- time: Time a zipper is active.
|
||||
force: Additional zipper force.
|
||||
speed-gain: One time additional speed.
|
||||
max-speed-increase: Additional speed allowed on top of the
|
||||
kart-specific maximum kart speed.
|
||||
fade-out-time: determines how long it takes for a zipper
|
||||
to fade out (after 'time').
|
||||
-->
|
||||
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
||||
fade-out-time="1.0" />
|
||||
|
||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||
decrease: multiplicative decrease of skidding factor in each frame.
|
||||
max: maximum skidding factor = maximum increase of steering angle.
|
||||
@ -246,15 +195,6 @@
|
||||
of the turn the kart is doing somewhat by steering to the left and right,
|
||||
but you will always keep on doing a left turn, just more or less. -->
|
||||
|
||||
<skid increase="1.05" decrease="0.95" max="2.5" time-till-max="0.5"
|
||||
visual="1.25" visual-time="0.7" revert-visual-time="0.7"
|
||||
min-speed="10" time-till-bonus="1.0 3.0"
|
||||
bonus-speed="4.5 6.5" bonus-time="3.0 4.0"
|
||||
bonus-force="250 350"
|
||||
physical-jump-time="0" graphical-jump-time="0.4"
|
||||
post-skid-rotate-factor="1"
|
||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||
|
||||
<!-- Kart-specific settings used by the AI.
|
||||
use-slipstream: if the AI should try to overtake karts using slipstream.
|
||||
disable-slipstream-usage: even if the AI is not trying to use slipstream,
|
||||
@ -394,81 +334,7 @@
|
||||
skidding-threshold="2.0"
|
||||
/>
|
||||
</ai>
|
||||
<!-- Slipstream: length: How far behind a kart slipstream works
|
||||
width: how wide slipstream works furthest away from the kart.
|
||||
collect-time: How many seconds of sstream give maximum benefit
|
||||
use-time: How long the benefit will last.
|
||||
add-power: Additional power due to sstreaming. 1 = +100%
|
||||
min-speed: Minimum speed necessary for slipstream to take effect.
|
||||
max-speed-increase: How much the speed of the kart might exceed
|
||||
its normal maximum speed.
|
||||
duration: How long the higher speed lasts after slipstream stopped
|
||||
working.
|
||||
fade-out-time: How long the slip stream speed increase will
|
||||
gradually be reduced. -->
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="5"
|
||||
add-power="3" min-speed="10"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||
|
||||
<!-- Kart-specific settings for the swatter:
|
||||
duration: how long can the swatter be active.
|
||||
distance: How close a kart or an item must be before it can be hit.
|
||||
squash-duration: How long a kart will remain squashed.
|
||||
squash-slowdown: percentage of max speed that a kart is
|
||||
restricted to. -->
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
<!-- Leaning related parameters, i.e. slightly leaning the karts when
|
||||
driving a fast curve.
|
||||
max: maximum leaning (i.e. when steering as much as possible at highest
|
||||
speed), in degrees.
|
||||
sped: Speed with which the leaning changes (in degree/second). -->
|
||||
<lean max="8.6" speed="5.0" />
|
||||
|
||||
<!-- turn-radius defines the turn radius of the kart at
|
||||
a given speed. The actual steering angle is dependent on the
|
||||
wheel base of the kart: radius = wheel_base/sin(steering_angle).
|
||||
The values below define that at speed 0 the turn radius is 2, at
|
||||
speed 10 the radius is 7.5 etc.
|
||||
The actual turn radius is piece-wise linearly interpolated. This
|
||||
allows for tighter turning at lower speeds, and also avoids that
|
||||
the kart becomes too hard to control at high speed (speeds of higher
|
||||
than 23 can only be reached with powerups).
|
||||
time-full-steer: This is the amount of change in steering depending
|
||||
on current steering. So if the steering is between 0 and 0.5,
|
||||
the time-for-steering-change is 0.15. If the current steering is
|
||||
between 0.5 and 1.0, the time-for-steering-change is 0.25.
|
||||
The speed is used as dt/time-for-steering-change.
|
||||
In short: steering at less than halfway is somewhat faster,
|
||||
which should avoid oversteering (by pressing the key for too long),
|
||||
but slower when you want to steer more. Overwall with the current
|
||||
settings the expected time-to-full-steer is:
|
||||
0.5 * 0.25 + 0.5 * 0.15 = 0.2 ... which is overall the same
|
||||
time we had previously.
|
||||
-->
|
||||
<turn turn-radius="0:2.0 10:7.5 25:15 45:30"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1" />
|
||||
|
||||
<!-- Speed and acceleration related values: power and max-speed (in m/s)
|
||||
have 3 values, one for low, medium, and hard.
|
||||
brake-factor: Value used when braking. max-speed-reverse-ratio is
|
||||
the percentage of max speed for reverse gear. -->
|
||||
<engine power="450 475 500 510" max-speed="17 21 23 25" brake-factor="11.0"
|
||||
max-speed-reverse-ratio="0.3"/>
|
||||
|
||||
<!-- Simulated gears: switch-ratio defines at what ratio of the maximum
|
||||
speed what gear is selected, e.g. 0.25 means that if the speed is
|
||||
bigger or equal to 0.25 x maxSpeed then use gear 1, 0.5 means if
|
||||
the speed is bigger or equal to 0.5 x maxSpeed then gear 2.
|
||||
gear-power-increase contains the increase in max power (to simulate
|
||||
different gears), e.g. 2.5 as first entry means: 2.5*maxPower in gear 1
|
||||
| first | second | third | . -->
|
||||
<gear switch-ratio="0.25 0.7 1.0" power-increase="2.2 1.7 1.3"/>
|
||||
|
||||
<!-- mass -->
|
||||
<mass value="225"/>
|
||||
|
||||
|
||||
<!-- Suspension related values. stiffness: kart's suspension stiffness.
|
||||
rest: Length of suspension when at rest.
|
||||
travel-cm: maximum movement of suspension - in cm!!
|
||||
@ -514,9 +380,6 @@
|
||||
downward-impulse-factor="0"
|
||||
track-connection-accel="2"/>
|
||||
|
||||
<!-- Parameters for the upright constraint, which keeps karts upright. -->
|
||||
<upright tolerance="0.2" max-force="30"/>
|
||||
|
||||
<!-- collision
|
||||
impulse-type: STK can apply an additional impulse in case of
|
||||
kart-track collision:
|
||||
@ -549,26 +412,280 @@
|
||||
<collision impulse-type="normal"
|
||||
impulse="3000" impulse-time="0.1" terrain-impulse="8000"
|
||||
restitution="1.0" bevel-factor="0.5 0.0 0.5" />
|
||||
|
||||
<!-- If a kart starts within the specified time after 'go',
|
||||
it receives the corresponding bonus from 'boost'. Those
|
||||
fields must have the same size, and must be sorted by
|
||||
increasing times. -->
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "6 3" />
|
||||
|
||||
<!-- Rescue: time: How long it takes the kart to be raised.
|
||||
height: how height the kart will be raised before it is
|
||||
dropped back onto the track.
|
||||
vert rescue offset: used to raise karts a bit higher before
|
||||
releasing them on the ground after a rescue. Used to avoid
|
||||
resetting karts into the track. Not sure if this is still
|
||||
necessary. -->
|
||||
<rescue vert-offset="0.0" time="1.2" height="2"/>
|
||||
|
||||
<!-- Nitro: engine-force: additional engine power
|
||||
consumption: nitro consumption - heavier characters can be set
|
||||
to need more nitro than lighter character.
|
||||
small-container: how much energy a small container gives.
|
||||
big-container: how much energy a big container gives.
|
||||
max-speed-increase: How much the speed of a kart might exceed
|
||||
its maximum speed (in m/s).
|
||||
duration: How long the increased speed will be valid after
|
||||
the kart stops using nitro (and the fade-out-time starts).
|
||||
fade-out-time: Duration during which the increased maximum
|
||||
speed due to nitro fades out.
|
||||
max: How much nitro a kart can store.
|
||||
-->
|
||||
<nitro engine-force="500" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2" max="20"/>
|
||||
|
||||
<!-- Bubble gum data:
|
||||
time: How long the bubblegum lasts.
|
||||
speed-fraction: To what fraction of top-speed the speed is reduced.
|
||||
torque: To rotate the kart somewhat.
|
||||
fade-in-time: How quick the slowdown takes effect.
|
||||
-->
|
||||
<bubblegum time="1" speed-fraction="0.3" torque="500" fade-in-time="0.01"/>
|
||||
|
||||
|
||||
<!-- time: Time a zipper is active.
|
||||
force: Additional zipper force.
|
||||
speed-gain: One time additional speed.
|
||||
max-speed-increase: Additional speed allowed on top of the
|
||||
kart-specific maximum kart speed.
|
||||
fade-out-time: determines how long it takes for a zipper
|
||||
to fade out (after 'time').
|
||||
-->
|
||||
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
||||
fade-out-time="1.0" />
|
||||
|
||||
<!-- Kart-specific plunger and rubber band handling: max-length is
|
||||
the maximum length of rubber band before it snaps. force is
|
||||
the force a plunger/rubber band applies to the kart(s).
|
||||
duration is the duration a rubber band acts.
|
||||
in-face-time determines how long it takes before a plunger
|
||||
in your face is removed. -->
|
||||
<plunger band-max-length="50" band-force="1500" band-duration="1"
|
||||
band-speed-increase="7" band-fade-out-time="3"
|
||||
in-face-time="3 4 4.5 4.5"/>
|
||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||
decrease: multiplicative decrease of skidding factor in each frame.
|
||||
max: maximum skidding factor = maximum increase of steering angle.
|
||||
time-till-max: Time till maximum skidding is reached.
|
||||
visual: Additional graphical rotation of kart. The graphical rotation
|
||||
of the kart also determines the direction the kart is driving to
|
||||
when skidding is stopped.
|
||||
visual-time: How long it takes for the visual skid to reach maximum.
|
||||
revert-visual-time: how long it takes when stopping a skid to revert
|
||||
the visual skid and bring visuals and physics in sync again.
|
||||
angular-velocity: Angular velocity to be used for the kart when skidding.
|
||||
min-speed: Minimum speed a kart must have before it can skid. Must be
|
||||
>0, otherwise the kart can skid at the start of the race.
|
||||
time-till-bonus: How long a kart needs to skid in order to get a bonus.
|
||||
bonus-force: A speedup applied to the kart whick skidded for a while.
|
||||
bonus-time: How long the bonus-force is applied.
|
||||
bonus-force: Additional engine force (this is used to offset the fact
|
||||
that turning after skidding (e.g. to correct direction) often uses
|
||||
up the skid bonus).
|
||||
post-skid-rotate-factor: a factor to be used to determine how much
|
||||
the chassis of a kart should rotate to match the graphical view.
|
||||
A factor of 1 is identical, a smaller factor will rotate the kart
|
||||
less (which might feel better).
|
||||
physical-jump-time: Time for a physical jump at the beginning of a skid.
|
||||
graphical-jump-time: Time for a graphics-only jump at the beginning
|
||||
of a skid.
|
||||
reduce-turn-min/max: The steering done by the controller (which is in
|
||||
[-1,1]) is mapped to [reduce-turn-min, reduce-turn-max] when skidding
|
||||
is active (for left turn, right turn will use [-max, -min]). The
|
||||
effect is that while you skid (say left) you can adjust the direction
|
||||
of the turn the kart is doing somewhat by steering to the left and right,
|
||||
but you will always keep on doing a left turn, just more or less. -->
|
||||
<skid increase="1.05" decrease="0.95" max="2.5" time-till-max="0.5"
|
||||
visual="1.25" visual-time="0.7" revert-visual-time="0.7"
|
||||
min-speed="10" time-till-bonus="1.0 3.0"
|
||||
bonus-speed="4.5 6.5" bonus-time="3.0 4.0"
|
||||
bonus-force="250 350"
|
||||
physical-jump-time="0" graphical-jump-time="0.4"
|
||||
post-skid-rotate-factor="1"
|
||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||
|
||||
|
||||
<!-- Slipstream: length: How far behind a kart slipstream works
|
||||
width: how wide slipstream works furthest away from the kart.
|
||||
collect-time: How many seconds of sstream give maximum benefit
|
||||
use-time: How long the benefit will last.
|
||||
add-power: Additional power due to sstreaming. 1 = +100%
|
||||
min-speed: Minimum speed necessary for slipstream to take effect.
|
||||
max-speed-increase: How much the speed of the kart might exceed
|
||||
its normal maximum speed.
|
||||
duration: How long the higher speed lasts after slipstream stopped
|
||||
working.
|
||||
fade-out-time: How long the slip stream speed increase will
|
||||
gradually be reduced. -->
|
||||
|
||||
<!-- Kart-specific explosion parameters.
|
||||
Time: how long it takes before the kart can drive again (this
|
||||
determines how height the kart is being thrown).
|
||||
Invulnerability-time: how long a kart will be invulnerable
|
||||
after being hit by an explosion.
|
||||
radius: Kart closer to this value will be affected by
|
||||
an explosion as well. -->
|
||||
<explosion time="2" radius="5"
|
||||
invulnerability-time="6" />
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="5"
|
||||
add-power="3" min-speed="10"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||
|
||||
|
||||
<!-- Kart-specific settings for the swatter:
|
||||
duration: how long can the swatter be active.
|
||||
distance: How close a kart or an item must be before it can be hit.
|
||||
squash-duration: How long a kart will remain squashed.
|
||||
squash-slowdown: percentage of max speed that a kart is
|
||||
restricted to. -->
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<!-- Leaning related parameters, i.e. slightly leaning the karts when
|
||||
driving a fast curve.
|
||||
max: maximum leaning (i.e. when steering as much as possible at highest
|
||||
speed), in degrees.
|
||||
sped: Speed with which the leaning changes (in degree/second). -->
|
||||
<lean max="8.6" speed="5.0" />
|
||||
|
||||
<!-- turn-radius defines the turn radius of the kart at
|
||||
a given speed. The actual steering angle is dependent on the
|
||||
wheel base of the kart: radius = wheel_base/sin(steering_angle).
|
||||
The values below define that at speed 0 the turn radius is 2, at
|
||||
speed 10 the radius is 7.5 etc.
|
||||
The actual turn radius is piece-wise linearly interpolated. This
|
||||
allows for tighter turning at lower speeds, and also avoids that
|
||||
the kart becomes too hard to control at high speed (speeds of higher
|
||||
than 23 can only be reached with powerups).
|
||||
time-full-steer: This is the amount of change in steering depending
|
||||
on current steering. So if the steering is between 0 and 0.5,
|
||||
the time-for-steering-change is 0.15. If the current steering is
|
||||
between 0.5 and 1.0, the time-for-steering-change is 0.25.
|
||||
The speed is used as dt/time-for-steering-change.
|
||||
In short: steering at less than halfway is somewhat faster,
|
||||
which should avoid oversteering (by pressing the key for too long),
|
||||
but slower when you want to steer more. Overwall with the current
|
||||
settings the expected time-to-full-steer is:
|
||||
0.5 * 0.25 + 0.5 * 0.15 = 0.2 ... which is overall the same
|
||||
time we had previously.
|
||||
-->
|
||||
<turn turn-radius="0:2.0 10:7.5 25:15 45:30"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1" />
|
||||
|
||||
<!-- Speed and acceleration related values: power and max-speed (in m/s)
|
||||
have 3 values, one for low, medium, and hard.
|
||||
brake-factor: Value used when braking. max-speed-reverse-ratio is
|
||||
the percentage of max speed for reverse gear. -->
|
||||
<engine power="450 475 500 510" max-speed="17 21 23 25" brake-factor="11.0"
|
||||
max-speed-reverse-ratio="0.3"/>
|
||||
|
||||
<!-- Simulated gears: switch-ratio defines at what ratio of the maximum
|
||||
speed what gear is selected, e.g. 0.25 means that if the speed is
|
||||
bigger or equal to 0.25 x maxSpeed then use gear 1, 0.5 means if
|
||||
the speed is bigger or equal to 0.5 x maxSpeed then gear 2.
|
||||
gear-power-increase contains the increase in max power (to simulate
|
||||
different gears), e.g. 2.5 as first entry means: 2.5*maxPower in gear 1
|
||||
| first | second | third | . -->
|
||||
<gear switch-ratio="0.25 0.7 1.0" power-increase="2.2 1.7 1.3"/>
|
||||
|
||||
<!-- mass -->
|
||||
<mass value="225"/>
|
||||
|
||||
<!-- Kart-specific plunger and rubber band handling: max-length is
|
||||
the maximum length of rubber band before it snaps. force is
|
||||
the force a plunger/rubber band applies to the kart(s).
|
||||
duration is the duration a rubber band acts.
|
||||
in-face-time determines how long it takes before a plunger
|
||||
in your face is removed. -->
|
||||
<plunger band-max-length="50" band-force="1500" band-duration="1"
|
||||
band-speed-increase="7" band-fade-out-time="3"
|
||||
in-face-time="3 4 4.5 4.5"/>
|
||||
|
||||
<!-- Kart-specific explosion parameters.
|
||||
Time: how long it takes before the kart can drive again (this
|
||||
determines how height the kart is being thrown).
|
||||
Invulnerability-time: how long a kart will be invulnerable
|
||||
after being hit by an explosion.
|
||||
radius: Kart closer to this value will be affected by
|
||||
an explosion as well. -->
|
||||
<explosion time="2" radius="5"
|
||||
invulnerability-time="6" />
|
||||
|
||||
<kart-type>
|
||||
<light>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "8.5 4.5" />
|
||||
|
||||
<nitro engine-force="350" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="4.5" duration="1.5" fade-out-time="2.5" max="20"/>
|
||||
|
||||
<slipstream length="11" width="2" collect-time="1.5" use-time="2.5"
|
||||
add-power="3.2" min-speed="9"
|
||||
max-speed-increase="4" duration="1.2" fade-out-time="2.3"/>
|
||||
|
||||
<turn turn-radius="0:3.0 10:10.0 25:20.0 45:40.0"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="250 300 350 400" max-speed="15.8 18.8 23.85 30.0" brake-factor="15.0"
|
||||
max-speed-reverse-ratio="0.3"/>
|
||||
|
||||
<gear switch-ratio="0.20 0.55 1" power-increase="5 4 3"/>
|
||||
|
||||
<mass value="195"/>
|
||||
|
||||
<explosion time="2.1" radius="5.5"
|
||||
invulnerability-time="7" />
|
||||
</light>
|
||||
|
||||
<medium>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "4.2 2.6" />
|
||||
|
||||
<nitro engine-force="425" consumption="1.4" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1.2" fade-out-time="2" max="20"/>
|
||||
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="3.3"
|
||||
add-power="2.8" min-speed="10"
|
||||
max-speed-increase="5" duration="0.9" fade-out-time="1.6"/>
|
||||
|
||||
<turn turn-radius="0:4.5 10:16.0 25:30.0 45:60.0"
|
||||
time-full-steer ="0:0.17 0.5:0.17 0.5:0.28 1.0:0.28"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="425 500 575 600" max-speed="15 20 23.2 27" brake-factor="11.0"
|
||||
max-speed-reverse-ratio="0.4"/>
|
||||
|
||||
<gear switch-ratio="0.30 0.7 1.0" power-increase="2.2 2.2 2.5"/>
|
||||
|
||||
<mass value="250"/>
|
||||
|
||||
<explosion time="1.8" radius="5"
|
||||
invulnerability-time="6" />
|
||||
</medium>
|
||||
|
||||
<heavy>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "3.8 2" />
|
||||
|
||||
<nitro engine-force="600" consumption="2" small-container="1" big-container="3"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1.3" max="20"/>
|
||||
|
||||
<slipstream length="8.5" width="2" collect-time="2" use-time="4"
|
||||
add-power="2.7" min-speed="10.5"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1"/>
|
||||
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<turn turn-radius="0:4.0 10:18.5 25:43.0 45:72.5"
|
||||
time-full-steer ="0:0.23 0.5:0.23 0.5:0.41 1.0:0.41"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="600 700 800 900" max-speed="15 20 23 25" brake-factor="10"
|
||||
max-speed-reverse-ratio="0.65"/>
|
||||
|
||||
<gear switch-ratio="0.45 0.70 1" power-increase="1.5 1.7 2.5"/>
|
||||
|
||||
<mass value="350"/>
|
||||
|
||||
<explosion time="1.5" radius="4"
|
||||
invulnerability-time="6" />
|
||||
</heavy>
|
||||
</kart-type>
|
||||
</general-kart-defaults>
|
||||
</config>
|
||||
|
@ -376,8 +376,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
|
||||
else if(m_mode==CM_GRAND_PRIX)
|
||||
{
|
||||
race_manager->setMinorMode(m_minor);
|
||||
const GrandPrixData *gp = grand_prix_manager->getGrandPrix(m_gp_id);
|
||||
race_manager->setGrandPrix(*gp);
|
||||
race_manager->setGrandPrix(grand_prix_manager->getGrandPrix(m_gp_id));
|
||||
race_manager->setDifficulty(d);
|
||||
race_manager->setNumKarts(m_num_karts[d]);
|
||||
race_manager->setNumLocalPlayers(1);
|
||||
@ -459,7 +458,7 @@ bool ChallengeData::isGPFulfilled() const
|
||||
// is no world objects to query at this stage.
|
||||
if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX ||
|
||||
race_manager->getMinorMode() != m_minor ||
|
||||
race_manager->getGrandPrix()->getId() != m_gp_id ||
|
||||
race_manager->getGrandPrix().getId() != m_gp_id ||
|
||||
race_manager->getNumberOfKarts() < (unsigned int)m_num_karts[d] ||
|
||||
race_manager->getNumPlayers() > 1) return false;
|
||||
|
||||
|
@ -50,6 +50,13 @@ STKConfig::~STKConfig()
|
||||
|
||||
if(m_default_kart_properties)
|
||||
delete m_default_kart_properties;
|
||||
|
||||
for(std::map<std::string, KartProperties*>::iterator it = m_kart_properties.begin();
|
||||
it != m_kart_properties.end(); ++it)
|
||||
{
|
||||
if (it->second)
|
||||
delete it->second;
|
||||
}
|
||||
} // ~STKConfig
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -380,6 +387,15 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
m_default_kart_properties->getAllData(node);
|
||||
const XMLNode *types = node->getNode("kart-type");
|
||||
|
||||
for (unsigned int i = 0; i < types->getNumNodes(); ++i)
|
||||
{
|
||||
const XMLNode* type = types->getNode(i);
|
||||
m_kart_properties[type->getName()] = new KartProperties();
|
||||
m_kart_properties[type->getName()]->copyFrom(m_default_kart_properties);
|
||||
m_kart_properties[type->getName()]->getAllData(type);
|
||||
}
|
||||
|
||||
} // getAllData
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class KartProperties;
|
||||
class MusicInformation;
|
||||
@ -47,6 +48,7 @@ class STKConfig : public NoCopy
|
||||
protected:
|
||||
/** Default kart properties. */
|
||||
KartProperties *m_default_kart_properties;
|
||||
std::map<std::string, KartProperties*> m_kart_properties;
|
||||
|
||||
public:
|
||||
/** What to do if a kart already has a powerup when it hits a bonus box:
|
||||
@ -170,6 +172,9 @@ public:
|
||||
/** Returns the default kart properties for each kart. */
|
||||
const KartProperties &
|
||||
getDefaultKartProperties() const {return *m_default_kart_properties; }
|
||||
|
||||
const KartProperties &
|
||||
getKartProperties(std::string type) { return *m_kart_properties[type]; }
|
||||
}
|
||||
; // STKConfig
|
||||
|
||||
|
@ -393,7 +393,6 @@ public:
|
||||
|
||||
void setPosition(float x, float y, float z)
|
||||
{
|
||||
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
|
||||
// Sun "position" is actually a direction and not a position
|
||||
core::matrix4 m_view = irr_driver->getViewMatrix();
|
||||
m_view.makeInverse();
|
||||
|
@ -47,7 +47,9 @@ PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||
PFNGLBLENDEQUATIONPROC glBlendEquation;
|
||||
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
|
||||
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
|
||||
PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
|
||||
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
|
||||
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
|
||||
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
|
||||
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
||||
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||
@ -201,7 +203,9 @@ void initGL()
|
||||
glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation");
|
||||
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor");
|
||||
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced");
|
||||
glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsBaseVertex");
|
||||
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced");
|
||||
glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstancedBaseVertex");
|
||||
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers");
|
||||
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
|
||||
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");
|
||||
@ -303,7 +307,7 @@ GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsi
|
||||
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
|
||||
printf(ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
@ -474,6 +478,20 @@ void saveCompressedTexture(const std::string& compressed_tex)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
static unsigned colorcount = 0;
|
||||
|
||||
video::ITexture* getUnicolorTexture(video::SColor c)
|
||||
{
|
||||
video::SColor tmp[4] = {
|
||||
c, c, c, c
|
||||
};
|
||||
video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
|
||||
img->grab();
|
||||
std::string name("color");
|
||||
name += colorcount++;
|
||||
return irr_driver->getVideoDriver()->addTexture(name.c_str(), img);
|
||||
}
|
||||
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + TextureUnit);
|
||||
@ -490,6 +508,235 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum
|
||||
glGetError();
|
||||
}
|
||||
|
||||
class VBOGatherer
|
||||
{
|
||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
||||
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
||||
std::vector<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
|
||||
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
|
||||
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
|
||||
std::map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
|
||||
void regenerateBuffer(enum VTXTYPE);
|
||||
void regenerateVAO(enum VTXTYPE);
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type);
|
||||
void append(scene::IMeshBuffer *, VBOGatherer::VTXTYPE tp);
|
||||
public:
|
||||
VBOGatherer();
|
||||
std::pair<unsigned, unsigned> getBase(scene::IMeshBuffer *);
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; }
|
||||
~VBOGatherer()
|
||||
{
|
||||
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
||||
{
|
||||
if (vbo[i])
|
||||
glDeleteBuffers(1, &vbo[i]);
|
||||
if (ibo[i])
|
||||
glDeleteBuffers(1, &ibo[i]);
|
||||
if (vao[i])
|
||||
glDeleteVertexArrays(1, &vao[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VBOGatherer::VBOGatherer()
|
||||
{
|
||||
vao[0] = vao[1] = vao[2] = 0;
|
||||
vbo[0] = vbo[1] = vbo[2] = 0;
|
||||
ibo[0] = ibo[1] = ibo[2] = 0;
|
||||
vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0;
|
||||
idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0;
|
||||
vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL;
|
||||
idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL;
|
||||
}
|
||||
|
||||
void VBOGatherer::regenerateBuffer(enum VTXTYPE tp)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
if (vbo[tp])
|
||||
glDeleteBuffers(1, &vbo[tp]);
|
||||
glGenBuffers(1, &vbo[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_STATIC_DRAW);
|
||||
|
||||
if (ibo[tp])
|
||||
glDeleteBuffers(1, &ibo[tp]);
|
||||
glGenBuffers(1, &ibo[tp]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void VBOGatherer::regenerateVAO(enum VTXTYPE tp)
|
||||
{
|
||||
if (vao[tp])
|
||||
glDeleteVertexArrays(1, &vao[tp]);
|
||||
glGenVertexArrays(1, &vao[tp]);
|
||||
glBindVertexArray(vao[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
break;
|
||||
case VTXTYPE_TCOORD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
break;
|
||||
case VTXTYPE_TANGENT:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
size_t VBOGatherer::getVertexPitch(enum VTXTYPE tp) const
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
return getVertexPitchFromType(video::EVT_STANDARD);
|
||||
case VTXTYPE_TCOORD:
|
||||
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
||||
case VTXTYPE_TANGENT:
|
||||
return getVertexPitchFromType(video::EVT_TANGENTS);
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
VBOGatherer::VTXTYPE VBOGatherer::getVTXTYPE(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
return VTXTYPE_STANDARD;
|
||||
case video::EVT_2TCOORDS:
|
||||
return VTXTYPE_TCOORD;
|
||||
case video::EVT_TANGENTS:
|
||||
return VTXTYPE_TANGENT;
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
}
|
||||
};
|
||||
|
||||
void VBOGatherer::append(scene::IMeshBuffer *mb, VBOGatherer::VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = vtx_cnt[tp];
|
||||
vtx_cnt[tp] += mb->getVertexCount();
|
||||
vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp));
|
||||
intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp));
|
||||
memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
|
||||
size_t old_idx_cnt = idx_cnt[tp];
|
||||
idx_cnt[tp] += mb->getIndexCount();
|
||||
idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16));
|
||||
|
||||
dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16));
|
||||
memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VBOGatherer::getBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
storedCPUBuffer[tp].push_back(mb);
|
||||
append(mb, tp);
|
||||
regenerateBuffer(tp);
|
||||
regenerateVAO(tp);
|
||||
}
|
||||
|
||||
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
||||
|
||||
static VBOGatherer *gatherersingleton = 0;
|
||||
|
||||
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
if (!gatherersingleton)
|
||||
gatherersingleton = new VBOGatherer();
|
||||
return gatherersingleton->getBase(mb);
|
||||
}
|
||||
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
if (gatherersingleton)
|
||||
return gatherersingleton->getVBO(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
if (gatherersingleton)
|
||||
return gatherersingleton->getVAO(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resetVAO()
|
||||
{
|
||||
if (gatherersingleton)
|
||||
delete gatherersingleton;
|
||||
gatherersingleton = 0;
|
||||
}
|
||||
|
||||
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &timer)
|
||||
{
|
||||
if (!UserConfigParams::m_profiler_enabled) return;
|
||||
@ -780,9 +1027,13 @@ void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
bool useAlphaChannelOfTexture)
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
@ -791,9 +1042,16 @@ void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
getSize(texture_w, texture_h, true,
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
drawTexQuad(texture, width, height, center_pos_x, center_pos_y,
|
||||
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
|
||||
|
||||
glUseProgram(UIShader::UniformColoredTextureRectShader::Program);
|
||||
glBindVertexArray(UIShader::UniformColoredTextureRectShader::vao);
|
||||
|
||||
setTexture(0, texture, GL_LINEAR, GL_LINEAR);
|
||||
UIShader::UniformColoredTextureRectShader::setUniforms(center_pos_x, center_pos_y, width, height, tex_center_pos_x, tex_center_pos_y, tex_width, tex_height, colors, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
|
@ -73,7 +73,9 @@ extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||
extern PFNGLBLENDEQUATIONPROC glBlendEquation;
|
||||
extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
|
||||
extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
|
||||
extern PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
|
||||
extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
|
||||
extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
|
||||
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
|
||||
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
||||
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||
@ -109,6 +111,7 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
|
||||
|
||||
void initGL();
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
video::ITexture* getUnicolorTexture(video::SColor c);
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
|
||||
GLuint LoadShader(const char * file, unsigned type);
|
||||
|
||||
@ -214,7 +217,7 @@ public:
|
||||
FrameBuffer(const std::vector <GLuint> &RTTs, GLuint DS, size_t w, size_t h, bool layered = false);
|
||||
~FrameBuffer();
|
||||
void Bind();
|
||||
std::vector<GLuint> &getRTT() { return RenderTargets; }
|
||||
const std::vector<GLuint> &getRTT() const { return RenderTargets; }
|
||||
GLuint &getDepthTexture() { assert(DepthTexture); return DepthTexture; }
|
||||
size_t getWidth() const { return width; }
|
||||
size_t getHeight() const { return height; }
|
||||
@ -233,13 +236,18 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = f
|
||||
bool loadCompressedTexture(const std::string& compressed_tex);
|
||||
void saveCompressedTexture(const std::string& compressed_tex);
|
||||
|
||||
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb);
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type);
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type);
|
||||
void resetVAO();
|
||||
|
||||
void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, irr::video::SColor color);
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
bool useAlphaChannelOfTexture);
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
|
||||
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
|
||||
|
@ -110,8 +110,9 @@ IrrDriver::IrrDriver()
|
||||
m_post_processing = NULL;
|
||||
m_wind = new Wind();
|
||||
m_mipviz = m_wireframe = m_normals = m_ssaoviz = \
|
||||
m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = 0;
|
||||
SkyboxCubeMap = 0;
|
||||
m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = false;
|
||||
SkyboxCubeMap = m_last_light_bucket_distance = 0;
|
||||
memset(object_count, 0, sizeof(object_count));
|
||||
} // IrrDriver
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -442,12 +443,12 @@ void IrrDriver::initDevice()
|
||||
{
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &GLMinorVersion);
|
||||
}
|
||||
Log::info("IrrDriver", "OpenGL version: %d.%d", GLMajorVersion, GLMinorVersion);
|
||||
Log::info("IrrDriver", "OpenGL vendor: %s", glGetString(GL_VENDOR));
|
||||
Log::info("IrrDriver", "OpenGL renderer: %s", glGetString(GL_RENDERER));
|
||||
Log::info("IrrDriver", "OpenGL version string: %s", glGetString(GL_VERSION));
|
||||
Log::info("IrrDriver", "OpenGL version: %d.%d", GLMajorVersion, GLMinorVersion);
|
||||
Log::info("IrrDriver", "OpenGL vendor: %s", glGetString(GL_VENDOR));
|
||||
Log::info("IrrDriver", "OpenGL renderer: %s", glGetString(GL_RENDERER));
|
||||
Log::info("IrrDriver", "OpenGL version string: %s", glGetString(GL_VERSION));
|
||||
//m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion >= 1));
|
||||
}
|
||||
m_glsl = false;
|
||||
|
||||
// Parse extensions
|
||||
@ -1658,8 +1659,14 @@ void IrrDriver::displayFPS()
|
||||
|
||||
if (UserConfigParams::m_artist_debug_mode)
|
||||
{
|
||||
sprintf(buffer, "FPS: %i/%i/%i - Objects (P1:%d P2:%d T:%d) - LightDst : ~%d",
|
||||
min, fps, max, object_count[SOLID_NORMAL_AND_DEPTH_PASS], object_count[SOLID_NORMAL_AND_DEPTH_PASS], object_count[TRANSPARENT_PASS], m_last_light_bucket_distance);
|
||||
sprintf(
|
||||
buffer, "FPS: %i/%i/%i - Objects (P1:%d P2:%d T:%d) - LightDst : ~%d",
|
||||
min, fps, max,
|
||||
object_count[SOLID_NORMAL_AND_DEPTH_PASS],
|
||||
object_count[SOLID_NORMAL_AND_DEPTH_PASS],
|
||||
object_count[TRANSPARENT_PASS],
|
||||
m_last_light_bucket_distance
|
||||
);
|
||||
object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0;
|
||||
object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0;
|
||||
object_count[TRANSPARENT_PASS] = 0;
|
||||
@ -2056,7 +2063,10 @@ bool IrrDriver::supportsSplatting()
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Begins a rendering to a texture.
|
||||
/**
|
||||
* THIS IS THE OLD OPENGL 1 RTT PROVIDER, USE THE SHADER-BASED
|
||||
* RTT FOR NEW DEVELOPMENT
|
||||
* Begins a rendering to a texture.
|
||||
* \param dimension The size of the texture.
|
||||
* \param name Name of the texture.
|
||||
* \param persistent_texture Whether the created RTT texture should persist in
|
||||
|
@ -230,7 +230,7 @@ private:
|
||||
core::array<video::IRenderTarget> m_mrt;
|
||||
|
||||
/** Matrixes used in several places stored here to avoid recomputation. */
|
||||
core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_InvProjViewMatrix;
|
||||
core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_previousProjViewMatrix, m_InvProjViewMatrix;
|
||||
|
||||
std::vector<video::ITexture *> SkyboxTextures;
|
||||
std::vector<video::ITexture *> SphericalHarmonicsTextures;
|
||||
@ -694,7 +694,8 @@ public:
|
||||
void setProjMatrix(core::matrix4 matrix) { m_ProjMatrix = matrix; matrix.getInverse(m_InvProjMatrix); }
|
||||
const core::matrix4 &getProjMatrix() const { return m_ProjMatrix; }
|
||||
const core::matrix4 &getInvProjMatrix() const { return m_InvProjMatrix; }
|
||||
void genProjViewMatrix() { m_ProjViewMatrix = m_ProjMatrix * m_ViewMatrix; m_InvProjViewMatrix = m_ProjViewMatrix; m_InvProjViewMatrix.makeInverse(); }
|
||||
void genProjViewMatrix() { m_previousProjViewMatrix = m_ProjViewMatrix; m_ProjViewMatrix = m_ProjMatrix * m_ViewMatrix; m_InvProjViewMatrix = m_ProjViewMatrix; m_InvProjViewMatrix.makeInverse(); }
|
||||
const core::matrix4 & getPreviousPVMatrix() { return m_previousProjViewMatrix; }
|
||||
const core::matrix4 &getProjViewMatrix() const { return m_ProjViewMatrix; }
|
||||
const core::matrix4 &getInvProjViewMatrix() const { return m_InvProjViewMatrix; }
|
||||
#ifdef DEBUG
|
||||
@ -716,8 +717,11 @@ public:
|
||||
unsigned UpdateLightsInfo(scene::ICameraSceneNode * const camnode, float dt);
|
||||
void computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height);
|
||||
|
||||
// --------------------- RTT --------------------
|
||||
// --------------------- OLD RTT --------------------
|
||||
/**
|
||||
* THIS IS THE OLD OPENGL 1 RTT PROVIDER, USE THE SHADER-BASED
|
||||
* RTT FOR NEW DEVELOPMENT
|
||||
*
|
||||
* Class that provides RTT (currently, only when no other 3D rendering
|
||||
* in the main scene is required)
|
||||
* Provides an optional 'setupRTTScene' method to make it quick and easy
|
||||
|
@ -757,7 +757,6 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
|
||||
|
||||
if (m_shader_type == SHADERTYPE_SOLID && m_normal_map_tex.size() > 0)
|
||||
{
|
||||
IVideoDriver* video_driver = irr_driver->getVideoDriver();
|
||||
if (irr_driver->isGLSL())
|
||||
{
|
||||
// FIXME; cannot perform this check atm, because setMaterialProperties
|
||||
|
@ -17,9 +17,11 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/mesh_tools.hpp"
|
||||
#include <irrlicht.h>
|
||||
#include <IMesh.h>
|
||||
#include <IMeshBuffer.h>
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
|
||||
@ -80,3 +82,357 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
} // for i<getMeshBufferCount
|
||||
} // minMax3D
|
||||
|
||||
// Copied from irrlicht
|
||||
void calculateTangents(
|
||||
core::vector3df& normal,
|
||||
core::vector3df& tangent,
|
||||
core::vector3df& binormal,
|
||||
const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
|
||||
const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
|
||||
{
|
||||
core::vector3df v1 = vt1 - vt2;
|
||||
core::vector3df v2 = vt3 - vt1;
|
||||
normal = v2.crossProduct(v1);
|
||||
normal.normalize();
|
||||
|
||||
// binormal
|
||||
|
||||
f32 deltaX1 = tc1.X - tc2.X;
|
||||
f32 deltaX2 = tc3.X - tc1.X;
|
||||
binormal = (v1 * deltaX2) - (v2 * deltaX1);
|
||||
binormal.normalize();
|
||||
|
||||
// tangent
|
||||
|
||||
f32 deltaY1 = tc1.Y - tc2.Y;
|
||||
f32 deltaY2 = tc3.Y - tc1.Y;
|
||||
tangent = (v1 * deltaY2) - (v2 * deltaY1);
|
||||
tangent.normalize();
|
||||
|
||||
// adjust
|
||||
|
||||
core::vector3df txb = tangent.crossProduct(binormal);
|
||||
if (txb.dotProduct(normal) < 0.0f)
|
||||
{
|
||||
tangent *= -1.0f;
|
||||
binormal *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
static inline core::vector3df getAngleWeight(const core::vector3df& v1,
|
||||
const core::vector3df& v2,
|
||||
const core::vector3df& v3)
|
||||
{
|
||||
// Calculate this triangle's weight for each of its three vertices
|
||||
// start by calculating the lengths of its sides
|
||||
const f32 a = v2.getDistanceFromSQ(v3);
|
||||
const f32 asqrt = sqrtf(a);
|
||||
const f32 b = v1.getDistanceFromSQ(v3);
|
||||
const f32 bsqrt = sqrtf(b);
|
||||
const f32 c = v1.getDistanceFromSQ(v2);
|
||||
const f32 csqrt = sqrtf(c);
|
||||
|
||||
// use them to find the angle at each vertex
|
||||
return core::vector3df(
|
||||
acosf((b + c - a) / (2.f * bsqrt * csqrt)),
|
||||
acosf((-b + c + a) / (2.f * asqrt * csqrt)),
|
||||
acosf((b - c + a) / (2.f * bsqrt * asqrt)));
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
template <typename T>
|
||||
void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
|
||||
{
|
||||
if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS))
|
||||
return;
|
||||
|
||||
const u32 vtxCnt = buffer->getVertexCount();
|
||||
const u32 idxCnt = buffer->getIndexCount();
|
||||
|
||||
T* idx = reinterpret_cast<T*>(buffer->getIndices());
|
||||
video::S3DVertexTangents* v =
|
||||
(video::S3DVertexTangents*)buffer->getVertices();
|
||||
|
||||
if (smooth)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
{
|
||||
if (recalculateNormals)
|
||||
v[i].Normal.set(0.f, 0.f, 0.f);
|
||||
v[i].Tangent.set(0.f, 0.f, 0.f);
|
||||
v[i].Binormal.set(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
//Each vertex gets the sum of the tangents and binormals from the faces around it
|
||||
for (i = 0; i<idxCnt; i += 3)
|
||||
{
|
||||
// if this triangle is degenerate, skip it!
|
||||
if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos ||
|
||||
v[idx[i + 0]].Pos == v[idx[i + 2]].Pos ||
|
||||
v[idx[i + 1]].Pos == v[idx[i + 2]].Pos
|
||||
/*||
|
||||
v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
|
||||
v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
|
||||
v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
|
||||
)
|
||||
continue;
|
||||
|
||||
//Angle-weighted normals look better, but are slightly more CPU intensive to calculate
|
||||
core::vector3df weight(1.f, 1.f, 1.f);
|
||||
if (angleWeighted)
|
||||
weight = getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos);
|
||||
core::vector3df localNormal;
|
||||
core::vector3df localTangent;
|
||||
core::vector3df localBinormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 0]].Normal += localNormal * weight.X;
|
||||
v[idx[i + 0]].Tangent += localTangent * weight.X;
|
||||
v[idx[i + 0]].Binormal += localBinormal * weight.X;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 1]].Normal += localNormal * weight.Y;
|
||||
v[idx[i + 1]].Tangent += localTangent * weight.Y;
|
||||
v[idx[i + 1]].Binormal += localBinormal * weight.Y;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 2]].Normal += localNormal * weight.Z;
|
||||
v[idx[i + 2]].Tangent += localTangent * weight.Z;
|
||||
v[idx[i + 2]].Binormal += localBinormal * weight.Z;
|
||||
}
|
||||
|
||||
// Normalize the tangents and binormals
|
||||
if (recalculateNormals)
|
||||
{
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
v[i].Normal.normalize();
|
||||
}
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
{
|
||||
v[i].Tangent.normalize();
|
||||
v[i].Binormal.normalize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::vector3df localNormal;
|
||||
for (u32 i = 0; i<idxCnt; i += 3)
|
||||
{
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 0]].Tangent,
|
||||
v[idx[i + 0]].Binormal,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 0]].Normal = localNormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 1]].Tangent,
|
||||
v[idx[i + 1]].Binormal,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 1]].Normal = localNormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 2]].Tangent,
|
||||
v[idx[i + 2]].Binormal,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 2]].Normal = localNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
void recalculateTangents(scene::IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
|
||||
{
|
||||
if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
|
||||
{
|
||||
if (buffer->getIndexType() == video::EIT_16BIT)
|
||||
recalculateTangentsT<u16>(buffer, recalculateNormals, smooth, angleWeighted);
|
||||
else
|
||||
recalculateTangentsT<u32>(buffer, recalculateNormals, smooth, angleWeighted);
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
void recalculateTangents(scene::IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted)
|
||||
{
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
const u32 meshBufferCount = mesh->getMeshBufferCount();
|
||||
for (u32 b = 0; b<meshBufferCount; ++b)
|
||||
{
|
||||
recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted);
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
|
||||
{
|
||||
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP));
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
|
||||
bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents)
|
||||
{
|
||||
if (!mesh)
|
||||
return 0;
|
||||
|
||||
// copy mesh and fill data into SMeshBufferTangents
|
||||
|
||||
scene::SMesh* clone = new scene::SMesh();
|
||||
const u32 meshBufferCount = mesh->getMeshBufferCount();
|
||||
|
||||
bool needsNormalMap = false;
|
||||
for (u32 b = 0; b < meshBufferCount; ++b)
|
||||
{
|
||||
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
|
||||
if (predicate(original))
|
||||
{
|
||||
needsNormalMap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsNormalMap)
|
||||
{
|
||||
return mesh;
|
||||
}
|
||||
|
||||
for (u32 b = 0; b<meshBufferCount; ++b)
|
||||
{
|
||||
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
|
||||
const u32 idxCnt = original->getIndexCount();
|
||||
const u16* idx = original->getIndices();
|
||||
|
||||
if (!predicate(original))
|
||||
{
|
||||
clone->addMeshBuffer(original);
|
||||
continue;
|
||||
}
|
||||
|
||||
scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();
|
||||
|
||||
buffer->Material = original->getMaterial();
|
||||
buffer->Vertices.reallocate(idxCnt);
|
||||
buffer->Indices.reallocate(idxCnt);
|
||||
|
||||
core::map<video::S3DVertexTangents, int> vertMap;
|
||||
int vertLocation;
|
||||
|
||||
// copy vertices
|
||||
|
||||
const video::E_VERTEX_TYPE vType = original->getVertexType();
|
||||
video::S3DVertexTangents vNew;
|
||||
for (u32 i = 0; i<idxCnt; ++i)
|
||||
{
|
||||
switch (vType)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
const video::S3DVertex* v =
|
||||
(const video::S3DVertex*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
const video::S3DVertex2TCoords* v =
|
||||
(const video::S3DVertex2TCoords*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
const video::S3DVertexTangents* v =
|
||||
(const video::S3DVertexTangents*)original->getVertices();
|
||||
vNew = v[idx[i]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
|
||||
if (n)
|
||||
{
|
||||
vertLocation = n->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
vertLocation = buffer->Vertices.size();
|
||||
buffer->Vertices.push_back(vNew);
|
||||
vertMap.insert(vNew, vertLocation);
|
||||
}
|
||||
|
||||
// create new indices
|
||||
buffer->Indices.push_back(vertLocation);
|
||||
}
|
||||
buffer->recalculateBoundingBox();
|
||||
|
||||
// add new buffer
|
||||
clone->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
|
||||
clone->recalculateBoundingBox();
|
||||
if (calculateTangents)
|
||||
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class IMesh; }
|
||||
namespace scene { class IMesh; class IMeshBuffer; }
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
@ -33,6 +33,12 @@ using namespace irr;
|
||||
namespace MeshTools
|
||||
{
|
||||
void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max);
|
||||
|
||||
bool isNormalMap(scene::IMeshBuffer* mb);
|
||||
|
||||
// Copied from irrlicht
|
||||
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
|
||||
bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false, bool calculateTangents = true);
|
||||
} // MeshTools
|
||||
|
||||
#endif
|
||||
|
@ -207,10 +207,6 @@ void PostProcessing::update(float dt)
|
||||
static
|
||||
void renderBloom(GLuint in)
|
||||
{
|
||||
float threshold = 1.0f;
|
||||
if (World::getWorld() != NULL)
|
||||
threshold = World::getWorld()->getTrack()->getBloomThreshold();
|
||||
|
||||
glUseProgram(FullScreenShader::BloomShader::Program);
|
||||
glBindVertexArray(FullScreenShader::BloomShader::vao);
|
||||
|
||||
@ -611,13 +607,17 @@ void PostProcessing::renderMotionBlur(unsigned cam, FrameBuffer &in_fbo, FrameBu
|
||||
glUseProgram(FullScreenShader::MotionBlurShader::Program);
|
||||
glBindVertexArray(FullScreenShader::MotionBlurShader::vao);
|
||||
|
||||
setTexture(0, in_fbo.getRTT()[0], GL_NEAREST, GL_NEAREST);
|
||||
setTexture(0, in_fbo.getRTT()[0], GL_LINEAR, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
|
||||
FullScreenShader::MotionBlurShader
|
||||
::setUniforms(cb->getBoostTime(cam), cb->getCenter(cam),
|
||||
cb->getDirection(cam), 0.15f,
|
||||
cb->getMaxHeight(cam) * 0.7f, 0);
|
||||
::setUniforms(cb->getBoostTime(0) * 10, // Todo : should be framerate dependent
|
||||
// Todo : use a previousPVMatrix per cam, not global
|
||||
irr_driver->getPreviousPVMatrix(),
|
||||
cb->getCenter(cam),
|
||||
0.15f,
|
||||
0, 1);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
@ -676,7 +676,7 @@ static void averageTexture(GLuint tex)
|
||||
void PostProcessing::applyMLAA()
|
||||
{
|
||||
const core::vector2df &PIXEL_SIZE = core::vector2df(1.0f / UserConfigParams::m_width, 1.0f / UserConfigParams::m_height);
|
||||
IVideoDriver *const drv = irr_driver->getVideoDriver();
|
||||
|
||||
irr_driver->getFBO(FBO_MLAA_TMP).Bind();
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
@ -727,15 +727,8 @@ void PostProcessing::applyMLAA()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Render the post-processed scene */
|
||||
FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode)
|
||||
FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, bool isRace)
|
||||
{
|
||||
IVideoDriver * const drv = irr_driver->getVideoDriver();
|
||||
|
||||
MotionBlurProvider * const mocb = (MotionBlurProvider *) irr_driver->
|
||||
getCallback(ES_MOTIONBLUR);
|
||||
GaussianBlurProvider * const gacb = (GaussianBlurProvider *) irr_driver->
|
||||
getCallback(ES_GAUSSIAN3H);
|
||||
|
||||
FrameBuffer *in_fbo = &irr_driver->getFBO(FBO_COLORS);
|
||||
FrameBuffer *out_fbo = &irr_driver->getFBO(FBO_TMP1_WITH_DS);
|
||||
// Each effect uses these as named, and sets them up for the next effect.
|
||||
@ -745,7 +738,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (UserConfigParams::m_dof)
|
||||
if (isRace && UserConfigParams::m_dof)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- DoF", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_DOF));
|
||||
@ -761,7 +754,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode)
|
||||
if (World::getWorld() != NULL)
|
||||
hasgodrays = World::getWorld()->getTrack()->hasGodRays();
|
||||
|
||||
if (UserConfigParams::m_light_shaft && m_sunpixels > 30 && hasgodrays)
|
||||
if (isRace && UserConfigParams::m_light_shaft && m_sunpixels > 30 && hasgodrays)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
// Grab the sky
|
||||
@ -827,7 +820,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_BLOOM));
|
||||
if (UserConfigParams::m_bloom)
|
||||
if (isRace && UserConfigParams::m_bloom)
|
||||
{
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
||||
@ -879,7 +872,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MOTIONBLUR));
|
||||
if (UserConfigParams::m_motionblur && m_any_boost && World::getWorld() != NULL) // motion blur
|
||||
if (isRace && UserConfigParams::m_motionblur && World::getWorld() != NULL) // motion blur
|
||||
{
|
||||
renderMotionBlur(0, *in_fbo, *out_fbo);
|
||||
std::swap(in_fbo, out_fbo);
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
void renderGlow(unsigned tex);
|
||||
|
||||
/** Render the post-processed scene */
|
||||
FrameBuffer *render(scene::ICameraSceneNode * const camnode);
|
||||
FrameBuffer *render(scene::ICameraSceneNode * const camnode, bool isRace);
|
||||
|
||||
/** Use motion blur for a short time */
|
||||
void giveBoost(unsigned int cam_index);
|
||||
|
@ -125,7 +125,6 @@ void IrrDriver::renderGLSL(float dt)
|
||||
|
||||
RaceGUIBase *rg = world->getRaceGUI();
|
||||
if (rg) rg->update(dt);
|
||||
irr::video::COpenGLDriver* gl_driver = (irr::video::COpenGLDriver*)m_device->getVideoDriver();
|
||||
|
||||
for(unsigned int cam = 0; cam < Camera::getNumCameras(); cam++)
|
||||
{
|
||||
@ -186,12 +185,17 @@ void IrrDriver::renderGLSL(float dt)
|
||||
// Render the post-processed scene
|
||||
if (UserConfigParams::m_dynamic_lights)
|
||||
{
|
||||
FrameBuffer *fbo = m_post_processing->render(camnode);
|
||||
bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME;
|
||||
FrameBuffer *fbo = m_post_processing->render(camnode, isRace);
|
||||
|
||||
if (irr_driver->getNormals())
|
||||
irr_driver->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
else if (irr_driver->getSSAOViz())
|
||||
irr_driver->getFBO(FBO_HALF1_R).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
m_post_processing->renderPassThrough(m_rtts->getFBO(FBO_HALF1_R).getRTT()[0]);
|
||||
}
|
||||
else if (irr_driver->getRSM())
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@ -205,9 +209,6 @@ void IrrDriver::renderGLSL(float dt)
|
||||
else
|
||||
fbo->BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
}
|
||||
else
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
} // for i<world->getNumKarts()
|
||||
@ -269,8 +270,6 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po
|
||||
renderSolidFirstPass();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
const core::aabbox3df cambox = camnode->getViewFrustum()->getBoundingBox();
|
||||
|
||||
// Shadows
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
|
||||
@ -375,7 +374,10 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
if (!UserConfigParams::m_dynamic_lights && !forceRTT)
|
||||
{
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
return;
|
||||
}
|
||||
|
||||
// Render displacement
|
||||
{
|
||||
@ -515,7 +517,8 @@ void IrrDriver::renderSolidFirstPass()
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS);
|
||||
GroupedFPSM<FPSM_DEFAULT>::reset();
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::reset();
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::reset();
|
||||
GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::reset();
|
||||
GroupedFPSM<FPSM_NORMAL_MAP>::reset();
|
||||
m_scene_manager->drawAll(scene::ESNRP_SOLID);
|
||||
@ -526,46 +529,58 @@ void IrrDriver::renderSolidFirstPass()
|
||||
{
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1));
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
|
||||
{
|
||||
const GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
|
||||
if (mesh.textures[0])
|
||||
{
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTexture(0, 0, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, false);
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
draw<MeshShader::ObjectPass1Shader>(mesh, mesh.vao, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT>::TIMVSet[i], 0);
|
||||
GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i];
|
||||
if (!mesh.textures[0])
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::ObjectPass1Shader>(mesh, GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet[i], 0);
|
||||
}
|
||||
|
||||
glBindVertexArray(getVAO(video::EVT_2TCOORDS));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
|
||||
{
|
||||
GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i];
|
||||
if (!mesh.textures[0])
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::ObjectPass1Shader>(mesh, GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet[i], 0);
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet.size(); ++i)
|
||||
{
|
||||
const GLMesh &mesh = *GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i];
|
||||
if (mesh.VAOType != video::EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::ObjectRefPass1Shader>(mesh, mesh.vao, GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix, 0);
|
||||
|
||||
draw<MeshShader::ObjectRefPass1Shader>(mesh, GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix, 0);
|
||||
}
|
||||
glUseProgram(MeshShader::NormalMapShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_TANGENTS));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet.size(); ++i)
|
||||
{
|
||||
const GLMesh &mesh = *GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i];
|
||||
assert(mesh.VAOType == video::EVT_TANGENTS);
|
||||
assert(mesh.textures[1]);
|
||||
compressTexture(mesh.textures[1], false);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::NormalMapShader>(mesh, mesh.vao, GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i], 0, 1);
|
||||
|
||||
draw<MeshShader::NormalMapShader>(mesh, GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i], 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -592,14 +607,14 @@ void IrrDriver::renderSolidSecondPass()
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
GroupedSM<SM_DEFAULT>::reset();
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::reset();
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::reset();
|
||||
GroupedSM<SM_ALPHA_REF_TEXTURE>::reset();
|
||||
GroupedSM<SM_RIMLIT>::reset();
|
||||
GroupedSM<SM_SPHEREMAP>::reset();
|
||||
GroupedSM<SM_SPLATTING>::reset();
|
||||
GroupedSM<SM_UNLIT>::reset();
|
||||
GroupedSM<SM_DETAILS>::reset();
|
||||
GroupedSM<SM_UNTEXTURED>::reset();
|
||||
setTexture(0, m_rtts->getRenderTarget(RTT_TMP1), GL_NEAREST, GL_NEAREST);
|
||||
setTexture(1, m_rtts->getRenderTarget(RTT_TMP2), GL_NEAREST, GL_NEAREST);
|
||||
setTexture(2, m_rtts->getRenderTarget(RTT_HALF1_R), GL_LINEAR, GL_LINEAR);
|
||||
@ -611,36 +626,179 @@ void IrrDriver::renderSolidSecondPass()
|
||||
m_scene_manager->drawAll(scene::ESNRP_SOLID);
|
||||
|
||||
glUseProgram(MeshShader::ObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < GroupedSM<SM_DEFAULT>::MeshSet.size(); i++)
|
||||
drawObjectPass2(*GroupedSM<SM_DEFAULT>::MeshSet[i], GroupedSM<SM_DEFAULT>::MVPSet[i], GroupedSM<SM_DEFAULT>::MeshSet[i]->TextureMatrix);
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_DEFAULT_STANDARD>::MeshSet.size(); i++)
|
||||
{
|
||||
GLMesh &mesh = *GroupedSM<SM_DEFAULT_STANDARD>::MeshSet[i];
|
||||
if (mesh.VAOType != video::EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (!mesh.textures[0])
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
draw<MeshShader::ObjectPass2Shader>(mesh, GroupedSM<SM_DEFAULT_STANDARD>::MVPSet[i], GroupedSM<SM_DEFAULT_STANDARD>::MeshSet[i]->TextureMatrix);
|
||||
}
|
||||
|
||||
glBindVertexArray(getVAO(video::EVT_TANGENTS));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_DEFAULT_TANGENT>::MeshSet.size(); i++)
|
||||
{
|
||||
const GLMesh &mesh = *GroupedSM<SM_DEFAULT_TANGENT>::MeshSet[i];
|
||||
assert(mesh.VAOType == video::EVT_TANGENTS);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
draw<MeshShader::ObjectPass2Shader>(mesh, GroupedSM<SM_DEFAULT_TANGENT>::MVPSet[i], GroupedSM<SM_DEFAULT_TANGENT>::MeshSet[i]->TextureMatrix);
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet.size(); i++)
|
||||
drawObjectRefPass2(*GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i], GroupedSM<SM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
const GLMesh &mesh = *GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i];
|
||||
if (mesh.VAOType != video::EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
draw<MeshShader::ObjectRefPass2Shader>(mesh, GroupedSM<SM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix);
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_RIMLIT>::MeshSet.size(); i++)
|
||||
drawObjectRimLimit(*GroupedSM<SM_RIMLIT>::MeshSet[i], GroupedSM<SM_RIMLIT>::MVPSet[i], GroupedSM<SM_RIMLIT>::TIMVSet[i], GroupedSM<SM_RIMLIT>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
const GLMesh &mesh = *GroupedSM<SM_RIMLIT>::MeshSet[i];
|
||||
assert(mesh.VAOType == EVT_STANDARD);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectRimLimitShader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
draw<MeshShader::ObjectRimLimitShader>(mesh, GroupedSM<SM_RIMLIT>::MVPSet[i], GroupedSM<SM_RIMLIT>::TIMVSet[i], GroupedSM<SM_RIMLIT>::MeshSet[i]->TextureMatrix);
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::SphereMapShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_SPHEREMAP>::MeshSet.size(); i++)
|
||||
drawSphereMap(*GroupedSM<SM_SPHEREMAP>::MeshSet[i], GroupedSM<SM_SPHEREMAP>::MVPSet[i], GroupedSM<SM_SPHEREMAP>::TIMVSet[i]);
|
||||
{
|
||||
const GLMesh &mesh = *GroupedSM<SM_SPHEREMAP>::MeshSet[i];
|
||||
assert(mesh.VAOType == EVT_STANDARD);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::SphereMapShader>(mesh, GroupedSM<SM_SPHEREMAP>::MVPSet[i], GroupedSM<SM_SPHEREMAP>::TIMVSet[i], irr_driver->getSceneManager()->getAmbientLight());
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::SplattingShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_2TCOORDS));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_SPLATTING>::MeshSet.size(); i++)
|
||||
drawSplatting(*GroupedSM<SM_SPLATTING>::MeshSet[i], GroupedSM<SM_SPLATTING>::MVPSet[i]);
|
||||
|
||||
glUseProgram(MeshShader::ObjectUnlitShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_UNLIT>::MeshSet.size(); i++)
|
||||
drawObjectUnlit(*GroupedSM<SM_UNLIT>::MeshSet[i], GroupedSM<SM_UNLIT>::MVPSet[i]);
|
||||
{
|
||||
const GLMesh &mesh = *GroupedSM<SM_UNLIT>::MeshSet[i];
|
||||
assert(mesh.VAOType == EVT_STANDARD);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
draw<MeshShader::ObjectUnlitShader>(mesh, GroupedSM<SM_UNLIT>::MVPSet[i]);
|
||||
}
|
||||
|
||||
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
|
||||
glBindVertexArray(getVAO(EVT_2TCOORDS));
|
||||
for (unsigned i = 0; i < GroupedSM<SM_DETAILS>::MeshSet.size(); i++)
|
||||
drawDetailledObjectPass2(*GroupedSM<SM_DETAILS>::MeshSet[i], GroupedSM<SM_DETAILS>::MVPSet[i]);
|
||||
|
||||
glUseProgram(MeshShader::UntexturedObjectShader::Program);
|
||||
for (unsigned i = 0; i < GroupedSM<SM_UNTEXTURED>::MeshSet.size(); i++)
|
||||
drawUntexturedObject(*GroupedSM<SM_UNTEXTURED>::MeshSet[i], GroupedSM<SM_UNTEXTURED>::MVPSet[i]);
|
||||
{
|
||||
GLMesh &mesh = *GroupedSM<SM_DETAILS>::MeshSet[i];
|
||||
assert(mesh.VAOType == EVT_2TCOORDS);
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
if (!mesh.textures[1])
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "No detail/lightmap texture provided for detail/lightmap material.");
|
||||
#endif
|
||||
mesh.textures[1] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
}
|
||||
compressTexture(mesh.textures[1], true);
|
||||
setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::DetailledObjectPass2Shader>(mesh, GroupedSM<SM_DETAILS>::MVPSet[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -657,25 +815,112 @@ void IrrDriver::renderTransparent()
|
||||
TransparentMeshes<TM_ADDITIVE>::reset();
|
||||
m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT);
|
||||
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
{
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
|
||||
// This function is only called once per frame - thus no need for setters.
|
||||
const float fogmax = track->getFogMax();
|
||||
const float startH = track->getFogStartHeight();
|
||||
const float endH = track->getFogEndHeight();
|
||||
const float start = track->getFogStart();
|
||||
const float end = track->getFogEnd();
|
||||
const video::SColor tmpcol = track->getFogColor();
|
||||
|
||||
core::vector3df col(tmpcol.getRed() / 255.0f,
|
||||
tmpcol.getGreen() / 255.0f,
|
||||
tmpcol.getBlue() / 255.0f);
|
||||
|
||||
glUseProgram(MeshShader::TransparentFogShader::Program);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
for (unsigned i = 0; i < TransparentMeshes<TM_DEFAULT>::MeshSet.size(); i++)
|
||||
drawTransparentFogObject(*TransparentMeshes<TM_DEFAULT>::MeshSet[i], TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
GLMesh &mesh = *TransparentMeshes<TM_DEFAULT>::MeshSet[i];
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to fog + transparent blend (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
}
|
||||
|
||||
|
||||
if (!mesh.textures[0])
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
draw<MeshShader::TransparentFogShader>(mesh, TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
}
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
for (unsigned i = 0; i < TransparentMeshes<TM_ADDITIVE>::MeshSet.size(); i++)
|
||||
drawTransparentFogObject(*TransparentMeshes<TM_ADDITIVE>::MeshSet[i], TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
GLMesh &mesh = *TransparentMeshes<TM_ADDITIVE>::MeshSet[i];
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
}
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
|
||||
if (!mesh.textures[0])
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
draw<MeshShader::TransparentFogShader>(mesh, TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
for (unsigned i = 0; i < TransparentMeshes<TM_DEFAULT>::MeshSet.size(); i++)
|
||||
drawTransparentObject(*TransparentMeshes<TM_DEFAULT>::MeshSet[i], TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
GLMesh &mesh = *TransparentMeshes<TM_DEFAULT>::MeshSet[i];
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
}
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
if (!mesh.textures[0])
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::TransparentShader>(mesh, TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix, 0);
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
}
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
for (unsigned i = 0; i < TransparentMeshes<TM_ADDITIVE>::MeshSet.size(); i++)
|
||||
drawTransparentObject(*TransparentMeshes<TM_ADDITIVE>::MeshSet[i], TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix);
|
||||
{
|
||||
const GLMesh &mesh = *TransparentMeshes<TM_ADDITIVE>::MeshSet[i];
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
|
||||
#endif
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
}
|
||||
glBindVertexArray(getVAO(mesh.VAOType));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::TransparentShader>(mesh, TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix, 0);
|
||||
if (mesh.VAOType != EVT_STANDARD)
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -837,13 +1082,19 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
{
|
||||
core::aabbox3df trackbox(vmin->toIrrVector(), vmax->toIrrVector() -
|
||||
core::vector3df(0, 30, 0));
|
||||
SunCamViewMatrix.transformBoxEx(trackbox);
|
||||
core::matrix4 tmp_matrix;
|
||||
tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
|
||||
trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
|
||||
30, trackbox.MaxEdge.Z);
|
||||
m_suncam->setProjectionMatrix(tmp_matrix, true);
|
||||
m_suncam->render();
|
||||
if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
|
||||
trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
|
||||
// Cover the case where SunCamViewMatrix is null
|
||||
SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
|
||||
{
|
||||
SunCamViewMatrix.transformBoxEx(trackbox);
|
||||
core::matrix4 tmp_matrix;
|
||||
tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
|
||||
trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
|
||||
30, trackbox.MaxEdge.Z);
|
||||
m_suncam->setProjectionMatrix(tmp_matrix, true);
|
||||
m_suncam->render();
|
||||
}
|
||||
rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
|
||||
}
|
||||
rh_extend = core::vector3df(128, 64, 128);
|
||||
@ -871,9 +1122,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
|
||||
void IrrDriver::renderShadows()
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT>::reset();
|
||||
GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::reset();
|
||||
GroupedFPSM<FPSM_NORMAL_MAP>::reset();
|
||||
irr_driver->setPhase(SHADOW_PASS);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
@ -887,12 +1135,18 @@ void IrrDriver::renderShadows()
|
||||
m_scene_manager->drawAll(scene::ESNRP_SOLID);
|
||||
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
|
||||
drawShadow(*GroupedFPSM<FPSM_DEFAULT>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT>::MVPSet[i]);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
|
||||
drawShadow(*GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i]);
|
||||
glBindVertexArray(getVAO(EVT_2TCOORDS));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
|
||||
drawShadow(*GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i]);
|
||||
glBindVertexArray(getVAO(EVT_TANGENTS));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet.size(); ++i)
|
||||
drawShadow(*GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i]);
|
||||
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet.size(); ++i)
|
||||
drawShadowRef(*GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i]);
|
||||
|
||||
@ -905,14 +1159,25 @@ void IrrDriver::renderShadows()
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glUseProgram(MeshShader::RSMShader::Program);
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
|
||||
{
|
||||
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
|
||||
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i];
|
||||
if (!mesh.textures[0])
|
||||
continue;
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::RSMShader>(mesh, mesh.vao, rsm_matrix, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], 0);
|
||||
draw<MeshShader::RSMShader>(mesh, rsm_matrix, GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i], 0);
|
||||
}
|
||||
glBindVertexArray(getVAO(EVT_2TCOORDS));
|
||||
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
|
||||
{
|
||||
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i];
|
||||
if (!mesh.textures[0])
|
||||
continue;
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
draw<MeshShader::RSMShader>(mesh, rsm_matrix, GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -968,6 +1233,7 @@ void IrrDriver::renderGlow(std::vector<GlowData>& glows)
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glBindVertexArray(getVAO(EVT_STANDARD));
|
||||
for (u32 i = 0; i < glowcount; i++)
|
||||
{
|
||||
const GlowData &dat = glows[i];
|
||||
@ -1675,6 +1941,7 @@ void IrrDriver::renderDisplacement()
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
glBindVertexArray(getVAO(EVT_2TCOORDS));
|
||||
for (int i = 0; i < displacingcount; i++)
|
||||
{
|
||||
m_scene_manager->setCurrentRendertime(scene::ESNRP_TRANSPARENT);
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/post_processing.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include <ISceneManager.h>
|
||||
|
||||
static GLuint generateRTT3D(GLenum target, size_t w, size_t h, size_t d, GLint internalFormat, GLint format, GLint type)
|
||||
{
|
||||
@ -72,6 +74,8 @@ static GLuint generateFBO(GLuint ColorAttachement, GLuint DepthAttachement)
|
||||
|
||||
RTT::RTT(size_t width, size_t height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_shadow_FBO = NULL;
|
||||
m_RH_FBO = NULL;
|
||||
m_RSM = NULL;
|
||||
@ -79,12 +83,10 @@ RTT::RTT(size_t width, size_t height)
|
||||
using namespace video;
|
||||
using namespace core;
|
||||
|
||||
IVideoDriver * const drv = irr_driver->getVideoDriver();
|
||||
const dimension2du res(width, height);
|
||||
const dimension2du half = res/2;
|
||||
const dimension2du quarter = res/4;
|
||||
const dimension2du eighth = res/8;
|
||||
const dimension2du sixteenth = res/16;
|
||||
|
||||
const u16 shadowside = 1024;
|
||||
const dimension2du shadowsize0(shadowside, shadowside);
|
||||
@ -281,3 +283,24 @@ RTT::~RTT()
|
||||
glDeleteTextures(1, &RH_Blue);
|
||||
}
|
||||
}
|
||||
|
||||
FrameBuffer* RTT::render(scene::ICameraSceneNode* camera, float dt)
|
||||
{
|
||||
irr_driver->setRTT(this);
|
||||
|
||||
irr_driver->getSceneManager()->setActiveCamera(camera);
|
||||
|
||||
std::vector<IrrDriver::GlowData> glows;
|
||||
irr_driver->computeCameraMatrix(camera, m_width, m_height);
|
||||
unsigned plc = irr_driver->UpdateLightsInfo(camera, dt);
|
||||
irr_driver->renderScene(camera, plc, glows, dt, false, true);
|
||||
FrameBuffer* frame_buffer = irr_driver->getPostProcessing()->render(camera, false);
|
||||
|
||||
// reset
|
||||
glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height);
|
||||
irr_driver->setRTT(NULL);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
irr_driver->getSceneManager()->setActiveCamera(NULL);
|
||||
return frame_buffer;
|
||||
}
|
||||
|
@ -45,11 +45,17 @@ public:
|
||||
unsigned getDepthStencilTexture() const { return DepthStencilTexture; }
|
||||
unsigned getRenderTarget(enum TypeRTT target) const { return RenderTargetTextures[target]; }
|
||||
FrameBuffer& getFBO(enum TypeFBO fbo) { return FrameBuffers[fbo]; }
|
||||
|
||||
FrameBuffer* render(scene::ICameraSceneNode* camera, float dt);
|
||||
|
||||
private:
|
||||
unsigned RenderTargetTextures[RTT_COUNT];
|
||||
PtrVector<FrameBuffer> FrameBuffers;
|
||||
unsigned DepthStencilTexture;
|
||||
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
unsigned shadowColorTex, shadowNormalTex, shadowDepthTex;
|
||||
unsigned RSM_Color, RSM_Normal, RSM_Depth;
|
||||
unsigned RH_Red, RH_Green, RH_Blue;
|
||||
|
@ -876,7 +876,6 @@ namespace MeshShader
|
||||
GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap");
|
||||
GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO");
|
||||
uniform_ambient = glGetUniformLocation(Program, "ambient");
|
||||
GLuint uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
if (!UserConfigParams::m_ubo_disabled)
|
||||
{
|
||||
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
|
||||
@ -1100,7 +1099,6 @@ namespace MeshShader
|
||||
uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix");
|
||||
uniform_ambient = glGetUniformLocation(Program, "ambient");
|
||||
GLuint uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo");
|
||||
GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap");
|
||||
GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap");
|
||||
GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO");
|
||||
@ -1539,6 +1537,7 @@ namespace MeshShader
|
||||
GLuint DisplaceShader::uniform_displacement_tex;
|
||||
GLuint DisplaceShader::uniform_mask_tex;
|
||||
GLuint DisplaceShader::uniform_color_tex;
|
||||
GLuint DisplaceShader::uniform_tex;
|
||||
GLuint DisplaceShader::uniform_dir;
|
||||
GLuint DisplaceShader::uniform_dir2;
|
||||
|
||||
@ -1553,11 +1552,12 @@ namespace MeshShader
|
||||
uniform_mask_tex = glGetUniformLocation(Program, "mask_tex");
|
||||
uniform_dir = glGetUniformLocation(Program, "dir");
|
||||
uniform_dir2 = glGetUniformLocation(Program, "dir2");
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
|
||||
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
|
||||
}
|
||||
|
||||
void DisplaceShader::setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex)
|
||||
void DisplaceShader::setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex)
|
||||
{
|
||||
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer());
|
||||
glUniform2f(uniform_dir, dir.X, dir.Y);
|
||||
@ -1565,6 +1565,7 @@ namespace MeshShader
|
||||
glUniform1i(uniform_displacement_tex, TU_displacement_tex);
|
||||
glUniform1i(uniform_mask_tex, TU_mask_tex);
|
||||
glUniform1i(uniform_color_tex, TU_color_tex);
|
||||
glUniform1i(uniform_tex, TU_tex);
|
||||
}
|
||||
|
||||
GLuint SkyboxShader::Program;
|
||||
@ -2665,33 +2666,34 @@ namespace FullScreenShader
|
||||
GLuint MotionBlurShader::uniform_boost_amount;
|
||||
GLuint MotionBlurShader::uniform_center;
|
||||
GLuint MotionBlurShader::uniform_color_buffer;
|
||||
GLuint MotionBlurShader::uniform_direction;
|
||||
GLuint MotionBlurShader::uniform_dtex;
|
||||
GLuint MotionBlurShader::uniform_previous_viewproj;
|
||||
GLuint MotionBlurShader::uniform_mask_radius;
|
||||
GLuint MotionBlurShader::uniform_max_tex_height;
|
||||
GLuint MotionBlurShader::vao;
|
||||
|
||||
void MotionBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/motion_blur.frag").c_str());
|
||||
uniform_boost_amount = glGetUniformLocation(Program, "boost_amount");
|
||||
uniform_center = glGetUniformLocation(Program, "center");
|
||||
uniform_color_buffer = glGetUniformLocation(Program, "color_buffer");
|
||||
uniform_direction = glGetUniformLocation(Program, "direction");
|
||||
uniform_mask_radius = glGetUniformLocation(Program, "mask_radius");
|
||||
uniform_max_tex_height = glGetUniformLocation(Program, "max_tex_height");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_previous_viewproj = glGetUniformLocation(Program, "previous_viewproj");
|
||||
vao = createFullScreenVAO(Program);
|
||||
}
|
||||
|
||||
void MotionBlurShader::setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb)
|
||||
void MotionBlurShader::setUniforms(float boost_amount, const core::matrix4 &previousVP, const core::vector2df ¢er, float mask_radius, unsigned TU_cb, unsigned TU_dtex)
|
||||
{
|
||||
glUniformMatrix4fv(uniform_previous_viewproj, 1, GL_FALSE, previousVP.pointer());
|
||||
glUniform1f(uniform_boost_amount, boost_amount);
|
||||
glUniform2f(uniform_center, center.X, center.Y);
|
||||
glUniform2f(uniform_direction, direction.X, direction.Y);
|
||||
glUniform1f(uniform_mask_radius, mask_radius);
|
||||
glUniform1f(uniform_max_tex_height, max_tex_height);
|
||||
glUniform1i(uniform_color_buffer, TU_cb);
|
||||
glUniform1i(uniform_dtex, TU_dtex);
|
||||
}
|
||||
|
||||
GLuint GodFadeShader::Program;
|
||||
|
@ -375,10 +375,10 @@ class DisplaceShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint uniform_MVP, uniform_displacement_tex, uniform_mask_tex, uniform_color_tex, uniform_dir, uniform_dir2;
|
||||
static GLuint uniform_MVP, uniform_displacement_tex, uniform_mask_tex, uniform_color_tex, uniform_tex, uniform_dir, uniform_dir2;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex);
|
||||
static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex);
|
||||
};
|
||||
|
||||
class SkyboxShader
|
||||
@ -759,11 +759,11 @@ class MotionBlurShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint uniform_boost_amount, uniform_color_buffer, uniform_center, uniform_direction, uniform_mask_radius, uniform_max_tex_height;
|
||||
static GLuint uniform_boost_amount, uniform_color_buffer, uniform_dtex, uniform_previous_viewproj, uniform_center, uniform_mask_radius;
|
||||
static GLuint vao;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb);
|
||||
static void setUniforms(float boost_amount, const core::matrix4 &previousVP, const core::vector2df ¢er, float mask_radius, unsigned TU_cb, unsigned TU_dtex);
|
||||
};
|
||||
|
||||
class GodFadeShader
|
||||
|
@ -93,17 +93,19 @@ void STKAnimatedMesh::render()
|
||||
if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
|
||||
initvaostate(mesh, TranspMat);
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
|
||||
initvaostate(mesh, GeometricType, ShadedType);
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
|
||||
GeometricMesh[GeometricType].push_back(&mesh);
|
||||
ShadedMesh[ShadedType].push_back(&mesh);
|
||||
}
|
||||
std::pair<unsigned, unsigned> p = getVAOOffsetAndBase(mb);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
mesh.VAOType = mb->getVertexType();
|
||||
}
|
||||
}
|
||||
firstTime = false;
|
||||
@ -117,8 +119,9 @@ void STKAnimatedMesh::render()
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, GLmeshes[i].vertex_buffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, getVBO(mb->getVertexType()));
|
||||
glBufferSubData(GL_ARRAY_BUFFER, GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
if (mb)
|
||||
@ -133,7 +136,7 @@ void STKAnimatedMesh::render()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
|
||||
{
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
TransposeInverseModelView = computeTIMV(AbsoluteTransformation);
|
||||
@ -141,11 +144,18 @@ void STKAnimatedMesh::render()
|
||||
AbsoluteTransformation.getInverse(invmodel);
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT])
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD])
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT>::TIMVSet.push_back(invmodel);
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD])
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE])
|
||||
@ -164,11 +174,18 @@ void STKAnimatedMesh::render()
|
||||
AbsoluteTransformation.getInverse(invmodel);
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT])
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD])
|
||||
{
|
||||
GroupedSM<SM_DEFAULT>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT>::TIMVSet.push_back(invmodel);
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT])
|
||||
{
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE])
|
||||
@ -199,13 +216,6 @@ void STKAnimatedMesh::render()
|
||||
GroupedSM<SM_DETAILS>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_UNTEXTURED])
|
||||
{
|
||||
GroupedSM<SM_UNTEXTURED>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_UNTEXTURED>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_UNTEXTURED>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ void STKInstancedSceneNode::createGLMeshes()
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb));
|
||||
fillLocalBuffer(GLmeshes.back(), mb);
|
||||
}
|
||||
isMaterialInitialized = false;
|
||||
}
|
||||
@ -98,8 +99,8 @@ void STKInstancedSceneNode::setFirstTimeMaterial()
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
|
||||
initinstancedvaostate(mesh, GeometricType, ShadedType);
|
||||
GeometricMesh[GeometricType].push_back(&mesh);
|
||||
ShadedMesh[ShadedType].push_back(&mesh);
|
||||
@ -302,10 +303,10 @@ void STKInstancedSceneNode::render()
|
||||
ModelViewProjectionMatrix = irr_driver->getProjMatrix();
|
||||
ModelViewProjectionMatrix *= irr_driver->getViewMatrix();
|
||||
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty())
|
||||
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++)
|
||||
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9);
|
||||
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::InstancedObjectRefPass1Shader::Program);
|
||||
@ -322,10 +323,10 @@ void STKInstancedSceneNode::render()
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_LIT_PASS)
|
||||
{
|
||||
if (!ShadedMesh[SM_DEFAULT].empty())
|
||||
if (!ShadedMesh[SM_DEFAULT_STANDARD].empty())
|
||||
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 9);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT_STANDARD].size(); i++)
|
||||
drawSMDefault(*ShadedMesh[SM_DEFAULT_STANDARD][i], ModelViewProjectionMatrix, instance_pos.size() / 9);
|
||||
|
||||
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::InstancedObjectRefPass2Shader::Program);
|
||||
@ -341,10 +342,10 @@ void STKInstancedSceneNode::render()
|
||||
|
||||
if (irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty())
|
||||
glUseProgram(MeshShader::InstancedShadowShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawShadowDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++)
|
||||
drawShadowDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9);
|
||||
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::InstancedRefShadowShader::Program);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "graphics/camera.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType)
|
||||
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp)
|
||||
{
|
||||
if (MaterialType == irr_driver->getShader(ES_NORMAL_MAP))
|
||||
return FPSM_NORMAL_MAP;
|
||||
@ -17,11 +17,13 @@ GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE Materia
|
||||
return FPSM_ALPHA_REF_TEXTURE;
|
||||
else if (MaterialType == irr_driver->getShader(ES_GRASS) || MaterialType == irr_driver->getShader(ES_GRASS_REF))
|
||||
return FPSM_GRASS;
|
||||
else
|
||||
return FPSM_DEFAULT;
|
||||
else if (tp == video::EVT_2TCOORDS)
|
||||
return FPSM_DEFAULT_2TCOORD;
|
||||
assert(tp == video::EVT_STANDARD);
|
||||
return FPSM_DEFAULT_STANDARD;
|
||||
}
|
||||
|
||||
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures)
|
||||
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures, video::E_VERTEX_TYPE tp)
|
||||
{
|
||||
if (type == irr_driver->getShader(ES_SPHERE_MAP))
|
||||
return SM_SPHEREMAP;
|
||||
@ -35,12 +37,11 @@ ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::
|
||||
return SM_GRASS;
|
||||
else if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
|
||||
return SM_UNLIT;
|
||||
else if (textures[1] && type != irr_driver->getShader(ES_NORMAL_MAP))
|
||||
else if (tp == video::EVT_2TCOORDS)
|
||||
return SM_DETAILS;
|
||||
else if (!textures[0])
|
||||
return SM_UNTEXTURED;
|
||||
else
|
||||
return SM_DEFAULT;
|
||||
else if (tp == video::EVT_TANGENTS)
|
||||
return SM_DEFAULT_TANGENT;
|
||||
return SM_DEFAULT_STANDARD;
|
||||
}
|
||||
|
||||
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE type, f32 MaterialTypeParam)
|
||||
@ -51,7 +52,7 @@ TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE typ
|
||||
video::E_MODULATE_FUNC mod;
|
||||
u32 alpha;
|
||||
unpack_textureBlendFunc(srcFact, DstFact, mod, alpha, MaterialTypeParam);
|
||||
if (DstFact == video::EBF_ONE)
|
||||
if (DstFact == video::EBF_ONE || type == video::EMT_TRANSPARENT_ADD_COLOR)
|
||||
return TM_ADDITIVE;
|
||||
return TM_DEFAULT;
|
||||
}
|
||||
@ -139,46 +140,28 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
|
||||
GLMesh result = {};
|
||||
if (!mb)
|
||||
return result;
|
||||
glBindVertexArray(0);
|
||||
glGenBuffers(1, &(result.vertex_buffer));
|
||||
glGenBuffers(1, &(result.index_buffer));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.vertex_buffer);
|
||||
const void* vertices = mb->getVertices();
|
||||
const u32 vertexCount = mb->getVertexCount();
|
||||
const irr::video::E_VERTEX_TYPE vType = mb->getVertexType();
|
||||
result.Stride = getVertexPitchFromType(vType);
|
||||
const c8* vbuf = static_cast<const c8*>(vertices);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * result.Stride, vbuf, GL_STATIC_DRAW);
|
||||
assert(vertexCount);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.index_buffer);
|
||||
const void* indices = mb->getIndices();
|
||||
u32 indexCount = mb->getIndexCount();
|
||||
GLenum indexSize;
|
||||
result.IndexCount = mb->getIndexCount();
|
||||
switch (mb->getIndexType())
|
||||
{
|
||||
case irr::video::EIT_16BIT:
|
||||
{
|
||||
indexSize = sizeof(u16);
|
||||
result.IndexType = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
}
|
||||
case irr::video::EIT_32BIT:
|
||||
{
|
||||
indexSize = sizeof(u32);
|
||||
result.IndexType = GL_UNSIGNED_INT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(0 && "Wrong index size");
|
||||
}
|
||||
case irr::video::EIT_16BIT:
|
||||
{
|
||||
result.IndexType = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
}
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW);
|
||||
case irr::video::EIT_32BIT:
|
||||
{
|
||||
result.IndexType = GL_UNSIGNED_INT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(0 && "Wrong index size");
|
||||
}
|
||||
}
|
||||
result.VAOType = mb->getVertexType();
|
||||
result.Stride = getVertexPitchFromType(result.VAOType);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
result.IndexCount = mb->getIndexCount();
|
||||
switch (mb->getPrimitiveType())
|
||||
@ -212,6 +195,44 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
size_t getUnsignedSize(unsigned tp)
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return sizeof(u16);
|
||||
case GL_UNSIGNED_INT:
|
||||
return sizeof(u32);
|
||||
default:
|
||||
assert(0 && "Unsupported index type");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fillLocalBuffer(GLMesh &mesh, scene::IMeshBuffer* mb)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
glGenBuffers(1, &(mesh.vertex_buffer));
|
||||
glGenBuffers(1, &(mesh.index_buffer));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
|
||||
const void* vertices = mb->getVertices();
|
||||
const u32 vertexCount = mb->getVertexCount();
|
||||
|
||||
const c8* vbuf = static_cast<const c8*>(vertices);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf, GL_STATIC_DRAW);
|
||||
assert(vertexCount);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
|
||||
const void* indices = mb->getIndices();
|
||||
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.IndexCount * getUnsignedSize(mesh.IndexType), indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
core::matrix4 computeMVP(const core::matrix4 &ModelMatrix)
|
||||
{
|
||||
@ -234,7 +255,7 @@ core::vector3df getWind()
|
||||
{
|
||||
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
|
||||
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
|
||||
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
|
||||
float m_speed = gsp->getSpeed();
|
||||
|
||||
return m_speed * vector3df(1., 0., 0.) * cos(time);
|
||||
}
|
||||
@ -245,151 +266,93 @@ void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
assert(mesh.VAOType == video::EVT_STANDARD);
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::GrassPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, windDir, 0);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::SphereMapShader::setUniforms(ModelMatrix, InverseModelMatrix, irr_driver->getSceneManager()->getAmbientLight());
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
// Texlayout
|
||||
compressTexture(mesh.textures[1], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail0
|
||||
compressTexture(mesh.textures[2], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail1
|
||||
compressTexture(mesh.textures[3], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
compressTexture(mesh.textures[4], true);
|
||||
//Tex detail2
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail3
|
||||
compressTexture(mesh.textures[5], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
// Texlayout
|
||||
compressTexture(mesh.textures[1], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail0
|
||||
compressTexture(mesh.textures[2], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail1
|
||||
compressTexture(mesh.textures[3], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
compressTexture(mesh.textures[4], true);
|
||||
//Tex detail2
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
//Tex detail3
|
||||
compressTexture(mesh.textures[5], true);
|
||||
setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
MeshShader::ObjectRefPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
static video::ITexture *CausticTex = 0;
|
||||
|
||||
void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir)
|
||||
{
|
||||
@ -397,7 +360,10 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
assert(mesh.VAOType == video::EVT_STANDARD);
|
||||
|
||||
if (!mesh.textures[0])
|
||||
const_cast<GLMesh &>(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::GrassPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
@ -412,134 +378,7 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
|
||||
}
|
||||
|
||||
MeshShader::GrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
MeshShader::UntexturedObjectShader::setUniforms(ModelMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectRimLimitShader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
MeshShader::ObjectRimLimitShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
MeshShader::ObjectUnlitShader::setUniforms(ModelViewProjectionMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
compressTexture(mesh.textures[1], true);
|
||||
setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::DetailledObjectPass2Shader::setUniforms(ModelViewProjectionMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (irr_driver->getLightViz())
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
|
||||
MeshShader::ObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
|
||||
@ -608,10 +447,7 @@ void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatr
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::BubbleShader::setUniforms(ModelViewProjectionMatrix, 0, time, transparency);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
|
||||
@ -624,10 +460,7 @@ void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
MeshShader::RefShadowShader::setUniforms(ModelMatrix, 0);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElementsInstanced(ptype, count, itype, 0, 4);
|
||||
glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
|
||||
@ -638,10 +471,7 @@ void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
MeshShader::ShadowShader::setUniforms(ModelMatrix);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElementsInstanced(ptype, count, itype, 0, 4);
|
||||
glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *) mesh.vaoOffset, 4, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
bool isObject(video::E_MATERIAL_TYPE type)
|
||||
|
@ -12,7 +12,8 @@
|
||||
|
||||
enum GeometricMaterial
|
||||
{
|
||||
FPSM_DEFAULT,
|
||||
FPSM_DEFAULT_STANDARD,
|
||||
FPSM_DEFAULT_2TCOORD,
|
||||
FPSM_ALPHA_REF_TEXTURE,
|
||||
FPSM_NORMAL_MAP,
|
||||
FPSM_GRASS,
|
||||
@ -21,7 +22,8 @@ enum GeometricMaterial
|
||||
|
||||
enum ShadedMaterial
|
||||
{
|
||||
SM_DEFAULT,
|
||||
SM_DEFAULT_STANDARD,
|
||||
SM_DEFAULT_TANGENT,
|
||||
SM_ALPHA_REF_TEXTURE,
|
||||
SM_RIMLIT,
|
||||
SM_SPHEREMAP,
|
||||
@ -29,7 +31,6 @@ enum ShadedMaterial
|
||||
SM_GRASS,
|
||||
SM_UNLIT,
|
||||
SM_DETAILS,
|
||||
SM_UNTEXTURED,
|
||||
SM_COUNT
|
||||
};
|
||||
|
||||
@ -52,9 +53,13 @@ struct GLMesh {
|
||||
size_t IndexCount;
|
||||
size_t Stride;
|
||||
core::matrix4 TextureMatrix;
|
||||
size_t vaoBaseVertex;
|
||||
size_t vaoOffset;
|
||||
video::E_VERTEX_TYPE VAOType;
|
||||
};
|
||||
|
||||
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb);
|
||||
void fillLocalBuffer(GLMesh &, scene::IMeshBuffer* mb);
|
||||
video::E_VERTEX_TYPE getVTXTYPEFromStride(size_t stride);
|
||||
GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type);
|
||||
void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
|
||||
@ -90,7 +95,7 @@ std::vector<core::matrix4> GroupedFPSM<T>::TIMVSet;
|
||||
|
||||
|
||||
template<typename Shader, typename...uniforms>
|
||||
void draw(const GLMesh &mesh, GLuint vao, uniforms... Args)
|
||||
void draw(const GLMesh &mesh, uniforms... Args)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
@ -98,10 +103,7 @@ void draw(const GLMesh &mesh, GLuint vao, uniforms... Args)
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
Shader::setUniforms(Args...);
|
||||
|
||||
assert(vao);
|
||||
glBindVertexArray(vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir);
|
||||
@ -129,15 +131,8 @@ std::vector<core::matrix4> GroupedSM<T>::MVPSet;
|
||||
template<enum ShadedMaterial T>
|
||||
std::vector<core::matrix4> GroupedSM<T>::TIMVSet;
|
||||
|
||||
void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
|
||||
void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
|
||||
void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
|
||||
void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir);
|
||||
void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix);
|
||||
void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
|
||||
// Shadow pass
|
||||
void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix);
|
||||
@ -167,8 +162,8 @@ void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewPro
|
||||
void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
|
||||
void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
|
||||
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE);
|
||||
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures);
|
||||
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE, video::E_VERTEX_TYPE);
|
||||
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures, video::E_VERTEX_TYPE tp);
|
||||
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam);
|
||||
|
||||
#endif // STKMESH_H
|
||||
|
@ -16,13 +16,16 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
|
||||
const irr::core::vector3df& scale) :
|
||||
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
reload_each_frame = false;
|
||||
immediate_draw = false;
|
||||
update_each_frame = false;
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::setReloadEachFrame(bool val)
|
||||
{
|
||||
reload_each_frame = val;
|
||||
update_each_frame = val;
|
||||
if (val)
|
||||
immediate_draw = true;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::createGLMeshes()
|
||||
@ -60,16 +63,38 @@ void STKMeshSceneNode::setFirstTimeMaterial()
|
||||
if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
|
||||
initvaostate(mesh, TranspMat);
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
if (immediate_draw)
|
||||
{
|
||||
fillLocalBuffer(mesh, mb);
|
||||
initvaostate(mesh, TranspMat);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
else
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
|
||||
initvaostate(mesh, GeometricType, ShadedType);
|
||||
GeometricMesh[GeometricType].push_back(&mesh);
|
||||
ShadedMesh[ShadedType].push_back(&mesh);
|
||||
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
|
||||
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
|
||||
if (immediate_draw)
|
||||
{
|
||||
fillLocalBuffer(mesh, mb);
|
||||
initvaostate(mesh, GeometricType, ShadedType);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeometricMesh[GeometricType].push_back(&mesh);
|
||||
ShadedMesh[ShadedType].push_back(&mesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (!immediate_draw)
|
||||
{
|
||||
std::pair<unsigned, unsigned> p = getVAOOffsetAndBase(mb);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
mesh.VAOType = mb->getVertexType();
|
||||
}
|
||||
}
|
||||
isMaterialInitialized = true;
|
||||
@ -109,22 +134,26 @@ STKMeshSceneNode::~STKMeshSceneNode()
|
||||
void STKMeshSceneNode::drawGlow(const GLMesh &mesh)
|
||||
{
|
||||
ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
|
||||
assert(mesh.VAOType == video::EVT_STANDARD);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
MeshShader::ColorizeShader::setUniforms(AbsoluteTransformation, cb->getRed(), cb->getGreen(), cb->getBlue());
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
static video::ITexture *displaceTex = 0;
|
||||
|
||||
void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
{
|
||||
if (mesh.VAOType != video::EVT_2TCOORDS)
|
||||
{
|
||||
Log::error("Materials", "Displacement has wrong vertex type");
|
||||
return;
|
||||
}
|
||||
glBindVertexArray(getVAO(video::EVT_2TCOORDS));
|
||||
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
@ -137,9 +166,7 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
|
||||
glUseProgram(MeshShader::DisplaceMaskShader::Program);
|
||||
MeshShader::DisplaceMaskShader::setUniforms(AbsoluteTransformation);
|
||||
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
|
||||
// Render the effect
|
||||
if (!displaceTex)
|
||||
@ -148,57 +175,16 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
setTexture(0, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(1, irr_driver->getRenderTargetTexture(RTT_TMP1), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(2, irr_driver->getRenderTargetTexture(RTT_COLOR), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(3, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR, true);
|
||||
glUseProgram(MeshShader::DisplaceShader::Program);
|
||||
MeshShader::DisplaceShader::setUniforms(AbsoluteTransformation,
|
||||
core::vector2df(cb->getDirX(), cb->getDirY()),
|
||||
core::vector2df(cb->getDir2X(), cb->getDir2Y()),
|
||||
core::vector2df(float(UserConfigParams::m_width),
|
||||
float(UserConfigParams::m_height)),
|
||||
0, 1, 2);
|
||||
0, 1, 2, 3);
|
||||
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
assert(irr_driver->getPhase() == TRANSPARENT_PASS);
|
||||
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
|
||||
if (type == irr_driver->getShader(ES_BUBBLES))
|
||||
drawBubble(mesh, ModelViewProjectionMatrix);
|
||||
// else if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
// drawTransparentFogObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
else
|
||||
drawTransparentObject(mesh, ModelViewProjectionMatrix, mesh.TextureMatrix);
|
||||
return;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawSolidPass1(const GLMesh &mesh, GeometricMaterial type)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
windDir = getWind();
|
||||
switch (type)
|
||||
{
|
||||
case FPSM_GRASS:
|
||||
drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "wrong geometric material");
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawSolidPass2(const GLMesh &mesh, ShadedMaterial type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SM_GRASS:
|
||||
drawGrassPass2(mesh, ModelViewProjectionMatrix, windDir);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Wrong shaded material");
|
||||
break;
|
||||
}
|
||||
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::updatevbo()
|
||||
@ -220,7 +206,7 @@ void STKMeshSceneNode::updatevbo()
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
|
||||
const void* indices = mb->getIndices();
|
||||
mesh.IndexCount = mb->getIndexCount();
|
||||
GLenum indexSize;
|
||||
size_t indexSize = 0;
|
||||
switch (mb->getIndexType())
|
||||
{
|
||||
case irr::video::EIT_16BIT:
|
||||
@ -243,9 +229,6 @@ void STKMeshSceneNode::render()
|
||||
if (!Mesh || !driver)
|
||||
return;
|
||||
|
||||
if (reload_each_frame)
|
||||
updatevbo();
|
||||
|
||||
bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
@ -263,20 +246,52 @@ void STKMeshSceneNode::render()
|
||||
GLmeshes[i].TextureMatrix = getMaterial(i).getTextureMatrix(0);
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
|
||||
{
|
||||
if (reload_each_frame)
|
||||
glDisable(GL_CULL_FACE);
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
TransposeInverseModelView = computeTIMV(AbsoluteTransformation);
|
||||
core::matrix4 invmodel;
|
||||
AbsoluteTransformation.getInverse(invmodel);
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT])
|
||||
|
||||
if (immediate_draw)
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT>::TIMVSet.push_back(invmodel);
|
||||
glDisable(GL_CULL_FACE);
|
||||
if (update_each_frame)
|
||||
updatevbo();
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
// Only untextured
|
||||
for (unsigned i = 0; i < GLmeshes.size(); i++)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
MeshShader::ObjectPass1Shader::setUniforms(AbsoluteTransformation, invmodel, 0);
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD])
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD])
|
||||
{
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.push_back(mesh);
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE])
|
||||
@ -293,33 +308,57 @@ void STKMeshSceneNode::render()
|
||||
GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
|
||||
{
|
||||
if (!GeometricMesh[FPSM_GRASS].empty())
|
||||
glUseProgram(MeshShader::GrassPass1Shader::Program);
|
||||
for_in(mesh, GeometricMesh[FPSM_GRASS])
|
||||
drawSolidPass1(*mesh, FPSM_GRASS);
|
||||
}
|
||||
if (!GeometricMesh[FPSM_GRASS].empty())
|
||||
glUseProgram(MeshShader::GrassPass1Shader::Program);
|
||||
windDir = getWind();
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
for_in(mesh, GeometricMesh[FPSM_GRASS])
|
||||
drawGrassPass1(*mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
|
||||
|
||||
if (reload_each_frame)
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_LIT_PASS)
|
||||
{
|
||||
if (reload_each_frame)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
core::matrix4 invmodel;
|
||||
AbsoluteTransformation.getInverse(invmodel);
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT])
|
||||
if (immediate_draw)
|
||||
{
|
||||
GroupedSM<SM_DEFAULT>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT>::TIMVSet.push_back(invmodel);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glUseProgram(MeshShader::UntexturedObjectShader::Program);
|
||||
// Only untextured
|
||||
for (unsigned i = 0; i < GLmeshes.size(); i++)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
MeshShader::UntexturedObjectShader::setUniforms(AbsoluteTransformation);
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD])
|
||||
{
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT])
|
||||
{
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_DEFAULT_TANGENT>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE])
|
||||
@ -365,20 +404,12 @@ void STKMeshSceneNode::render()
|
||||
GroupedSM<SM_DETAILS>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
for_in(mesh, ShadedMesh[SM_UNTEXTURED])
|
||||
{
|
||||
GroupedSM<SM_UNTEXTURED>::MeshSet.push_back(mesh);
|
||||
GroupedSM<SM_UNTEXTURED>::MVPSet.push_back(AbsoluteTransformation);
|
||||
GroupedSM<SM_UNTEXTURED>::TIMVSet.push_back(invmodel);
|
||||
}
|
||||
|
||||
if (!ShadedMesh[SM_GRASS].empty())
|
||||
glUseProgram(MeshShader::GrassPass2Shader::Program);
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
for_in(mesh, ShadedMesh[SM_GRASS])
|
||||
drawSolidPass2(*mesh, SM_GRASS);
|
||||
drawGrassPass2(*mesh, ModelViewProjectionMatrix, windDir);
|
||||
|
||||
if (reload_each_frame)
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -390,6 +421,7 @@ void STKMeshSceneNode::render()
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
drawGlow(GLmeshes[i]);
|
||||
}
|
||||
}
|
||||
@ -398,6 +430,71 @@ void STKMeshSceneNode::render()
|
||||
{
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
|
||||
if (immediate_draw)
|
||||
{
|
||||
if (update_each_frame)
|
||||
updatevbo();
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
{
|
||||
glUseProgram(MeshShader::TransparentFogShader::Program);
|
||||
for (unsigned i = 0; i < GLmeshes.size(); i++)
|
||||
{
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
|
||||
// This function is only called once per frame - thus no need for setters.
|
||||
const float fogmax = track->getFogMax();
|
||||
const float startH = track->getFogStartHeight();
|
||||
const float endH = track->getFogEndHeight();
|
||||
const float start = track->getFogStart();
|
||||
const float end = track->getFogEnd();
|
||||
const video::SColor tmpcol = track->getFogColor();
|
||||
|
||||
core::vector3df col(tmpcol.getRed() / 255.0f,
|
||||
tmpcol.getGreen() / 255.0f,
|
||||
tmpcol.getBlue() / 255.0f);
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
MeshShader::TransparentFogShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
|
||||
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
for (unsigned i = 0; i < GLmeshes.size(); i++)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
compressTexture(mesh.textures[0], true);
|
||||
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::TransparentShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, 0);
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GLMesh* mesh;
|
||||
|
||||
for_in(mesh, TransparentMesh[TM_DEFAULT])
|
||||
@ -414,6 +511,7 @@ void STKMeshSceneNode::render()
|
||||
|
||||
if (!TransparentMesh[TM_BUBBLE].empty())
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
glBindVertexArray(getVAO(video::EVT_STANDARD));
|
||||
for_in(mesh, TransparentMesh[TM_BUBBLE])
|
||||
drawBubble(*mesh, ModelViewProjectionMatrix);
|
||||
return;
|
||||
|
@ -14,9 +14,6 @@ protected:
|
||||
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView;
|
||||
core::vector3df windDir;
|
||||
core::vector2df caustic_dir, caustic_dir2;
|
||||
void drawSolidPass1(const GLMesh &mesh, GeometricMaterial type);
|
||||
void drawSolidPass2(const GLMesh &mesh, ShadedMaterial type);
|
||||
void drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
|
||||
// Misc passes shaders (glow, displace...)
|
||||
void drawGlow(const GLMesh &mesh);
|
||||
@ -26,7 +23,8 @@ protected:
|
||||
void setFirstTimeMaterial();
|
||||
void updatevbo();
|
||||
bool isMaterialInitialized;
|
||||
bool reload_each_frame;
|
||||
bool immediate_draw;
|
||||
bool update_each_frame;
|
||||
public:
|
||||
void setReloadEachFrame(bool);
|
||||
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
|
@ -1944,7 +1944,7 @@ void Skin::process3DPane(IGUIElement *element, const core::recti &rect,
|
||||
if (fb != NULL && fb->getRTT().size() > 0)
|
||||
{
|
||||
draw2DImageFromRTT(fb->getRTT()[0], 512, 512,
|
||||
rect, core::rect<s32>(0, 0, 512, 512), NULL, true);
|
||||
rect, core::rect<s32>(0, 0, 512, 512), NULL, SColor(255, 255, 255, 255), true);
|
||||
}
|
||||
}
|
||||
else if (type == WTYPE_ICON_BUTTON || type == WTYPE_MODEL_VIEW)
|
||||
|
170
src/guiengine/widgets/kart_stats_widget.cpp
Normal file
170
src/guiengine/widgets/kart_stats_widget.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2013 Marianne Gagnon
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/widgets/kart_stats_widget.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include <string.h>
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIElement.h>
|
||||
#include <IGUIButton.h>
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::core;
|
||||
using namespace irr;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
bool multiplayer) : Widget(WTYPE_DIV)
|
||||
{
|
||||
m_player_id = player_id;
|
||||
|
||||
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight() );
|
||||
|
||||
const std::string default_kart = UserConfigParams::m_default_kart;
|
||||
const KartProperties* props =
|
||||
kart_properties_manager->getKart(default_kart);
|
||||
if(!props)
|
||||
{
|
||||
// If the default kart can't be found (e.g. previously a addon
|
||||
// kart was used, but the addon package was removed), use the
|
||||
// first kart as a default. This way we don't have to hardcode
|
||||
// any kart names.
|
||||
int id = kart_properties_manager->getKartByGroup(kart_group, 0);
|
||||
if (id == -1)
|
||||
{
|
||||
props = kart_properties_manager->getKartById(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
props = kart_properties_manager->getKartById(id);
|
||||
}
|
||||
|
||||
if(!props)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[KartSelectionScreen] WARNING: Can't find default "
|
||||
"kart '%s' nor any other kart.\n",
|
||||
default_kart.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const int offset = (m_h - (SKILL_COUNT*m_skill_bar_h)) / 2;
|
||||
for (int i = 0; i < SKILL_COUNT; ++i)
|
||||
{
|
||||
irr::core::recti skillArea(m_skill_bar_x, m_skill_bar_y + offset*i,
|
||||
m_skill_bar_x + m_skill_bar_w,
|
||||
m_skill_bar_y + m_skill_bar_h + offset*i);
|
||||
|
||||
SkillLevelWidget* skill_bar = NULL;
|
||||
|
||||
skill_bar = new SkillLevelWidget(skillArea, m_player_id, multiplayer);
|
||||
|
||||
m_skills.push_back(skill_bar);
|
||||
m_children.push_back(skill_bar);
|
||||
}
|
||||
|
||||
m_skills[SKILL_MASS]->setValue((int)(props->getMass()/5));
|
||||
m_skills[SKILL_MASS]->setLabel("WEIGHT");
|
||||
m_skills[SKILL_MASS]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_mass", m_player_id);
|
||||
|
||||
m_skills[SKILL_SPEED]->setValue((int)((props->getAbsMaxSpeed()-20)*20));
|
||||
m_skills[SKILL_SPEED]->setLabel("SPEED");
|
||||
m_skills[SKILL_SPEED]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_speed", m_player_id);
|
||||
|
||||
m_skills[SKILL_POWER]->setValue((int)(props->getAvgPower()));
|
||||
m_skills[SKILL_POWER]->setLabel("POWER");
|
||||
m_skills[SKILL_POWER]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_power", m_player_id);
|
||||
|
||||
} // KartStatsWidget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void KartStatsWidget::add()
|
||||
{
|
||||
for (int i = 0; i < SKILL_COUNT; ++i) {
|
||||
m_skills[i]->add();
|
||||
}
|
||||
}
|
||||
|
||||
void KartStatsWidget::move(int x, int y, int w, int h)
|
||||
{
|
||||
Widget::move(x,y,w,h);
|
||||
setSize(m_x, m_y, m_w, m_h);
|
||||
int offset = (m_h - (SKILL_COUNT*m_skill_bar_h)) / 2;
|
||||
for (int i = 0; i < SKILL_COUNT; ++i)
|
||||
{
|
||||
m_skills[i]->move(m_skill_bar_x,
|
||||
m_y + offset + m_skill_bar_h*i,
|
||||
m_skill_bar_w,
|
||||
m_skill_bar_h);
|
||||
}
|
||||
} //move
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// ---- set value for given type
|
||||
void KartStatsWidget::setValue(Stats type, int value)
|
||||
{
|
||||
m_skills[type]->setValue(value);
|
||||
} //setValue
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// ---- get value for given type
|
||||
int KartStatsWidget::getValue(Stats type)
|
||||
{
|
||||
return m_skills[type]->getValue();
|
||||
} // getVAlue
|
||||
|
||||
// ---- set size for widgets inside KartStatsWidget
|
||||
void KartStatsWidget::setSize(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
|
||||
// -- sizes
|
||||
m_skill_bar_w = w;
|
||||
m_skill_bar_h = GUIEngine::getTitleFontHeight();
|
||||
|
||||
// for shrinking effect
|
||||
if (h < 175)
|
||||
{
|
||||
const float factor = h / 175.0f;
|
||||
m_skill_bar_h = (int)(m_skill_bar_h*factor);
|
||||
}
|
||||
|
||||
m_skill_bar_x = x;
|
||||
m_skill_bar_y = y + h/2 - m_skill_bar_h/2;
|
||||
} // setSize
|
||||
|
||||
// -----------------------------------------------------------------------------
|
104
src/guiengine/widgets/kart_stats_widget.hpp
Normal file
104
src/guiengine/widgets/kart_stats_widget.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2013 Marianne Gagnon
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
|
||||
#ifndef HEADER_KART_STATS_HPP
|
||||
#define HEADER_KART_STATS_HPP
|
||||
|
||||
#include <irrString.h>
|
||||
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/progress_bar_widget.hpp"
|
||||
#include "guiengine/widgets/skill_level_widget.hpp"
|
||||
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
/**
|
||||
* \brief A progress bar widget.
|
||||
* \ingroup widgetsgroup
|
||||
*/
|
||||
|
||||
|
||||
class KartStatsWidget : public Widget
|
||||
{
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
virtual int getWidthNeededAroundLabel() const { return 35; }
|
||||
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
virtual int getHeightNeededAroundLabel() const { return 4; }
|
||||
|
||||
/** widget coordinates */
|
||||
int m_skill_bar_x, m_skill_bar_y, m_skill_bar_h, m_skill_bar_w;
|
||||
|
||||
int m_player_id;
|
||||
|
||||
std::vector<SkillLevelWidget*> m_skills;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum Stats
|
||||
{
|
||||
SKILL_MASS,
|
||||
SKILL_SPEED,
|
||||
SKILL_POWER,
|
||||
SKILL_COUNT
|
||||
};
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
KartStatsWidget(core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
bool multiplayer);
|
||||
virtual ~KartStatsWidget() {};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add the widgets to the current screen */
|
||||
virtual void add();
|
||||
|
||||
/** Move the widget and its children */
|
||||
virtual void move(const int x, const int y, const int w, const int h);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Updates the animation (moving/shrinking/etc.) */
|
||||
void onUpdate(float delta);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Event callback */
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Sets the size of the widget as a whole, and placed children widgets
|
||||
* inside itself */
|
||||
void setSize(const int x, const int y, const int w, const int h);
|
||||
|
||||
/** Change the value of the widget, it must be a percent. */
|
||||
void setValue(Stats type, int value);
|
||||
|
||||
/** Get the current values of the widget. */
|
||||
int getValue(Stats type);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -33,7 +33,7 @@ using namespace irr::core;
|
||||
using namespace irr::gui;
|
||||
|
||||
ModelViewWidget::ModelViewWidget() :
|
||||
IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false, false)
|
||||
IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false, false)
|
||||
{
|
||||
m_frame_buffer = NULL;
|
||||
m_rtt_main_node = NULL;
|
||||
@ -42,17 +42,17 @@ ModelViewWidget::ModelViewWidget() :
|
||||
m_type = WTYPE_MODEL_VIEW;
|
||||
m_rtt_provider = NULL;
|
||||
m_rotation_mode = ROTATE_OFF;
|
||||
|
||||
|
||||
// so that the base class doesn't complain there is no icon defined
|
||||
m_properties[PROP_ICON]="gui/main_help.png";
|
||||
|
||||
|
||||
m_rtt_unsupported = false;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
ModelViewWidget::~ModelViewWidget()
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
|
||||
|
||||
delete m_rtt_provider;
|
||||
m_rtt_provider = NULL;
|
||||
}
|
||||
@ -61,18 +61,18 @@ void ModelViewWidget::add()
|
||||
{
|
||||
// so that the base class doesn't complain there is no icon defined
|
||||
m_properties[PROP_ICON]="gui/main_help.png";
|
||||
|
||||
|
||||
IconButtonWidget::add();
|
||||
|
||||
|
||||
/*
|
||||
FIXME: remove this unclean thing, I think irrlicht provides this feature:
|
||||
virtual void IGUIElement::OnPostRender (u32 timeMs)
|
||||
\brief animate the element and its children.
|
||||
virtual void IGUIElement::OnPostRender (u32 timeMs)
|
||||
\brief animate the element and its children.
|
||||
*/
|
||||
GUIEngine::needsUpdate.push_back(this);
|
||||
|
||||
|
||||
angle = 0;
|
||||
|
||||
|
||||
} // add
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -82,11 +82,11 @@ void ModelViewWidget::clearModels()
|
||||
m_model_location.clear();
|
||||
m_model_scale.clear();
|
||||
m_model_frames.clear();
|
||||
|
||||
|
||||
if (m_rtt_main_node != NULL) m_rtt_main_node->remove();
|
||||
if (m_light != NULL) m_light->remove();
|
||||
if (m_camera != NULL) m_camera->remove();
|
||||
|
||||
|
||||
m_rtt_main_node = NULL;
|
||||
m_camera = NULL;
|
||||
m_light = NULL;
|
||||
@ -98,7 +98,7 @@ void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
|
||||
const Vec3& scale, const int frame)
|
||||
{
|
||||
if(!mesh) return;
|
||||
|
||||
|
||||
m_models.push_back(mesh);
|
||||
m_model_location.push_back(location);
|
||||
m_model_scale.push_back(scale);
|
||||
@ -109,7 +109,7 @@ void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
|
||||
void ModelViewWidget::update(float delta)
|
||||
{
|
||||
if (m_rtt_unsupported) return;
|
||||
|
||||
|
||||
if (m_rotation_mode == ROTATE_CONTINUOUSLY)
|
||||
{
|
||||
angle += delta*m_rotation_speed;
|
||||
@ -121,10 +121,10 @@ void ModelViewWidget::update(float delta)
|
||||
// (taking wrap-arounds into account)
|
||||
const int angle_distance_from_end = (int)(360 - angle);
|
||||
const int target_distance_from_end = (int)(360 - angle);
|
||||
|
||||
|
||||
int distance_with_positive_rotation;
|
||||
int distance_with_negative_rotation;
|
||||
|
||||
|
||||
if (angle < m_rotation_target)
|
||||
{
|
||||
distance_with_positive_rotation = (int)(m_rotation_target - angle);
|
||||
@ -135,10 +135,10 @@ void ModelViewWidget::update(float delta)
|
||||
distance_with_positive_rotation = (int)(angle_distance_from_end + m_rotation_target);
|
||||
distance_with_negative_rotation = (int)(angle - m_rotation_target);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "distance_with_positive_rotation=" << distance_with_positive_rotation <<
|
||||
//" distance_with_negative_rotation=" << distance_with_negative_rotation << " angle="<< angle <<std::endl;
|
||||
|
||||
|
||||
if (distance_with_positive_rotation < distance_with_negative_rotation)
|
||||
{
|
||||
angle += m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
@ -149,65 +149,53 @@ void ModelViewWidget::update(float delta)
|
||||
}
|
||||
if (angle > 360) angle -= 360;
|
||||
if (angle < 0) angle += 360;
|
||||
|
||||
|
||||
// stop rotating when target reached
|
||||
if (fabsf(angle - m_rotation_target) < 2.0f) m_rotation_mode = ROTATE_OFF;
|
||||
}
|
||||
|
||||
|
||||
if (!irr_driver->isGLSL())
|
||||
return;
|
||||
|
||||
|
||||
if (m_rtt_provider == NULL)
|
||||
{
|
||||
std::string name = "model view ";
|
||||
name += m_properties[PROP_ID].c_str();
|
||||
|
||||
|
||||
m_rtt_provider = new RTT(512, 512);
|
||||
}
|
||||
|
||||
|
||||
if (m_rtt_main_node == NULL)
|
||||
{
|
||||
setupRTTScene(m_models, m_model_location, m_model_scale, m_model_frames);
|
||||
}
|
||||
|
||||
|
||||
m_rtt_main_node->setRotation(core::vector3df(0.0f, angle, 0.0f));
|
||||
|
||||
m_rtt_main_node->setVisible(true);
|
||||
irr_driver->setRTT(m_rtt_provider);
|
||||
|
||||
irr_driver->getSceneManager()->setActiveCamera(m_camera);
|
||||
m_frame_buffer = m_rtt_provider->render(m_camera, GUIEngine::getLatestDt());
|
||||
|
||||
std::vector<IrrDriver::GlowData> glows;
|
||||
irr_driver->computeCameraMatrix(m_camera, 512, 512);
|
||||
unsigned plc = irr_driver->UpdateLightsInfo(m_camera, GUIEngine::getLatestDt());
|
||||
irr_driver->renderScene(m_camera, plc, glows, GUIEngine::getLatestDt(), false, true);
|
||||
m_frame_buffer = irr_driver->getPostProcessing()->render(m_camera);
|
||||
glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height);
|
||||
|
||||
irr_driver->setRTT(NULL);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
irr_driver->getSceneManager()->setActiveCamera(NULL);
|
||||
m_rtt_main_node->setVisible(false);
|
||||
}
|
||||
|
||||
void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
|
||||
AlignedArray<Vec3>& mesh_location,
|
||||
AlignedArray<Vec3>& mesh_scale,
|
||||
const std::vector<int>& model_frames)
|
||||
AlignedArray<Vec3>& mesh_location,
|
||||
AlignedArray<Vec3>& mesh_scale,
|
||||
const std::vector<int>& model_frames)
|
||||
{
|
||||
irr_driver->suppressSkyBox();
|
||||
|
||||
|
||||
if (m_rtt_main_node != NULL) m_rtt_main_node->remove();
|
||||
if (m_light != NULL) m_light->remove();
|
||||
if (m_camera != NULL) m_camera->remove();
|
||||
|
||||
|
||||
m_rtt_main_node = NULL;
|
||||
m_camera = NULL;
|
||||
m_light = NULL;
|
||||
|
||||
|
||||
irr_driver->clearLights();
|
||||
|
||||
|
||||
if (model_frames[0] == -1)
|
||||
{
|
||||
scene::ISceneNode* node = irr_driver->addMesh(mesh.get(0), NULL);
|
||||
@ -219,27 +207,27 @@ void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
|
||||
else
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode* node =
|
||||
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(0), NULL);
|
||||
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(0), NULL);
|
||||
node->setPosition(mesh_location[0].toIrrVector());
|
||||
node->setFrameLoop(model_frames[0], model_frames[0]);
|
||||
node->setAnimationSpeed(0);
|
||||
node->setScale(mesh_scale[0].toIrrVector());
|
||||
node->setMaterialFlag(video::EMF_FOG_ENABLE, false);
|
||||
|
||||
|
||||
m_rtt_main_node = node;
|
||||
}
|
||||
|
||||
|
||||
assert(m_rtt_main_node != NULL);
|
||||
assert(mesh.size() == mesh_location.size());
|
||||
assert(mesh.size() == model_frames.size());
|
||||
|
||||
|
||||
const int mesh_amount = mesh.size();
|
||||
for (int n = 1; n<mesh_amount; n++)
|
||||
{
|
||||
if (model_frames[n] == -1)
|
||||
{
|
||||
scene::ISceneNode* node =
|
||||
irr_driver->addMesh(mesh.get(n), m_rtt_main_node);
|
||||
irr_driver->addMesh(mesh.get(n), m_rtt_main_node);
|
||||
node->setPosition(mesh_location[n].toIrrVector());
|
||||
node->updateAbsolutePosition();
|
||||
node->setScale(mesh_scale[n].toIrrVector());
|
||||
@ -247,8 +235,8 @@ void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
|
||||
else
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode* node =
|
||||
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(n),
|
||||
m_rtt_main_node);
|
||||
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(n),
|
||||
m_rtt_main_node);
|
||||
node->setPosition(mesh_location[n].toIrrVector());
|
||||
node->setFrameLoop(model_frames[n], model_frames[n]);
|
||||
node->setAnimationSpeed(0);
|
||||
@ -257,37 +245,34 @@ void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
|
||||
//std::cout << "(((( set frame " << model_frames[n] << " ))))\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 35, 35, 35));
|
||||
|
||||
|
||||
const core::vector3df &spot_pos = core::vector3df(0, 30, 40);
|
||||
m_light = irr_driver->addLight(spot_pos, 0.3f /* energy */, 10 /* distance */, 1.0f /* r */, 1.0f /* g */, 1.0f /* g*/, true, NULL);
|
||||
|
||||
|
||||
m_rtt_main_node->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);
|
||||
m_rtt_main_node->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||
|
||||
|
||||
const int materials = m_rtt_main_node->getMaterialCount();
|
||||
for (int n = 0; n<materials; n++)
|
||||
{
|
||||
m_rtt_main_node->getMaterial(n).setFlag(video::EMF_LIGHTING, true);
|
||||
|
||||
|
||||
// set size of specular highlights
|
||||
m_rtt_main_node->getMaterial(n).Shininess = 100.0f;
|
||||
m_rtt_main_node->getMaterial(n).SpecularColor.set(255, 50, 50, 50);
|
||||
m_rtt_main_node->getMaterial(n).DiffuseColor.set(255, 150, 150, 150);
|
||||
|
||||
|
||||
m_rtt_main_node->getMaterial(n).setFlag(video::EMF_GOURAUD_SHADING,
|
||||
true);
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
m_camera = irr_driver->getSceneManager()->addCameraSceneNode();
|
||||
m_camera->setAspectRatio(1.0f);
|
||||
|
||||
|
||||
m_camera->setPosition(core::vector3df(0.0, 20.0f, 70.0f));
|
||||
if (irr_driver->isGLSL())
|
||||
m_camera->setUpVector(core::vector3df(0.0, 1.0, 0.0));
|
||||
else
|
||||
m_camera->setUpVector(core::vector3df(0.0, 1.0, 0.0));
|
||||
m_camera->setUpVector(core::vector3df(0.0, 1.0, 0.0));
|
||||
m_camera->setTarget(core::vector3df(0, 10, 0.0f));
|
||||
m_camera->setFOV(DEGREE_TO_RAD*50.0f);
|
||||
m_camera->updateAbsolutePosition();
|
||||
|
@ -30,9 +30,10 @@ using namespace irr;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ProgressBarWidget::ProgressBarWidget() : Widget(WTYPE_PROGRESS)
|
||||
ProgressBarWidget::ProgressBarWidget(bool show_label) : Widget(WTYPE_PROGRESS)
|
||||
{
|
||||
m_value = 0;
|
||||
m_show_label = show_label;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -52,7 +53,10 @@ void ProgressBarWidget::add()
|
||||
void ProgressBarWidget::setValue(int value)
|
||||
{
|
||||
m_value = value;
|
||||
setLabel(std::string(StringUtils::toString(value) + "%").c_str());
|
||||
if (m_show_label)
|
||||
{
|
||||
setLabel(std::string(StringUtils::toString(value) + "%").c_str());
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
@ -45,12 +45,12 @@ namespace GUIEngine
|
||||
/** Change the label on the widget */
|
||||
void setLabel(const irr::core::stringw label);
|
||||
int m_value;
|
||||
bool m_show_label;
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
ProgressBarWidget();
|
||||
ProgressBarWidget(bool show_label = true);
|
||||
virtual ~ProgressBarWidget() {}
|
||||
|
||||
/** Change the value of the widget, it must be a percent. */
|
||||
|
152
src/guiengine/widgets/skill_level_widget.cpp
Normal file
152
src/guiengine/widgets/skill_level_widget.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2013 Marianne Gagnon
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/widgets/skill_level_widget.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include <string.h>
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIElement.h>
|
||||
#include <IGUIButton.h>
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::core;
|
||||
using namespace irr;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id,
|
||||
bool multiplayer, const int value,
|
||||
const stringw& label) : Widget(WTYPE_DIV)
|
||||
{
|
||||
m_player_id = player_id;
|
||||
|
||||
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight() );
|
||||
|
||||
// ---- Mass skill level widget
|
||||
m_bar = NULL;
|
||||
|
||||
m_bar = new ProgressBarWidget(false);
|
||||
m_bar->setValue(value);
|
||||
|
||||
m_bar->m_x = m_bar_x;
|
||||
m_bar->m_y = m_bar_y;
|
||||
m_bar->m_w = m_bar_w;
|
||||
m_bar->m_h = m_bar_h;
|
||||
m_bar->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_bar", m_player_id);
|
||||
|
||||
m_label = NULL;
|
||||
|
||||
m_label = new LabelWidget(!multiplayer, true);
|
||||
m_label->setText(label,false);
|
||||
|
||||
m_label->m_x = m_label_x;
|
||||
m_label->m_y = m_label_y;
|
||||
m_label->m_w = m_label_w;
|
||||
m_label->m_h = m_label_h;
|
||||
m_label->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_label", m_player_id);
|
||||
|
||||
m_children.push_back(m_bar);
|
||||
m_children.push_back(m_label);
|
||||
} // KartStatsWidget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SkillLevelWidget::add()
|
||||
{
|
||||
m_bar->add();
|
||||
m_label->add();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void SkillLevelWidget::move(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
Widget::move(x,y,w,h);
|
||||
setSize(m_x, m_y, m_w, m_h);
|
||||
|
||||
if (m_bar != NULL)
|
||||
{
|
||||
m_bar->move(m_bar_x,
|
||||
m_bar_y,
|
||||
m_bar_w,
|
||||
m_bar_h );
|
||||
}
|
||||
if (m_label != NULL)
|
||||
{
|
||||
m_label->move(m_label_x,
|
||||
m_label_y,
|
||||
m_label_w,
|
||||
m_label_h);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void SkillLevelWidget::setSize(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
|
||||
// -- sizes
|
||||
m_bar_w = 3*(w/2)/4;
|
||||
m_bar_h = h;
|
||||
m_label_w = w/2;
|
||||
m_label_h = h;
|
||||
|
||||
// for shrinking effect
|
||||
if (h < 175)
|
||||
{
|
||||
const float factor = h / 175.0f;
|
||||
m_bar_h = (int)(m_bar_h*factor);
|
||||
m_label_h = (int)(m_label_h*factor);
|
||||
}
|
||||
|
||||
m_bar_x = x + w/2;
|
||||
m_bar_y = y + m_h/2 - m_bar_h/2;
|
||||
|
||||
m_label_x = x;
|
||||
m_label_y = y + m_h/2 - m_label_h/2;
|
||||
} // setSize
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SkillLevelWidget::setValue(const int value)
|
||||
{
|
||||
m_bar->setValue(value);
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SkillLevelWidget::setLabel(const irr::core::stringw& label)
|
||||
{
|
||||
m_label->setText(label, false);
|
||||
}
|
||||
|
102
src/guiengine/widgets/skill_level_widget.hpp
Normal file
102
src/guiengine/widgets/skill_level_widget.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2013 Marianne Gagnon
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
|
||||
#ifndef HEADER_SKILL_LEVEL_HPP
|
||||
#define HEADER_SKILL_LEVEL_HPP
|
||||
|
||||
#include <irrString.h>
|
||||
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/progress_bar_widget.hpp"
|
||||
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
/**
|
||||
* \brief A skill level widget.
|
||||
* \ingroup widgetsgroup
|
||||
*/
|
||||
|
||||
class SkillLevelWidget : public Widget
|
||||
{
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
virtual int getWidthNeededAroundLabel() const { return 35; }
|
||||
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
virtual int getHeightNeededAroundLabel() const { return 4; }
|
||||
|
||||
/** widget coordinates */
|
||||
int m_bar_x, m_bar_y, m_bar_h, m_bar_w;
|
||||
int m_label_x, m_label_y, m_label_h, m_label_w;
|
||||
|
||||
std::string m_label_name;
|
||||
|
||||
int m_player_id;
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
LabelWidget* m_label;
|
||||
ProgressBarWidget* m_bar;
|
||||
|
||||
SkillLevelWidget(core::recti area, const int player_id, bool multiplayer,
|
||||
const int value = 0, const irr::core::stringw& label = "default");
|
||||
|
||||
virtual ~SkillLevelWidget() {};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add the widgets to the current screen */
|
||||
virtual void add();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
virtual void move(const int x, const int y, const int w, const int h);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Sets the size of the widget as a whole, and placed children widgets
|
||||
* inside itself */
|
||||
void setSize(const int x, const int y, const int w, const int h);
|
||||
|
||||
/** Change the value of the widget, it must be a percent. */
|
||||
void setValue(const int value);
|
||||
|
||||
/** Get the current values of the widget. */
|
||||
int getValue() {return m_bar->getValue(); };
|
||||
|
||||
/** Change the label of the widget */
|
||||
void setLabel(const irr::core::stringw& label);
|
||||
|
||||
/** Get the current label of the widget. */
|
||||
const irr::core::stringw& getLabel()
|
||||
{
|
||||
return m_label->getText();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -160,7 +160,7 @@ void SpinnerWidget::add()
|
||||
{
|
||||
label->setText(m_labels[m_value].c_str() );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ void SpinnerWidget::add()
|
||||
m_children[2].m_id = m_children[2].m_element->getID();
|
||||
|
||||
// refresh display
|
||||
|
||||
|
||||
|
||||
setValue(m_value);
|
||||
}
|
||||
@ -333,7 +333,7 @@ void SpinnerWidget::setValue(const int new_value)
|
||||
assert(new_value >= 0);
|
||||
assert(new_value < (int)m_labels.size());
|
||||
|
||||
m_children[1].m_element->setText(m_labels[new_value].c_str() );
|
||||
m_children[1].m_element->setText(m_labels[new_value].c_str());
|
||||
}
|
||||
else if (m_text.size() > 0 && m_children.size() > 0)
|
||||
{
|
||||
|
@ -74,15 +74,16 @@ bool DeviceManager::initialize()
|
||||
}
|
||||
|
||||
const int keyboard_amount = m_keyboard_configs.size();
|
||||
for (int n=0; n<keyboard_amount; n++)
|
||||
for (int n = 0; n < keyboard_amount; n++)
|
||||
{
|
||||
m_keyboards.push_back(new KeyboardDevice(m_keyboard_configs.get(n)));
|
||||
}
|
||||
|
||||
if(UserConfigParams::logMisc())
|
||||
Log::info("Device manager","Initializing gamepad support.");
|
||||
Log::info("Device manager","Initializing gamepad support.");
|
||||
|
||||
irr_driver->getDevice()->activateJoysticks(m_irrlicht_gamepads);
|
||||
|
||||
int num_gamepads = m_irrlicht_gamepads.size();
|
||||
if(UserConfigParams::logMisc())
|
||||
{
|
||||
@ -90,8 +91,6 @@ bool DeviceManager::initialize()
|
||||
num_gamepads);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create GamePadDevice for each physical gamepad and find a GamepadConfig to match
|
||||
for (int id = 0; id < num_gamepads; id++)
|
||||
{
|
||||
@ -112,6 +111,7 @@ bool DeviceManager::initialize()
|
||||
{
|
||||
Log::info("Device manager","#%d: %s detected...", id, name.c_str());
|
||||
}
|
||||
|
||||
// Returns true if new configuration was created
|
||||
if (getConfigForGamepad(id, name, &gamepadConfig) == true)
|
||||
{
|
||||
@ -135,6 +135,7 @@ bool DeviceManager::initialize()
|
||||
} // end for
|
||||
|
||||
if (created) serialize();
|
||||
|
||||
return created;
|
||||
} // initialize
|
||||
|
||||
|
@ -28,7 +28,6 @@ class AbstractKartAnimation;
|
||||
class Attachment;
|
||||
class btKart;
|
||||
class btQuaternion;
|
||||
class btUprightConstraint;
|
||||
class Controller;
|
||||
class Item;
|
||||
class KartModel;
|
||||
@ -342,9 +341,6 @@ public:
|
||||
/** Returns the bullet vehicle which represents this kart. */
|
||||
virtual btKart* getVehicle() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the upright constraint for this kart. */
|
||||
virtual btUprightConstraint* getUprightConstraint() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual btQuaternion getVisualRotation() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the kart is 'resting', i.e. (nearly) not moving. */
|
||||
|
@ -58,7 +58,6 @@
|
||||
#include "network/network_manager.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/btKartRaycast.hpp"
|
||||
#include "physics/btUprightConstraint.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
@ -269,7 +268,6 @@ Kart::~Kart()
|
||||
World::getWorld()->getPhysics()->removeKart(this);
|
||||
delete m_vehicle;
|
||||
delete m_vehicle_raycaster;
|
||||
delete m_uprightConstraint;
|
||||
}
|
||||
|
||||
for(int i=0; i<m_kart_chassis.getNumChildShapes(); i++)
|
||||
@ -682,13 +680,6 @@ void Kart::createPhysics()
|
||||
// Obviously these allocs have to be properly managed/freed
|
||||
btTransform t;
|
||||
t.setIdentity();
|
||||
m_uprightConstraint=new btUprightConstraint(this, t);
|
||||
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
|
||||
m_uprightConstraint->setBounce(0.0f);
|
||||
m_uprightConstraint->setMaxLimitForce(m_kart_properties->getUprightMaxForce());
|
||||
m_uprightConstraint->setErp(1.0f);
|
||||
m_uprightConstraint->setLimitSoftness(1.0f);
|
||||
m_uprightConstraint->setDamping(0.0f);
|
||||
World::getWorld()->getPhysics()->addKart(this);
|
||||
|
||||
} // createPhysics
|
||||
@ -699,8 +690,9 @@ void Kart::flyUp()
|
||||
{
|
||||
m_flying = true;
|
||||
Moveable::flyUp();
|
||||
}
|
||||
} // flyUp
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Kart::flyDown()
|
||||
{
|
||||
if (isNearGround())
|
||||
@ -712,7 +704,7 @@ void Kart::flyDown()
|
||||
{
|
||||
Moveable::flyDown();
|
||||
}
|
||||
} // flyUp
|
||||
} // flyDown
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Starts the engine sound effect. Called once the track intro phase is over.
|
||||
@ -957,8 +949,7 @@ bool Kart::isOnGround() const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** The kart is near the ground, but not necessarily on it (small jumps). This
|
||||
* is used to determine when to switch off the upright constraint, so that
|
||||
* explosions can be more violent, while still
|
||||
* is used to determine when to stop flying.
|
||||
*/
|
||||
bool Kart::isNearGround() const
|
||||
{
|
||||
@ -1102,21 +1093,6 @@ void Kart::update(float dt)
|
||||
|
||||
m_slipstream->update(dt);
|
||||
|
||||
if (!m_flying)
|
||||
{
|
||||
// When really on air, free fly, when near ground, try to glide /
|
||||
// adjust for landing. If zipped, be stable, so ramp+zipper can
|
||||
// allow nice jumps without scripting the fly
|
||||
// Also disable he upright constraint when gravity is changed by
|
||||
// the terrain
|
||||
if ((!isNearGround() &&
|
||||
m_max_speed->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER) <= 0.0f) ||
|
||||
(getMaterial() && getMaterial()->hasGravity()))
|
||||
m_uprightConstraint->setLimit(M_PI);
|
||||
else
|
||||
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
|
||||
}
|
||||
|
||||
// TODO: hiker said this probably will be moved to btKart or so when updating bullet engine.
|
||||
// Neutralize any yaw change if the kart leaves the ground, so the kart falls more or less
|
||||
// straight after jumping, but still allowing some "boat shake" (roll and pitch).
|
||||
@ -1258,9 +1234,7 @@ void Kart::update(float dt)
|
||||
if (material->hasGravity() || 1)
|
||||
{
|
||||
Vec3 normal = m_terrain_info->getNormal();
|
||||
|
||||
gravity = normal*-g;
|
||||
//std::cout << gravity.x() << " "<< gravity.y() <<" " << gravity.z() << std::endl;
|
||||
gravity = normal * -g;
|
||||
}
|
||||
body->setGravity(gravity);
|
||||
} // if !flying
|
||||
@ -2053,6 +2027,30 @@ void Kart::updatePhysics(float dt)
|
||||
m_max_speed->setMinSpeed(min_speed);
|
||||
m_max_speed->update(dt);
|
||||
|
||||
// If the kart is flying, keep its up-axis aligned to gravity (which in
|
||||
// turn typically means the kart is parallel to the ground). This avoids
|
||||
// that the kart rotates in mid-air and lands on its side.
|
||||
if(m_vehicle->getNumWheelsOnGround()==0)
|
||||
{
|
||||
btVector3 kart_up = getTrans().getBasis().getColumn(1); // up vector
|
||||
btVector3 terrain_up = m_body->getGravity();
|
||||
float g = World::getWorld()->getTrack()->getGravity();
|
||||
// Normalize the gravity, g is the length of the vector
|
||||
btVector3 new_up = 0.9f * kart_up + 0.1f * terrain_up/-g;
|
||||
// Get the rotation (hpr) based on current heading.
|
||||
Vec3 rotation(getHeading(), new_up);
|
||||
btMatrix3x3 m;
|
||||
m.setEulerZYX(rotation.getX(), rotation.getY(), rotation.getZ());
|
||||
// We can't use getXYZ() for the position here, since the position is
|
||||
// based on interpolation, while the actual center-of-mass-transform
|
||||
// is based on the actual value every 1/60 of a second (using getXYZ()
|
||||
// would result in the kart being pushed ahead a bit, making it jump
|
||||
// much further, depending on fps)
|
||||
btTransform new_trans(m, m_body->getCenterOfMassTransform().getOrigin());
|
||||
//setTrans(new_trans);
|
||||
m_body->setCenterOfMassTransform(new_trans);
|
||||
}
|
||||
|
||||
// To avoid tunneling (which can happen on long falls), clamp the
|
||||
// velocity in Y direction. Tunneling can happen if the Y velocity
|
||||
// is larger than the maximum suspension travel (per frame), since then
|
||||
@ -2060,6 +2058,7 @@ void Kart::updatePhysics(float dt)
|
||||
// not sure if this is enough in all cases!). So the speed is limited
|
||||
// to suspensionTravel / dt with dt = 1/60 (since this is the dt
|
||||
// bullet is using).
|
||||
|
||||
// Only apply if near ground instead of purely based on speed avoiding
|
||||
// the "parachute on top" look.
|
||||
const Vec3 &v = m_body->getLinearVelocity();
|
||||
@ -2068,7 +2067,7 @@ void Kart::updatePhysics(float dt)
|
||||
Vec3 v_clamped = v;
|
||||
// clamp the speed to 99% of the maxium falling speed.
|
||||
v_clamped.setY(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
|
||||
m_body->setLinearVelocity(v_clamped);
|
||||
//m_body->setLinearVelocity(v_clamped);
|
||||
}
|
||||
|
||||
//at low velocity, forces on kart push it back and forth so we ignore this
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
class btKart;
|
||||
class btUprightConstraint;
|
||||
|
||||
class Attachment;
|
||||
class Controller;
|
||||
@ -146,7 +145,6 @@ private:
|
||||
btCompoundShape m_kart_chassis;
|
||||
btVehicleRaycaster *m_vehicle_raycaster;
|
||||
btKart *m_vehicle;
|
||||
btUprightConstraint *m_uprightConstraint;
|
||||
|
||||
/** The amount of energy collected by hitting coins. Note that it
|
||||
* must be float, since dt is subtraced in each timestep. */
|
||||
@ -342,11 +340,7 @@ public:
|
||||
virtual Skidding *getSkidding() { return m_skidding; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the bullet vehicle which represents this kart. */
|
||||
virtual btKart *getVehicle () const {return m_vehicle; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the upright constraint for this kart. */
|
||||
virtual btUprightConstraint *getUprightConstraint() const
|
||||
{return m_uprightConstraint;}
|
||||
virtual btKart *getVehicle() const {return m_vehicle; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the speed of the kart in meters/second. */
|
||||
virtual float getSpeed() const {return m_speed; }
|
||||
|
@ -72,9 +72,8 @@ KartProperties::KartProperties(const std::string &filename)
|
||||
m_wheel_radius = m_chassis_linear_damping = m_max_suspension_force =
|
||||
m_chassis_angular_damping = m_suspension_rest =
|
||||
m_max_speed_reverse_ratio = m_rescue_vert_offset =
|
||||
m_upright_tolerance = m_collision_terrain_impulse =
|
||||
m_collision_impulse = m_restitution = m_collision_impulse_time =
|
||||
m_upright_max_force = m_suspension_travel_cm =
|
||||
m_collision_terrain_impulse = m_collision_impulse = m_restitution =
|
||||
m_collision_impulse_time = m_suspension_travel_cm =
|
||||
m_track_connection_accel = m_rubber_band_max_length =
|
||||
m_rubber_band_force = m_rubber_band_duration =
|
||||
m_rubber_band_speed_increase = m_rubber_band_fade_out_time =
|
||||
@ -172,13 +171,19 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
{
|
||||
// Get the default values from STKConfig. This will also allocate any
|
||||
// pointers used in KartProperties
|
||||
copyFrom(&stk_config->getDefaultKartProperties());
|
||||
|
||||
const XMLNode* root = new XMLNode(filename);
|
||||
std::string kart_type;
|
||||
if (root->get("type", &kart_type))
|
||||
copyFrom(&stk_config->getKartProperties(kart_type));
|
||||
else
|
||||
copyFrom(&stk_config->getDefaultKartProperties());
|
||||
|
||||
// m_kart_model must be initialised after assigning the default
|
||||
// values from stk_config (otherwise all kart_properties will
|
||||
// share the same KartModel
|
||||
m_kart_model = new KartModel(/*is_master*/true);
|
||||
|
||||
const XMLNode * root = 0;
|
||||
m_root = StringUtils::getPath(filename)+"/";
|
||||
m_ident = StringUtils::getBasename(StringUtils::getPath(filename));
|
||||
// If this is an addon kart, add "addon_" to the identifier - just in
|
||||
@ -188,7 +193,6 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
m_ident = Addon::createAddonId(m_ident);
|
||||
try
|
||||
{
|
||||
root = new XMLNode(filename);
|
||||
if(!root || root->getName()!="kart")
|
||||
{
|
||||
std::ostringstream msg;
|
||||
@ -286,7 +290,7 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
*/
|
||||
void KartProperties::getAllData(const XMLNode * root)
|
||||
{
|
||||
root->get("version", &m_version);
|
||||
root->get("version", &m_version);
|
||||
|
||||
root->get("name", &m_name );
|
||||
|
||||
@ -307,50 +311,11 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
root->get("shadow-x-offset", &m_shadow_x_offset );
|
||||
root->get("shadow-y-offset", &m_shadow_y_offset );
|
||||
|
||||
root->get("type", &m_kart_type );
|
||||
|
||||
if(const XMLNode *dimensions_node = root->getNode("center"))
|
||||
dimensions_node->get("gravity-shift", &m_gravity_center_shift);
|
||||
|
||||
if(const XMLNode *nitro_node = root->getNode("nitro"))
|
||||
{
|
||||
nitro_node->get("consumption", &m_nitro_consumption );
|
||||
nitro_node->get("small-container", &m_nitro_small_container );
|
||||
nitro_node->get("big-container", &m_nitro_big_container );
|
||||
nitro_node->get("max-speed-increase", &m_nitro_max_speed_increase);
|
||||
nitro_node->get("engine-force", &m_nitro_engine_force );
|
||||
nitro_node->get("duration", &m_nitro_duration );
|
||||
nitro_node->get("fade-out-time", &m_nitro_fade_out_time );
|
||||
nitro_node->get("max", &m_nitro_max );
|
||||
nitro_node->get("min-consumption-time", &m_nitro_min_consumption );
|
||||
}
|
||||
|
||||
if(const XMLNode *bubble_node = root->getNode("bubblegum"))
|
||||
{
|
||||
bubble_node->get("time", &m_bubblegum_time );
|
||||
bubble_node->get("speed-fraction", &m_bubblegum_speed_fraction);
|
||||
bubble_node->get("fade-in-time", &m_bubblegum_fade_in_time );
|
||||
bubble_node->get("torque", &m_bubblegum_torque );
|
||||
}
|
||||
|
||||
if(const XMLNode *rescue_node = root->getNode("rescue"))
|
||||
{
|
||||
rescue_node->get("vert-offset", &m_rescue_vert_offset);
|
||||
rescue_node->get("time", &m_rescue_time );
|
||||
rescue_node->get("height", &m_rescue_height );
|
||||
}
|
||||
|
||||
if(const XMLNode *explosion_node = root->getNode("explosion"))
|
||||
{
|
||||
explosion_node->get("time", &m_explosion_time );
|
||||
explosion_node->get("radius", &m_explosion_radius);
|
||||
explosion_node->get("invulnerability-time",
|
||||
&m_explosion_invulnerability_time);
|
||||
}
|
||||
|
||||
if(const XMLNode *skid_node = root->getNode("skid"))
|
||||
{
|
||||
m_skidding_properties->load(skid_node);
|
||||
}
|
||||
|
||||
if(const XMLNode *ai_node = root->getNode("ai"))
|
||||
{
|
||||
const XMLNode *easy = ai_node->getNode("easy");
|
||||
@ -363,59 +328,6 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
m_ai_properties[RaceManager::DIFFICULTY_BEST]->load(best);
|
||||
}
|
||||
|
||||
if(const XMLNode *slipstream_node = root->getNode("slipstream"))
|
||||
{
|
||||
slipstream_node->get("length", &m_slipstream_length );
|
||||
slipstream_node->get("width", &m_slipstream_width );
|
||||
slipstream_node->get("collect-time", &m_slipstream_collect_time );
|
||||
slipstream_node->get("use-time", &m_slipstream_use_time );
|
||||
slipstream_node->get("add-power", &m_slipstream_add_power );
|
||||
slipstream_node->get("min-speed", &m_slipstream_min_speed );
|
||||
slipstream_node->get("max-speed-increase",
|
||||
&m_slipstream_max_speed_increase);
|
||||
slipstream_node->get("duration", &m_slipstream_duration );
|
||||
slipstream_node->get("fade-out-time",&m_slipstream_fade_out_time );
|
||||
}
|
||||
|
||||
if(const XMLNode *turn_node = root->getNode("turn"))
|
||||
{
|
||||
turn_node->get("time-full-steer", &m_time_full_steer );
|
||||
turn_node->get("time-reset-steer", &m_time_reset_steer );
|
||||
turn_node->get("turn-radius", &m_turn_angle_at_speed );
|
||||
// For now store the turn radius in turn angle, the correct
|
||||
// value can only be determined later in ::load
|
||||
}
|
||||
|
||||
if(const XMLNode *engine_node = root->getNode("engine"))
|
||||
{
|
||||
engine_node->get("brake-factor", &m_brake_factor);
|
||||
engine_node->get("max-speed-reverse-ratio", &m_max_speed_reverse_ratio);
|
||||
engine_node->get("power", &m_engine_power);
|
||||
if(m_engine_power.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("[KartProperties]",
|
||||
"Incorrect engine-power specifications for kart '%s'",
|
||||
getIdent().c_str());
|
||||
}
|
||||
engine_node->get("max-speed", &m_max_speed);
|
||||
if(m_max_speed.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("[KartProperties]",
|
||||
"Incorrect max-speed specifications for kart '%s'",
|
||||
getIdent().c_str());
|
||||
}
|
||||
} // if getNode("engine")
|
||||
|
||||
if(const XMLNode *gear_node = root->getNode("gear"))
|
||||
{
|
||||
gear_node->get("switch-ratio", &m_gear_switch_ratio );
|
||||
gear_node->get("power-increase", &m_gear_power_increase);
|
||||
}
|
||||
|
||||
if(const XMLNode *mass_node = root->getNode("mass"))
|
||||
mass_node->get("value", &m_mass);
|
||||
|
||||
|
||||
if(const XMLNode *suspension_node = root->getNode("suspension"))
|
||||
{
|
||||
suspension_node->get("stiffness", &m_suspension_stiffness);
|
||||
@ -454,12 +366,6 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
&m_track_connection_accel );
|
||||
}
|
||||
|
||||
if(const XMLNode *upright_node = root->getNode("upright"))
|
||||
{
|
||||
upright_node->get("tolerance", &m_upright_tolerance);
|
||||
upright_node->get("max-force", &m_upright_max_force);
|
||||
}
|
||||
|
||||
if(const XMLNode *collision_node = root->getNode("collision"))
|
||||
{
|
||||
collision_node->get("impulse", &m_collision_impulse );
|
||||
@ -488,50 +394,6 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
//TODO: listed as an attribute in the xml file after wheel-radius
|
||||
//TODO: same goes for their rear equivalents
|
||||
|
||||
if(const XMLNode *plunger_node= root->getNode("plunger"))
|
||||
{
|
||||
plunger_node->get("band-max-length", &m_rubber_band_max_length );
|
||||
plunger_node->get("band-force", &m_rubber_band_force );
|
||||
plunger_node->get("band-duration", &m_rubber_band_duration );
|
||||
plunger_node->get("band-speed-increase",&m_rubber_band_speed_increase);
|
||||
plunger_node->get("band-fade-out-time", &m_rubber_band_fade_out_time );
|
||||
plunger_node->get("in-face-time", &m_plunger_in_face_duration);
|
||||
if(m_plunger_in_face_duration.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("KartProperties",
|
||||
"Invalid plunger in-face-time specification.");
|
||||
}
|
||||
}
|
||||
|
||||
if(const XMLNode *zipper_node= root->getNode("zipper"))
|
||||
{
|
||||
zipper_node->get("time", &m_zipper_time );
|
||||
zipper_node->get("fade-out-time", &m_zipper_fade_out_time );
|
||||
zipper_node->get("force", &m_zipper_force );
|
||||
zipper_node->get("speed-gain", &m_zipper_speed_gain );
|
||||
zipper_node->get("max-speed-increase", &m_zipper_max_speed_increase);
|
||||
}
|
||||
|
||||
if(const XMLNode *swatter_node= root->getNode("swatter"))
|
||||
{
|
||||
swatter_node->get("duration", &m_swatter_duration );
|
||||
swatter_node->get("squash-duration", &m_squash_duration );
|
||||
swatter_node->get("squash-slowdown", &m_squash_slowdown );
|
||||
if(swatter_node->get("distance", &m_swatter_distance2) )
|
||||
{
|
||||
// Avoid squaring if distance is not defined, so that
|
||||
// distance2 remains UNDEFINED (which is a negative value)
|
||||
m_swatter_distance2 *= m_swatter_distance2;
|
||||
}
|
||||
}
|
||||
|
||||
if(const XMLNode *lean_node= root->getNode("lean"))
|
||||
{
|
||||
lean_node->get("max", &m_max_lean );
|
||||
lean_node->get("speed", &m_lean_speed);
|
||||
m_max_lean *= DEGREE_TO_RAD;
|
||||
m_lean_speed *= DEGREE_TO_RAD;
|
||||
}
|
||||
|
||||
if(const XMLNode *jump_node= root->getNode("jump"))
|
||||
{
|
||||
@ -547,12 +409,6 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
m_camera_backward_up_angle *= DEGREE_TO_RAD;
|
||||
}
|
||||
|
||||
if(const XMLNode *startup_node= root->getNode("startup"))
|
||||
{
|
||||
startup_node->get("time", &m_startup_times);
|
||||
startup_node->get("boost", &m_startup_boost);
|
||||
}
|
||||
|
||||
if(const XMLNode *sounds_node= root->getNode("sounds"))
|
||||
{
|
||||
std::string s;
|
||||
@ -598,6 +454,151 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
#endif
|
||||
} // if sounds-node exist
|
||||
|
||||
if(const XMLNode *nitro_node = root->getNode("nitro"))
|
||||
{
|
||||
nitro_node->get("consumption", &m_nitro_consumption );
|
||||
nitro_node->get("small-container", &m_nitro_small_container );
|
||||
nitro_node->get("big-container", &m_nitro_big_container );
|
||||
nitro_node->get("max-speed-increase", &m_nitro_max_speed_increase);
|
||||
nitro_node->get("engine-force", &m_nitro_engine_force );
|
||||
nitro_node->get("duration", &m_nitro_duration );
|
||||
nitro_node->get("fade-out-time", &m_nitro_fade_out_time );
|
||||
nitro_node->get("max", &m_nitro_max );
|
||||
nitro_node->get("min-consumption-time", &m_nitro_min_consumption );
|
||||
}
|
||||
|
||||
if(const XMLNode *bubble_node = root->getNode("bubblegum"))
|
||||
{
|
||||
bubble_node->get("time", &m_bubblegum_time );
|
||||
bubble_node->get("speed-fraction", &m_bubblegum_speed_fraction);
|
||||
bubble_node->get("fade-in-time", &m_bubblegum_fade_in_time );
|
||||
bubble_node->get("torque", &m_bubblegum_torque );
|
||||
}
|
||||
|
||||
if(const XMLNode *rescue_node = root->getNode("rescue"))
|
||||
{
|
||||
rescue_node->get("vert-offset", &m_rescue_vert_offset);
|
||||
rescue_node->get("time", &m_rescue_time );
|
||||
rescue_node->get("height", &m_rescue_height );
|
||||
}
|
||||
|
||||
if(const XMLNode *explosion_node = root->getNode("explosion"))
|
||||
{
|
||||
explosion_node->get("time", &m_explosion_time );
|
||||
explosion_node->get("radius", &m_explosion_radius);
|
||||
explosion_node->get("invulnerability-time",
|
||||
&m_explosion_invulnerability_time);
|
||||
}
|
||||
|
||||
if(const XMLNode *skid_node = root->getNode("skid"))
|
||||
{
|
||||
m_skidding_properties->load(skid_node);
|
||||
}
|
||||
|
||||
|
||||
if(const XMLNode *slipstream_node = root->getNode("slipstream"))
|
||||
{
|
||||
slipstream_node->get("length", &m_slipstream_length );
|
||||
slipstream_node->get("width", &m_slipstream_width );
|
||||
slipstream_node->get("collect-time", &m_slipstream_collect_time );
|
||||
slipstream_node->get("use-time", &m_slipstream_use_time );
|
||||
slipstream_node->get("add-power", &m_slipstream_add_power );
|
||||
slipstream_node->get("min-speed", &m_slipstream_min_speed );
|
||||
slipstream_node->get("max-speed-increase",
|
||||
&m_slipstream_max_speed_increase);
|
||||
slipstream_node->get("duration", &m_slipstream_duration );
|
||||
slipstream_node->get("fade-out-time",&m_slipstream_fade_out_time );
|
||||
}
|
||||
|
||||
if(const XMLNode *turn_node = root->getNode("turn"))
|
||||
{
|
||||
turn_node->get("time-full-steer", &m_time_full_steer );
|
||||
turn_node->get("time-reset-steer", &m_time_reset_steer );
|
||||
turn_node->get("turn-radius", &m_turn_angle_at_speed );
|
||||
// For now store the turn radius in turn angle, the correct
|
||||
// value can only be determined later in ::load
|
||||
}
|
||||
|
||||
if(const XMLNode *engine_node = root->getNode("engine"))
|
||||
{
|
||||
engine_node->get("brake-factor", &m_brake_factor);
|
||||
engine_node->get("max-speed-reverse-ratio", &m_max_speed_reverse_ratio);
|
||||
engine_node->get("power", &m_engine_power);
|
||||
if(m_engine_power.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("[KartProperties]",
|
||||
"Incorrect engine-power specifications for kart '%s'",
|
||||
getIdent().c_str());
|
||||
}
|
||||
engine_node->get("max-speed", &m_max_speed);
|
||||
if(m_max_speed.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("[KartProperties]",
|
||||
"Incorrect max-speed specifications for kart '%s'",
|
||||
getIdent().c_str());
|
||||
}
|
||||
} // if getNode("engine")
|
||||
|
||||
if(const XMLNode *gear_node = root->getNode("gear"))
|
||||
{
|
||||
gear_node->get("switch-ratio", &m_gear_switch_ratio );
|
||||
gear_node->get("power-increase", &m_gear_power_increase);
|
||||
}
|
||||
|
||||
if(const XMLNode *mass_node = root->getNode("mass"))
|
||||
mass_node->get("value", &m_mass);
|
||||
|
||||
if(const XMLNode *plunger_node= root->getNode("plunger"))
|
||||
{
|
||||
plunger_node->get("band-max-length", &m_rubber_band_max_length );
|
||||
plunger_node->get("band-force", &m_rubber_band_force );
|
||||
plunger_node->get("band-duration", &m_rubber_band_duration );
|
||||
plunger_node->get("band-speed-increase",&m_rubber_band_speed_increase);
|
||||
plunger_node->get("band-fade-out-time", &m_rubber_band_fade_out_time );
|
||||
plunger_node->get("in-face-time", &m_plunger_in_face_duration);
|
||||
if(m_plunger_in_face_duration.size()!=RaceManager::DIFFICULTY_COUNT)
|
||||
{
|
||||
Log::fatal("KartProperties",
|
||||
"Invalid plunger in-face-time specification.");
|
||||
}
|
||||
}
|
||||
|
||||
if(const XMLNode *zipper_node= root->getNode("zipper"))
|
||||
{
|
||||
zipper_node->get("time", &m_zipper_time );
|
||||
zipper_node->get("fade-out-time", &m_zipper_fade_out_time );
|
||||
zipper_node->get("force", &m_zipper_force );
|
||||
zipper_node->get("speed-gain", &m_zipper_speed_gain );
|
||||
zipper_node->get("max-speed-increase", &m_zipper_max_speed_increase);
|
||||
}
|
||||
|
||||
if(const XMLNode *swatter_node= root->getNode("swatter"))
|
||||
{
|
||||
swatter_node->get("duration", &m_swatter_duration );
|
||||
swatter_node->get("squash-duration", &m_squash_duration );
|
||||
swatter_node->get("squash-slowdown", &m_squash_slowdown );
|
||||
if(swatter_node->get("distance", &m_swatter_distance2) )
|
||||
{
|
||||
// Avoid squaring if distance is not defined, so that
|
||||
// distance2 remains UNDEFINED (which is a negative value)
|
||||
m_swatter_distance2 *= m_swatter_distance2;
|
||||
}
|
||||
}
|
||||
|
||||
if(const XMLNode *lean_node= root->getNode("lean"))
|
||||
{
|
||||
lean_node->get("max", &m_max_lean );
|
||||
lean_node->get("speed", &m_lean_speed);
|
||||
m_max_lean *= DEGREE_TO_RAD;
|
||||
m_lean_speed *= DEGREE_TO_RAD;
|
||||
}
|
||||
|
||||
if(const XMLNode *startup_node= root->getNode("startup"))
|
||||
{
|
||||
startup_node->get("time", &m_startup_times);
|
||||
startup_node->get("boost", &m_startup_boost);
|
||||
}
|
||||
|
||||
if(m_kart_model)
|
||||
m_kart_model->loadInfo(*root);
|
||||
} // getAllData
|
||||
@ -665,8 +666,6 @@ void KartProperties::checkAllSet(const std::string &filename)
|
||||
CHECK_NEG(m_bevel_factor.getX(), "collision bevel-factor" );
|
||||
CHECK_NEG(m_bevel_factor.getY(), "collision bevel-factor" );
|
||||
CHECK_NEG(m_bevel_factor.getZ(), "collision bevel-factor" );
|
||||
CHECK_NEG(m_upright_tolerance, "upright tolerance" );
|
||||
CHECK_NEG(m_upright_max_force, "upright max-force" );
|
||||
CHECK_NEG(m_rubber_band_max_length, "plunger band-max-length" );
|
||||
CHECK_NEG(m_rubber_band_force, "plunger band-force" );
|
||||
CHECK_NEG(m_rubber_band_duration, "plunger band-duration" );
|
||||
@ -755,6 +754,7 @@ bool KartProperties::isInGroup(const std::string &group) const
|
||||
return std::find(m_groups.begin(), m_groups.end(), group) != m_groups.end();
|
||||
} // isInGroups
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called the first time a kart accelerates after 'ready-set-go'. It searches
|
||||
* through m_startup_times to find the appropriate slot, and returns the
|
||||
@ -771,4 +771,16 @@ float KartProperties::getStartupBoost() const
|
||||
}
|
||||
return 0;
|
||||
} // getStartupBoost
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const float KartProperties::getAvgPower() const
|
||||
{
|
||||
float sum = 0.0;
|
||||
for (unsigned int i = 0; i < m_gear_power_increase.size(); ++i)
|
||||
{
|
||||
sum += m_gear_power_increase[i]*m_max_speed[0];
|
||||
}
|
||||
return sum/m_gear_power_increase.size();
|
||||
} // getAvgPower
|
||||
|
||||
/* EOF */
|
||||
|
@ -181,6 +181,9 @@ private:
|
||||
*/
|
||||
float m_nitro_min_consumption;
|
||||
|
||||
/** Type of the kart (for the properties) */
|
||||
std::string m_kart_type;
|
||||
|
||||
/** Filename of the wheel models. */
|
||||
std::string m_wheel_filename[4];
|
||||
/** Radius of the graphical wheels. */
|
||||
@ -325,9 +328,6 @@ private:
|
||||
/** The restitution factor to be used in collsions for this kart. */
|
||||
float m_restitution;
|
||||
|
||||
float m_upright_tolerance;
|
||||
float m_upright_max_force;
|
||||
|
||||
/** How far behind a kart slipstreaming is effective. */
|
||||
float m_slipstream_length;
|
||||
/** How wide the slipstream area is at the end. */
|
||||
@ -543,7 +543,10 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns parameters for the speed-weighted objects */
|
||||
const SpeedWeightedObject::Properties& getSpeedWeightedObjectProperties() const {return m_speed_weighted_object_properties;}
|
||||
const SpeedWeightedObject::Properties& getSpeedWeightedObjectProperties() const
|
||||
{
|
||||
return m_speed_weighted_object_properties;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the wheel base (distance front to rear axis). */
|
||||
@ -568,8 +571,17 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum speed dependent on the difficult level. */
|
||||
float getMaxSpeed () const {return
|
||||
m_max_speed[race_manager->getDifficulty()];}
|
||||
float getMaxSpeed () const
|
||||
{
|
||||
return m_max_speed[race_manager->getDifficulty()];
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the absolute maximum speed, independent on the difficulty. */
|
||||
float getAbsMaxSpeed () const
|
||||
{
|
||||
return m_max_speed[m_max_speed.size()-1];
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the nitro consumption. */
|
||||
@ -684,15 +696,6 @@ public:
|
||||
float getExplosionInvulnerabilityTime() const
|
||||
{ return m_explosion_invulnerability_time; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns how much a kart can roll/pitch before the upright constraint
|
||||
* counteracts. */
|
||||
float getUprightTolerance () const {return m_upright_tolerance; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum value of the upright counteracting force. */
|
||||
float getUprightMaxForce () const {return m_upright_max_force; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum length of a rubber band before it breaks. */
|
||||
float getRubberBandMaxLength () const {return m_rubber_band_max_length;}
|
||||
@ -826,6 +829,10 @@ public:
|
||||
const std::vector<float>&
|
||||
getGearPowerIncrease () const {return m_gear_power_increase; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the average power of the kart (in all gears). */
|
||||
const float getAvgPower () const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns distance between kart and camera. */
|
||||
float getCameraDistance () const {return m_camera_distance; }
|
||||
|
@ -854,7 +854,7 @@ int handleCmdLine()
|
||||
Log::warn("main", "There is no GP named '%s'.", s.c_str());
|
||||
return 0;
|
||||
}
|
||||
race_manager->setGrandPrix(*gp);
|
||||
race_manager->setGrandPrix(gp);
|
||||
} // --gp
|
||||
|
||||
if(CommandLine::has("--numkarts", &n) ||CommandLine::has("-k", &n))
|
||||
|
@ -149,12 +149,12 @@ void OverWorld::update(float dt)
|
||||
if (m_return_to_garage)
|
||||
{
|
||||
m_return_to_garage = false;
|
||||
delayedSelfDestruct();
|
||||
race_manager->exitRace(false);
|
||||
race_manager->exitRace();
|
||||
KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
|
||||
s->setMultiplayer(false);
|
||||
s->setFromOverworld(true);
|
||||
StateManager::get()->resetAndGoToScreen(s);
|
||||
throw AbortWorldUpdateException();
|
||||
}
|
||||
} // update
|
||||
|
||||
|
@ -796,7 +796,14 @@ void World::updateWorld(float dt)
|
||||
getPhase() == IN_GAME_MENU_PHASE )
|
||||
return;
|
||||
|
||||
update(dt);
|
||||
try
|
||||
{
|
||||
update(dt);
|
||||
}
|
||||
catch (AbortWorldUpdateException& e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(m_magic_number == 0xB01D6543);
|
||||
|
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "modes/world_status.hpp"
|
||||
#include "race/highscores.hpp"
|
||||
@ -47,6 +48,12 @@ namespace irr
|
||||
namespace scene { class ISceneNode; }
|
||||
}
|
||||
|
||||
class AbortWorldUpdateException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
AbortWorldUpdateException() : std::runtime_error("race abort") { };
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief base class for all game modes
|
||||
* This class is responsible for running the actual race. A world is created
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
/** \brief Gets the element with the highest count in a std::map<S,int>.
|
||||
* \param histogram : A pointer to the histogram.
|
||||
* \return The key of type S that has the highest second value.
|
||||
|
@ -323,35 +323,24 @@ btScalar btKart::rayCast(unsigned int index)
|
||||
#else
|
||||
if(index==2 || index==3)
|
||||
{
|
||||
if(m_visual_rotation==0.123123123)
|
||||
btTransform chassisTrans = getChassisWorldTransform();
|
||||
if (getRigidBody()->getMotionState())
|
||||
{
|
||||
m_visual_contact_point[index ] = rayResults.m_hitPointInWorld;
|
||||
m_visual_contact_point[index-2] = source;
|
||||
m_visual_wheels_touch_ground &= (object!=NULL);
|
||||
getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
|
||||
}
|
||||
else
|
||||
{
|
||||
btTransform chassisTrans = getChassisWorldTransform();
|
||||
if (getRigidBody()->getMotionState())
|
||||
{
|
||||
getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
|
||||
}
|
||||
btQuaternion q(m_visual_rotation, 0, 0);
|
||||
btQuaternion rot_new = chassisTrans.getRotation() * q;
|
||||
chassisTrans.setRotation(rot_new);
|
||||
btVector3 pos = m_kart->getKartModel()->getWheelGraphicsPosition(index);
|
||||
pos.setZ(pos.getZ()*0.9f);
|
||||
//pos.setX(pos.getX()*0.1f);
|
||||
//btVector3 pos = wheel.m_chassisConnectionPointCS;
|
||||
btVector3 source = chassisTrans( pos );
|
||||
btVector3 target = source + rayvector;
|
||||
btVehicleRaycaster::btVehicleRaycasterResult rayResults;
|
||||
btQuaternion q(m_visual_rotation, 0, 0);
|
||||
btQuaternion rot_new = chassisTrans.getRotation() * q;
|
||||
chassisTrans.setRotation(rot_new);
|
||||
btVector3 pos = m_kart->getKartModel()->getWheelGraphicsPosition(index);
|
||||
pos.setZ(pos.getZ()*0.9f);
|
||||
btVector3 source = chassisTrans( pos );
|
||||
btVector3 target = source + rayvector;
|
||||
btVehicleRaycaster::btVehicleRaycasterResult rayResults;
|
||||
|
||||
void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
|
||||
m_visual_contact_point[index] = rayResults.m_hitPointInWorld;
|
||||
m_visual_contact_point[index-2] = source;
|
||||
m_visual_wheels_touch_ground &= (object!=NULL);
|
||||
}
|
||||
void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
|
||||
m_visual_contact_point[index] = rayResults.m_hitPointInWorld;
|
||||
m_visual_contact_point[index-2] = source;
|
||||
m_visual_wheels_touch_ground &= (object!=NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -600,7 +589,7 @@ void btKart::updateSuspension(btScalar deltaTime)
|
||||
btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
|
||||
btScalar length_diff = (susp_length - current_length);
|
||||
if(m_kart->getKartProperties()->getExpSpringResponse())
|
||||
length_diff *= length_diff/susp_length;
|
||||
length_diff *= fabsf(length_diff)/susp_length;
|
||||
|
||||
force = wheel_info.m_suspensionStiffness * length_diff
|
||||
* wheel_info.m_clippedInvContactDotSuspension;
|
||||
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (C) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim
|
||||
that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
*/
|
||||
|
||||
#include "physics/btUprightConstraint.hpp"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "LinearMath/btTransformUtil.h"
|
||||
|
||||
#include "karts/kart.hpp"
|
||||
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
|
||||
void btUprightConstraint::solveAngularLimit(
|
||||
btUprightConstraintLimit *limit,
|
||||
btScalar timeStep, btScalar jacDiagABInv,
|
||||
btRigidBody * body0 )
|
||||
{
|
||||
|
||||
// Work out if limit is violated
|
||||
if(limit->m_angle>=m_loLimit && limit->m_angle<=m_hiLimit) return;
|
||||
|
||||
limit->m_currentLimitError = (limit->m_angle<m_loLimit)
|
||||
? limit->m_angle - m_loLimit
|
||||
: limit->m_angle - m_hiLimit;
|
||||
|
||||
btScalar targetVelocity = -m_ERP*limit->m_currentLimitError
|
||||
/ (3.1415f/8.0f*timeStep);
|
||||
btScalar maxMotorForce = m_maxLimitForce;
|
||||
|
||||
maxMotorForce *= timeStep;
|
||||
|
||||
// current velocity difference
|
||||
btVector3 angularVelocity = body0->getAngularVelocity();
|
||||
btScalar axisAngularVelocity = limit->m_axis.dot( angularVelocity );
|
||||
|
||||
// correction velocity
|
||||
btScalar motorVelocity = m_limitSoftness*(targetVelocity
|
||||
- m_damping*axisAngularVelocity);
|
||||
|
||||
// correction impulse
|
||||
btScalar unclippedMotorImpulse = (1+m_bounce)*motorVelocity*jacDiagABInv;
|
||||
|
||||
// clip correction impulse
|
||||
btScalar clippedMotorImpulse = unclippedMotorImpulse;
|
||||
|
||||
//todo: should clip against accumulated impulse
|
||||
|
||||
if (unclippedMotorImpulse>0.0f)
|
||||
{
|
||||
clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce
|
||||
? maxMotorForce : unclippedMotorImpulse;
|
||||
}
|
||||
else
|
||||
{
|
||||
clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce
|
||||
? -maxMotorForce : unclippedMotorImpulse;
|
||||
}
|
||||
|
||||
// sort with accumulated impulses
|
||||
btScalar lo = btScalar(-1e30);
|
||||
btScalar hi = btScalar(1e30);
|
||||
|
||||
btScalar oldaccumImpulse = limit->m_accumulatedImpulse;
|
||||
|
||||
btScalar sum = oldaccumImpulse + clippedMotorImpulse;
|
||||
|
||||
limit->m_accumulatedImpulse = sum > hi ? btScalar(0.)
|
||||
: sum < lo ? btScalar(0.) : sum;
|
||||
|
||||
clippedMotorImpulse = limit->m_accumulatedImpulse - oldaccumImpulse;
|
||||
|
||||
btVector3 motorImp = clippedMotorImpulse * limit->m_axis;
|
||||
body0->applyTorqueImpulse(motorImp);
|
||||
} // solveAngularLimit
|
||||
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
|
||||
btUprightConstraint::btUprightConstraint(const Kart* kart,
|
||||
const btTransform& frameInA)
|
||||
: btTypedConstraint(D6_CONSTRAINT_TYPE, *(kart->getBody()))
|
||||
, m_frameInA(frameInA)
|
||||
|
||||
{
|
||||
m_kart = kart;
|
||||
m_ERP = 1.0f;
|
||||
m_bounce = 0.0f;
|
||||
m_damping = 1.0f;
|
||||
m_limitSoftness = 1.0f;
|
||||
m_maxLimitForce = 3000.0f;
|
||||
m_disable_time = 0.0f;
|
||||
m_limit[0].m_accumulatedImpulse = 0.0f;
|
||||
m_limit[1].m_accumulatedImpulse = 0.0f;
|
||||
m_limit[ 0 ].m_axis = btVector3( 1, 0, 0 );
|
||||
m_limit[ 1 ].m_axis = btVector3( 0, 0, 1 );
|
||||
setLimit( SIMD_PI * 0.4f );
|
||||
} // btUprightConstraint
|
||||
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
|
||||
void btUprightConstraint::buildJacobian()
|
||||
{
|
||||
m_limit[ 0 ].m_angle = m_kart->getPitch();
|
||||
m_limit[ 1 ].m_angle = -m_kart->getRoll();
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
new (&m_jacAng[ i ]) btJacobianEntry( m_limit[ i ].m_axis,
|
||||
m_rbA.getCenterOfMassTransform().getBasis().transpose(),
|
||||
m_rbB.getCenterOfMassTransform().getBasis().transpose(),
|
||||
m_rbA.getInvInertiaDiagLocal(),
|
||||
m_rbB.getInvInertiaDiagLocal());
|
||||
}
|
||||
} // buildJacobian
|
||||
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
|
||||
void btUprightConstraint::solveConstraintObsolete(btRigidBody& /*bodyA*/,btRigidBody& /*bodyB*/,btScalar timeStep)
|
||||
{
|
||||
m_timeStep = timeStep;
|
||||
|
||||
// Update disable time and return if constraint is still disabled
|
||||
if(m_disable_time>0.0f)
|
||||
{
|
||||
m_disable_time -= timeStep;
|
||||
if(m_disable_time>0.0f) return;
|
||||
}
|
||||
|
||||
solveAngularLimit( &m_limit[ 0 ], m_timeStep, btScalar(1.) / m_jacAng[ 0 ].getDiagonal(), &m_rbA );
|
||||
solveAngularLimit( &m_limit[ 1 ], m_timeStep, btScalar(1.) / m_jacAng[ 1 ].getDiagonal(), &m_rbA );
|
||||
} // solveConstraint
|
||||
|
||||
void btUprightConstraint::getInfo1(btConstraintInfo1* info) {
|
||||
info->m_numConstraintRows = 0;
|
||||
info->nub = 0;
|
||||
}
|
||||
|
||||
void btUprightConstraint::getInfo2(btConstraintInfo2* info) {
|
||||
}
|
||||
|
||||
btScalar btUprightConstraint::getParam(int num, int axis) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btUprightConstraint::setParam(int num, btScalar value, int axis)
|
||||
{
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (C) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim
|
||||
that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef HEADER_UPRIGHT_CONSTRAINT_HPP
|
||||
#define HEADER_UPRIGHT_CONSTRAINT_HPP
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||
|
||||
class btRigidBody;
|
||||
class Kart;
|
||||
|
||||
/**
|
||||
* \ingroup physics
|
||||
*/
|
||||
class btUprightConstraint : public btTypedConstraint
|
||||
{
|
||||
private:
|
||||
class btUprightConstraintLimit
|
||||
{
|
||||
public:
|
||||
btVector3 m_axis;
|
||||
btScalar m_angle;
|
||||
btScalar m_accumulatedImpulse;
|
||||
btScalar m_currentLimitError;
|
||||
};
|
||||
|
||||
//! relative_frames
|
||||
|
||||
//!@{
|
||||
btTransform m_frameInA;//!< the constraint space w.r.t body A
|
||||
//!@}
|
||||
|
||||
//! Jacobians
|
||||
//!@{
|
||||
btJacobianEntry m_jacAng[ 2 ];//!< angular constraint
|
||||
//!@}
|
||||
|
||||
const Kart *m_kart;
|
||||
protected:
|
||||
|
||||
//! temporal variables
|
||||
//!@{
|
||||
btScalar m_timeStep;
|
||||
btScalar m_ERP;
|
||||
btScalar m_bounce;
|
||||
btScalar m_damping;
|
||||
btScalar m_maxLimitForce;
|
||||
btScalar m_limitSoftness;
|
||||
btScalar m_hiLimit;
|
||||
btScalar m_loLimit;
|
||||
btScalar m_disable_time;
|
||||
|
||||
btUprightConstraintLimit m_limit[ 2 ];
|
||||
|
||||
//!@}
|
||||
|
||||
btUprightConstraint& operator=(btUprightConstraint& other)
|
||||
{
|
||||
btAssert(0);
|
||||
(void) other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void buildAngularJacobian(btJacobianEntry & jacAngular,
|
||||
const btVector3 & jointAxisW);
|
||||
|
||||
void solveAngularLimit(btUprightConstraintLimit *limit,
|
||||
btScalar timeStep, btScalar jacDiagABInv,
|
||||
btRigidBody * body0 );
|
||||
|
||||
public:
|
||||
|
||||
btUprightConstraint(const Kart* kart, const btTransform& frameInA);
|
||||
|
||||
// -PI,+PI is the full range
|
||||
// 0,0 is no rotation around x or z
|
||||
// -PI*0.2,+PI*0.2 is a nice bit of tilt
|
||||
void setLimit( btScalar range ) { m_loLimit = -range;
|
||||
m_hiLimit = +range; }
|
||||
// Error correction scaling
|
||||
// 0 - 1
|
||||
void setErp( btScalar erp ) { m_ERP = erp; }
|
||||
void setBounce( btScalar bounce ) { m_bounce = bounce; }
|
||||
void setMaxLimitForce( btScalar force ) { m_maxLimitForce = force; }
|
||||
void setLimitSoftness( btScalar softness ) { m_limitSoftness = softness; }
|
||||
void setDamping( btScalar damping ) { m_damping = damping; }
|
||||
void setDisableTime( btScalar t ) { m_disable_time = t; }
|
||||
virtual void buildJacobian();
|
||||
virtual void solveConstraintObsolete(btRigidBody& /*bodyA*/,
|
||||
btRigidBody& /*bodyB*/, btScalar
|
||||
timeStep);
|
||||
virtual void getInfo1 (btConstraintInfo1* info);
|
||||
virtual void getInfo2 (btConstraintInfo2* info);
|
||||
virtual void setParam(int num, btScalar value, int axis = -1);
|
||||
virtual btScalar getParam(int num, int axis) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //UPRIGHT_CONSTRAINT_H
|
||||
|
@ -580,7 +580,7 @@ void PhysicalObject::hit(const Material *m, const Vec3 &normal)
|
||||
if(isSoccerBall() && m != NULL &&
|
||||
m->getCollisionReaction() == Material::PUSH_SOCCER_BALL)
|
||||
{
|
||||
m_body->applyCentralImpulse(normal * 1000.0f);
|
||||
m_body->applyCentralImpulse(normal * 100.0f);
|
||||
}
|
||||
} // hit
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/btUprightConstraint.hpp"
|
||||
#include "physics/irr_debug_drawer.hpp"
|
||||
#include "physics/physical_object.hpp"
|
||||
#include "physics/stk_dynamics_world.hpp"
|
||||
@ -85,8 +84,8 @@ Physics::~Physics()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a kart to the physics engine.
|
||||
* This adds the rigid body, the vehicle, and the upright constraint, but only
|
||||
* if the kart is not already in the physics world.
|
||||
* This adds the rigid body and the vehicle but only if the kart is not
|
||||
* already in the physics world.
|
||||
* \param kart The kart to add.
|
||||
* \param vehicle The raycast vehicle object.
|
||||
*/
|
||||
@ -101,7 +100,6 @@ void Physics::addKart(const AbstractKart *kart)
|
||||
}
|
||||
m_dynamics_world->addRigidBody(kart->getBody());
|
||||
m_dynamics_world->addVehicle(kart->getVehicle());
|
||||
m_dynamics_world->addConstraint(kart->getUprightConstraint());
|
||||
} // addKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -129,7 +127,6 @@ void Physics::removeKart(const AbstractKart *kart)
|
||||
{
|
||||
m_dynamics_world->removeRigidBody(kart->getBody());
|
||||
m_dynamics_world->removeVehicle(kart->getVehicle());
|
||||
m_dynamics_world->removeConstraint(kart->getUprightConstraint());
|
||||
}
|
||||
} // removeKart
|
||||
|
||||
|
@ -24,13 +24,15 @@
|
||||
#include "config/player_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/utf_writer.hpp"
|
||||
#include "states_screens/dialogs/random_gp_dialog.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
@ -44,6 +46,94 @@ GrandPrixData::GrandPrixData(const std::string& filename)
|
||||
reload();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData::GrandPrixData(const unsigned int number_of_tracks,
|
||||
const std::string& track_group,
|
||||
const RandomGPInfoDialog::REVERSED use_reverse)
|
||||
{
|
||||
m_filename = "Random GP - Not loaded from a file!";
|
||||
m_id = "random";
|
||||
m_name = "Random Grand Prix";
|
||||
m_editable = false;
|
||||
|
||||
m_tracks.reserve(number_of_tracks);
|
||||
m_laps.reserve(number_of_tracks);
|
||||
m_reversed.reserve(number_of_tracks);
|
||||
|
||||
changeTrackNumber(number_of_tracks, track_group);
|
||||
changeReverse(use_reverse);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks,
|
||||
const std::string& track_group)
|
||||
{
|
||||
// The problem with the track groups is that "all" isn't a track group
|
||||
// TODO: Add "all" to the track groups and rewrite this more elegant
|
||||
std::vector<int> track_indices;
|
||||
size_t available_tracks;
|
||||
if (track_group == "all")
|
||||
{
|
||||
available_tracks = track_manager->getNumberOfTracks();
|
||||
}
|
||||
else
|
||||
{
|
||||
track_indices = track_manager->getTracksInGroup(track_group);
|
||||
available_tracks = track_indices.size();
|
||||
}
|
||||
assert(number_of_tracks <= available_tracks);
|
||||
|
||||
// add or remove the right number of tracks
|
||||
if (m_tracks.size() < number_of_tracks)
|
||||
{
|
||||
while (m_tracks.size() < number_of_tracks)
|
||||
{
|
||||
int index = (track_group == "all") ?
|
||||
rand() % available_tracks :
|
||||
track_indices[rand() % available_tracks];
|
||||
|
||||
std::string id = track_manager->getTrack(index)->getIdent();
|
||||
// Avoid duplicate tracks
|
||||
if (std::find(m_tracks.begin(), m_tracks.end(), id) != m_tracks.end())
|
||||
continue;
|
||||
|
||||
m_tracks.push_back(id);
|
||||
m_laps.push_back(3); // TODO: Take the default number from the track
|
||||
m_reversed.push_back(false); // This will be changed later
|
||||
}
|
||||
}
|
||||
else if (m_tracks.size() > number_of_tracks)
|
||||
{
|
||||
while (m_tracks.size() > number_of_tracks)
|
||||
{
|
||||
m_tracks.pop_back();
|
||||
m_laps.pop_back();
|
||||
m_reversed.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_tracks.size() == m_laps.size() );
|
||||
assert(m_laps.size() == m_reversed.size());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GrandPrixData::changeReverse(const RandomGPInfoDialog::REVERSED use_reverse)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_tracks.size(); i++)
|
||||
{
|
||||
if (use_reverse == RandomGPInfoDialog::NO_REVERSE)
|
||||
m_reversed[i] = false;
|
||||
else if (use_reverse == RandomGPInfoDialog::MIXED)
|
||||
if (track_manager->getTrack(m_tracks[i])->reverseAvailable())
|
||||
m_reversed[i] = (rand() % 2 != 0);
|
||||
else
|
||||
m_reversed[i] = false;
|
||||
else // all reversed
|
||||
m_reversed[i] = track_manager->getTrack(m_tracks[i])->reverseAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::setId(const std::string& id)
|
||||
{
|
||||
|
@ -20,14 +20,15 @@
|
||||
#ifndef HEADER_GRAND_PRIX_DATA_HPP
|
||||
#define HEADER_GRAND_PRIX_DATA_HPP
|
||||
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <irrString.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "states_screens/dialogs/random_gp_dialog.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
using irr::core::stringw;
|
||||
|
||||
class Track;
|
||||
|
||||
/** Simple class that hold the data relevant to a 'grand_prix', aka. a number
|
||||
@ -76,6 +77,13 @@ public:
|
||||
GrandPrixData(const std::string& filename);
|
||||
/** Needed for simple creation of an instance of GrandPrixData */
|
||||
GrandPrixData() {};
|
||||
/** Creates a new random GP */
|
||||
GrandPrixData(const unsigned int number_of_tracks,
|
||||
const std::string& track_group,
|
||||
const RandomGPInfoDialog::REVERSED use_reverse);
|
||||
void changeTrackNumber(const unsigned int number_of_tracks,
|
||||
const std::string& track_group);
|
||||
void changeReverse(const RandomGPInfoDialog::REVERSED use_reverse);
|
||||
|
||||
// Methods for the GP editor
|
||||
void setId(const std::string& id);
|
||||
@ -117,7 +125,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the filename of the grand prix xml file. */
|
||||
const std::string& getFilename() const { return m_filename; }
|
||||
|
||||
}; // GrandPrixData
|
||||
|
||||
#endif
|
||||
|
@ -31,6 +31,23 @@ GrandPrixManager *grand_prix_manager = NULL;
|
||||
|
||||
const char* GrandPrixManager::SUFFIX = ".grandprix";
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::GrandPrixManager()
|
||||
{
|
||||
m_random_gp = NULL; // better do it explicitly and avoid weird stuff
|
||||
loadFiles();
|
||||
} // GrandPrixManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::~GrandPrixManager()
|
||||
{
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
{
|
||||
delete m_gp_data[i];
|
||||
}
|
||||
delete m_random_gp;
|
||||
} // ~GrandPrixManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::loadFiles()
|
||||
{
|
||||
@ -48,7 +65,7 @@ void GrandPrixManager::loadFiles()
|
||||
if (!dir.empty() && dir[dir.size() - 1] == '/')
|
||||
loadDir(dir);
|
||||
}
|
||||
}
|
||||
} // loadFiles
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::loadDir(const std::string& dir)
|
||||
@ -64,7 +81,7 @@ void GrandPrixManager::loadDir(const std::string& dir)
|
||||
i != result.end(); i++)
|
||||
if (StringUtils::hasSuffix(*i, SUFFIX))
|
||||
load(dir + *i);
|
||||
}
|
||||
} // loadDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::load(const std::string& filename)
|
||||
@ -92,7 +109,7 @@ void GrandPrixManager::reload()
|
||||
m_gp_data.clear();
|
||||
|
||||
loadFiles();
|
||||
}
|
||||
} // reload
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string GrandPrixManager::generateId()
|
||||
@ -118,7 +135,7 @@ std::string GrandPrixManager::generateId()
|
||||
}
|
||||
|
||||
return s.str();
|
||||
}
|
||||
} // generateId
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixManager::existsName(const irr::core::stringw& name) const
|
||||
@ -128,32 +145,20 @@ bool GrandPrixManager::existsName(const irr::core::stringw& name) const
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::GrandPrixManager()
|
||||
{
|
||||
loadFiles();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::~GrandPrixManager()
|
||||
{
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
{
|
||||
delete m_gp_data[i];
|
||||
}
|
||||
}
|
||||
} // existsName
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const
|
||||
{
|
||||
return editGrandPrix(s);
|
||||
}
|
||||
} // getGrandPrix
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const
|
||||
{
|
||||
if (s == "random")
|
||||
return m_random_gp;
|
||||
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
{
|
||||
if(m_gp_data[i]->getId() == s)
|
||||
@ -161,7 +166,7 @@ GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const
|
||||
} // for i in m_gp_data
|
||||
|
||||
return NULL;
|
||||
}
|
||||
} // editGrandPrix
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::checkConsistency()
|
||||
@ -194,7 +199,7 @@ GrandPrixData* GrandPrixManager::createNewGP(const irr::core::stringw& newName)
|
||||
m_gp_data.push_back(gp);
|
||||
|
||||
return gp;
|
||||
}
|
||||
} // createNewGP
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::copy(const std::string& id,
|
||||
@ -214,7 +219,7 @@ GrandPrixData* GrandPrixManager::copy(const std::string& id,
|
||||
m_gp_data.push_back(gp);
|
||||
|
||||
return gp;
|
||||
}
|
||||
} // copy
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::remove(const std::string& id)
|
||||
@ -232,4 +237,4 @@ void GrandPrixManager::remove(const std::string& id)
|
||||
Log::warn("GrandPrixManager",
|
||||
"Grand Prix '%s' can not be removed", gp->getId().c_str());
|
||||
}
|
||||
}
|
||||
} // remove
|
||||
|
@ -47,6 +47,10 @@ private:
|
||||
bool existsName(const irr::core::stringw& name) const;
|
||||
|
||||
public:
|
||||
/** saved here by a random GP dialog to avoid dangling pinters or
|
||||
* memory leaks */
|
||||
GrandPrixData* m_random_gp;
|
||||
|
||||
GrandPrixManager();
|
||||
~GrandPrixManager();
|
||||
void reload();
|
||||
|
@ -771,9 +771,10 @@ void RaceManager::startGP(const GrandPrixData* gp, bool from_overworld,
|
||||
bool continue_saved_gp)
|
||||
{
|
||||
assert(gp != NULL);
|
||||
//std::cout << gp->getId();
|
||||
|
||||
StateManager::get()->enterGameState();
|
||||
setGrandPrix(*gp);
|
||||
setGrandPrix(gp);
|
||||
setCoinTarget( 0 ); // Might still be set from a previous challenge
|
||||
race_manager->setupPlayerKartInfo();
|
||||
m_continue_saved_gp = continue_saved_gp;
|
||||
|
@ -331,7 +331,7 @@ private:
|
||||
int m_coin_target;
|
||||
bool m_has_time_target;
|
||||
float m_time_target;
|
||||
int m_goal_target;
|
||||
int m_goal_target;
|
||||
|
||||
void startNextRace(); // start a next race
|
||||
|
||||
@ -344,7 +344,7 @@ private:
|
||||
|
||||
bool m_have_kart_last_position_on_overworld;
|
||||
Vec3 m_kart_last_position_on_overworld;
|
||||
|
||||
|
||||
/** Determines if saved GP should be continued or not*/
|
||||
bool m_continue_saved_gp;
|
||||
|
||||
@ -410,9 +410,9 @@ public:
|
||||
void setDifficulty(Difficulty diff);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void setGrandPrix(const GrandPrixData &gp)
|
||||
void setGrandPrix(const GrandPrixData *gp)
|
||||
{
|
||||
m_grand_prix = gp;
|
||||
m_grand_prix = *gp;
|
||||
m_coin_target = 0;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@ -525,7 +525,7 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getTrackName() const { return m_tracks[m_track_number];}
|
||||
// ------------------------------------------------------------------------
|
||||
const GrandPrixData *getGrandPrix() const { return &m_grand_prix; }
|
||||
const GrandPrixData& getGrandPrix() const { return m_grand_prix; }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -81,7 +81,7 @@ void EnterGPNameDialog::onEnterPressedInternal()
|
||||
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
|
||||
assert(textCtrl != NULL);
|
||||
stringw name = textCtrl->getText().trim();
|
||||
if (name.size() > 0)
|
||||
if (name.size() > 0 && name != "Random Grand Prix")
|
||||
{
|
||||
// check for duplicate names
|
||||
for (unsigned int i = 0; i < grand_prix_manager->getNumberOfGrandPrix(); i++)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
#include "race/grand_prix_data.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/tracks_screen.hpp"
|
||||
@ -35,143 +36,190 @@
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIStaticText.h>
|
||||
|
||||
using namespace irr::gui;
|
||||
using namespace irr::video;
|
||||
using namespace irr::core;
|
||||
using namespace GUIEngine;
|
||||
using irr::gui::IGUIStaticText;
|
||||
using GUIEngine::PROP_ID;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
typedef GUIEngine::LabelWidget Label;
|
||||
|
||||
GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const float h) : ModalDialog(w, h)
|
||||
const float GPInfoDialog::PERCENT_WIDTH = 0.8f;
|
||||
const float GPInfoDialog::PERCENT_HEIGHT = 0.7f;
|
||||
|
||||
GPInfoDialog::GPInfoDialog(const std::string& gp_ident)
|
||||
: ModalDialog(PERCENT_WIDTH, PERCENT_HEIGHT)
|
||||
{
|
||||
doInit();
|
||||
m_curr_time = 0.0f;
|
||||
|
||||
const int y1 = m_area.getHeight()/7;
|
||||
const int y2 = m_area.getHeight()*6/7;
|
||||
m_gp = grand_prix_manager->getGrandPrix(gp_ident);
|
||||
m_gp->checkConsistency();
|
||||
|
||||
m_gp_ident = gpIdent;
|
||||
m_under_title = m_area.getHeight()/7;
|
||||
m_over_body = m_area.getHeight()/7;
|
||||
m_lower_bound = m_area.getHeight()*6/7;
|
||||
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(gpIdent);
|
||||
assert (gp != NULL);
|
||||
addTitle();
|
||||
addTracks();
|
||||
addScreenshot();
|
||||
addButtons();
|
||||
}
|
||||
|
||||
// ---- GP Name
|
||||
core::rect< s32 > area_top(0, 0, m_area.getWidth(), y1);
|
||||
IGUIStaticText* title = GUIEngine::getGUIEnv()->addStaticText( translations->fribidize(gp->getName()),
|
||||
area_top, false, true, // border, word wrap
|
||||
m_irrlicht_window);
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GPInfoDialog::~GPInfoDialog()
|
||||
{
|
||||
GUIEngine::Screen* curr_screen = GUIEngine::getCurrentScreen();
|
||||
if (curr_screen->getName() == "tracks.stkgui")
|
||||
static_cast<TracksScreen*>(curr_screen)->setFocusOnGP(m_gp->getId());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GPInfoDialog::addTitle()
|
||||
{
|
||||
core::rect< s32 > area_top(0, 0, m_area.getWidth(), m_under_title);
|
||||
IGUIStaticText* title = GUIEngine::getGUIEnv()->addStaticText(
|
||||
translations->fribidize(m_gp->getName()),
|
||||
area_top, false, true, // border, word wrap
|
||||
m_irrlicht_window);
|
||||
title->setTabStop(false);
|
||||
title->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
|
||||
title->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ---- Track listings
|
||||
const std::vector<std::string> tracks = gp->getTrackNames();
|
||||
const int trackAmount = tracks.size();
|
||||
void GPInfoDialog::addTracks()
|
||||
{
|
||||
const std::vector<std::string> tracks = m_gp->getTrackNames();
|
||||
const unsigned int track_amount = tracks.size();
|
||||
|
||||
int height_of_one_line = (y2 - y1)/(trackAmount+1);
|
||||
const int textHeight = GUIEngine::getFontHeight();
|
||||
if (height_of_one_line > (int)(textHeight*1.5f)) height_of_one_line = (int)(textHeight*1.5f);
|
||||
int height_of_one_line = std::min((m_lower_bound - m_over_body)/(track_amount+1),
|
||||
(unsigned int)(GUIEngine::getFontHeight()*1.5f));
|
||||
|
||||
bool gp_ok = true;
|
||||
|
||||
for (int t=0; t<trackAmount; t++)
|
||||
// Count the number of label already existing labels representing a track
|
||||
unsigned int existing = 0;
|
||||
for (unsigned int i = 0; i < m_widgets.size(); i++)
|
||||
{
|
||||
const int from_y = y1 + height_of_one_line*(t+1);
|
||||
|
||||
Track* track = track_manager->getTrack(tracks[t]);
|
||||
stringw lineText;
|
||||
if (track == NULL)
|
||||
{
|
||||
lineText = L"MISSING : ";
|
||||
lineText.append( stringw(tracks[t].c_str()) );
|
||||
gp_ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineText = track->getName();
|
||||
}
|
||||
|
||||
LabelWidget* widget = new LabelWidget();
|
||||
widget->setText(translations->fribidize(lineText), false);
|
||||
widget->m_x = 20;
|
||||
widget->m_y = from_y;
|
||||
widget->m_w = m_area.getWidth()/2 - 20;
|
||||
widget->m_h = height_of_one_line;
|
||||
widget->setParent(m_irrlicht_window);
|
||||
|
||||
m_widgets.push_back(widget);
|
||||
widget->add();
|
||||
|
||||
// IGUIStaticText* line = GUIEngine::getGUIEnv()->addStaticText( lineText.c_str(),
|
||||
// entry_area, false , true , // border, word wrap
|
||||
// m_irrlicht_window);
|
||||
if (m_widgets.get(i)->m_properties[PROP_ID] == "Track label")
|
||||
existing++;
|
||||
}
|
||||
|
||||
// ---- Track screenshot
|
||||
unsigned int reuse = std::min(existing, track_amount);
|
||||
// m_widgets has the type PtrVector<Widget, HOLD>
|
||||
unsigned int widgets_iter = 0;
|
||||
for (unsigned int i = 0; i < reuse; i++)
|
||||
{
|
||||
Track* track = track_manager->getTrack(tracks[i]);
|
||||
|
||||
m_screenshot_widget = new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO,
|
||||
false /* tab stop */, false /* focusable */,
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE /* Track gives us absolute paths */);
|
||||
// Find the next widget that is a track label
|
||||
while (m_widgets.get(widgets_iter)->m_properties[PROP_ID] != "Track label")
|
||||
widgets_iter++;
|
||||
|
||||
Label* widget = dynamic_cast<Label*>(m_widgets.get(widgets_iter));
|
||||
widget->setText(translations->fribidize(track->getName()), false);
|
||||
widget->move(20, m_over_body + height_of_one_line*(i+1),
|
||||
m_area.getWidth()/2 - 20, height_of_one_line);
|
||||
|
||||
widgets_iter++;
|
||||
}
|
||||
|
||||
if (existing < track_amount)
|
||||
{
|
||||
// There are not enough labels for all the track names, so we have to
|
||||
// add some more
|
||||
for (unsigned int i = reuse; i < track_amount; i++)
|
||||
{
|
||||
Track* track = track_manager->getTrack(tracks[i]);
|
||||
assert(track != NULL);
|
||||
|
||||
Label* widget = new Label();
|
||||
widget->m_properties[PROP_ID] = "Track label";
|
||||
widget->setText(translations->fribidize(track->getName()), false);
|
||||
widget->setParent(m_irrlicht_window);
|
||||
m_widgets.push_back(widget);
|
||||
widget->add();
|
||||
|
||||
widget->move(20, m_over_body + height_of_one_line*(i+1),
|
||||
m_area.getWidth()/2 - 20, height_of_one_line);
|
||||
}
|
||||
}
|
||||
else if (existing > track_amount)
|
||||
{
|
||||
// There are label which are not necessary anymore so they're deleted
|
||||
for (unsigned int i = widgets_iter; i < m_widgets.size(); i++)
|
||||
{
|
||||
if (m_widgets.get(i)->m_properties[PROP_ID] == "Track label")
|
||||
{
|
||||
m_irrlicht_window->removeChild(m_widgets.get(i)->getIrrlichtElement());
|
||||
m_widgets.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GPInfoDialog::addScreenshot()
|
||||
{
|
||||
m_screenshot_widget = new GUIEngine::IconButtonWidget(
|
||||
GUIEngine::IconButtonWidget::SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO,
|
||||
false, false, GUIEngine::IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
// images are saved squared, but must be stretched to 4:3
|
||||
m_screenshot_widget->setCustomAspectRatio(4.0f / 3.0f);
|
||||
|
||||
m_screenshot_widget->m_x = m_area.getWidth()/2;
|
||||
m_screenshot_widget->m_y = y1;
|
||||
m_screenshot_widget->m_w = m_area.getWidth()/2;
|
||||
m_screenshot_widget->m_h = y2 - y1 - 10;
|
||||
m_screenshot_widget->m_x = m_area.getWidth()/2-20;
|
||||
m_screenshot_widget->m_y = m_over_body + 10;
|
||||
|
||||
Track* track = (tracks.size() == 0 ? NULL : track_manager->getTrack(tracks[0]));
|
||||
// Scale the picture to the biggest possible size without an overflow
|
||||
if (m_lower_bound - m_over_body - 20 < m_area.getWidth()/2*3/4)
|
||||
{
|
||||
m_screenshot_widget->m_w = (m_lower_bound - m_over_body - 30)*4/3;
|
||||
m_screenshot_widget->m_h = m_lower_bound - m_over_body - 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_screenshot_widget->m_w = m_area.getWidth()/2;
|
||||
m_screenshot_widget->m_h = m_area.getWidth()*3/8; // *(3/4)*(1/2)
|
||||
}
|
||||
|
||||
m_screenshot_widget->m_properties[PROP_ICON] = (track != NULL ?
|
||||
track->getScreenshotFile().c_str() :
|
||||
file_manager->getAsset(FileManager::GUI,"main_help.png"));
|
||||
Track* track = track_manager->getTrack(m_gp->getTrackNames()[0]);
|
||||
m_screenshot_widget->m_properties[GUIEngine::PROP_ICON] = (track->getScreenshotFile().c_str());
|
||||
m_screenshot_widget->setParent(m_irrlicht_window);
|
||||
m_screenshot_widget->add();
|
||||
m_widgets.push_back(m_screenshot_widget);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GPInfoDialog::addButtons()
|
||||
{
|
||||
// ---- Start button
|
||||
ButtonWidget* okBtn = new ButtonWidget();
|
||||
ButtonWidget* continueBtn = new ButtonWidget();
|
||||
GUIEngine::ButtonWidget* okBtn = new GUIEngine::ButtonWidget();
|
||||
GUIEngine::ButtonWidget* continueBtn = new GUIEngine::ButtonWidget();
|
||||
|
||||
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP( StateManager::get()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
gpIdent,
|
||||
m_gp->getId(),
|
||||
race_manager->getDifficulty(),
|
||||
race_manager->getNumberOfKarts(),
|
||||
race_manager->getNumLocalPlayers());
|
||||
|
||||
if (tracks.size() == 0)
|
||||
{
|
||||
okBtn->m_properties[PROP_ID] = "cannot_start";
|
||||
okBtn->setText(_("Sorry, no tracks available"));
|
||||
}
|
||||
else if (gp_ok)
|
||||
{
|
||||
okBtn->m_properties[PROP_ID] = "start";
|
||||
okBtn->setText(_("Start Grand Prix"));
|
||||
okBtn->m_properties[PROP_ID] = "start";
|
||||
okBtn->setText(_("Start Grand Prix"));
|
||||
|
||||
continueBtn->m_properties[PROP_ID] = "continue";
|
||||
continueBtn->setText(_("Continue"));
|
||||
}
|
||||
else
|
||||
{
|
||||
okBtn->m_properties[PROP_ID] = "cannot_start";
|
||||
okBtn->setText(_("This Grand Prix is broken!"));
|
||||
okBtn->setBadge(BAD_BADGE);
|
||||
}
|
||||
continueBtn->m_properties[PROP_ID] = "continue";
|
||||
continueBtn->setText(_("Continue"));
|
||||
|
||||
if (saved_gp && gp_ok)
|
||||
if (saved_gp)
|
||||
{
|
||||
continueBtn->m_x = m_area.getWidth()/2 + 110;
|
||||
continueBtn->m_y = y2;
|
||||
continueBtn->m_y = m_lower_bound;
|
||||
continueBtn->m_w = 200;
|
||||
continueBtn->m_h = m_area.getHeight() - y2 - 15;
|
||||
continueBtn->m_h = m_area.getHeight() - m_lower_bound - 15;
|
||||
continueBtn->setParent(m_irrlicht_window);
|
||||
m_widgets.push_back(continueBtn);
|
||||
continueBtn->add();
|
||||
@ -185,9 +233,9 @@ GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const floa
|
||||
okBtn->m_x = m_area.getWidth()/2 - 200;
|
||||
}
|
||||
|
||||
okBtn->m_y = y2;
|
||||
okBtn->m_y = m_lower_bound;
|
||||
okBtn->m_w = 400;
|
||||
okBtn->m_h = m_area.getHeight() - y2 - 15;
|
||||
okBtn->m_h = m_area.getHeight() - m_lower_bound - 15;
|
||||
okBtn->setParent(m_irrlicht_window);
|
||||
m_widgets.push_back(okBtn);
|
||||
okBtn->add();
|
||||
@ -195,87 +243,57 @@ GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const floa
|
||||
okBtn->getIrrlichtElement()->setTabGroup(false);
|
||||
|
||||
okBtn->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
||||
GPInfoDialog::~GPInfoDialog()
|
||||
{
|
||||
// Place focus back on selected GP, in case the dialog was cancelled and we're back to
|
||||
// the track selection screen after
|
||||
Screen* curr_screen = GUIEngine::getCurrentScreen();
|
||||
if (curr_screen->getName() == "tracks.stkgui")
|
||||
{
|
||||
((TracksScreen*)curr_screen)->setFocusOnGP(m_gp_ident);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GPInfoDialog::onEnterPressedInternal()
|
||||
{
|
||||
// Save the gp identifier, since dismiss will delete this object.
|
||||
std::string gp_id = m_gp_ident;
|
||||
// Save the GP id because dismiss() will destroy this instance
|
||||
std::string gp_id = m_gp->getId();
|
||||
ModalDialog::dismiss();
|
||||
// Disable accidentally unlocking of a challenge
|
||||
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
|
||||
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GUIEngine::EventPropagation GPInfoDialog::processEvent(const std::string& eventSource)
|
||||
{
|
||||
if (eventSource == "start")
|
||||
if (eventSource == "start" || eventSource == "continue")
|
||||
{
|
||||
// Save GP identifier, since dismiss will delete this object.
|
||||
std::string gp_id = m_gp_ident;
|
||||
std::string gp_id = m_gp->getId();
|
||||
ModalDialog::dismiss();
|
||||
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
|
||||
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false,
|
||||
(eventSource == "continue"));
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
if (eventSource == "continue")
|
||||
{
|
||||
// Save GP identifier, since dismiss will delete this object.
|
||||
std::string gp_id = m_gp_ident;
|
||||
ModalDialog::dismiss();
|
||||
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, true);
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
else if (eventSource == "cannot_start")
|
||||
{
|
||||
sfx_manager->quickSound( "anvil" );
|
||||
}
|
||||
|
||||
return GUIEngine::EVENT_LET;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GPInfoDialog::onUpdate(float dt)
|
||||
{
|
||||
const int frameBefore = (int)(m_curr_time / 1.5f);
|
||||
if (dt == 0)
|
||||
return; // if nothing changed, return right now
|
||||
|
||||
m_curr_time += dt;
|
||||
int frameAfter = (int)(m_curr_time / 1.5f);
|
||||
|
||||
if (frameAfter == frameBefore) return; // if nothing changed, return right now
|
||||
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_gp_ident);
|
||||
assert(gp != NULL);
|
||||
const std::vector<std::string> tracks = gp->getTrackNames();
|
||||
const std::vector<std::string> tracks = m_gp->getTrackNames();
|
||||
if (frameAfter >= (int)tracks.size())
|
||||
{
|
||||
frameAfter = 0;
|
||||
m_curr_time = 0;
|
||||
}
|
||||
|
||||
Track* track = (tracks.size() == 0 ? NULL :
|
||||
track_manager->getTrack(tracks[frameAfter]));
|
||||
std::string fn = track ? track->getScreenshotFile()
|
||||
: file_manager->getAsset(FileManager::GUI, "main_help.png");
|
||||
m_screenshot_widget->setImage(fn.c_str(), IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
Track* track = track_manager->getTrack(tracks[frameAfter]);
|
||||
std::string file = track->getScreenshotFile();
|
||||
typedef GUIEngine::IconButtonWidget Icon;
|
||||
m_screenshot_widget->setImage(file.c_str(), Icon::ICON_PATH_TYPE_ABSOLUTE);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
@ -20,6 +20,10 @@
|
||||
#define HEADER_GP_INFO_DIALOG_HPP
|
||||
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
// Don't include grand_prix_data.hpp here or the compilation will fail
|
||||
|
||||
|
||||
class GrandPrixData;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
@ -32,23 +36,46 @@ namespace GUIEngine
|
||||
*/
|
||||
class GPInfoDialog : public GUIEngine::ModalDialog
|
||||
{
|
||||
std::string m_gp_ident;
|
||||
protected: // Necessary for RandomGPInfoDialog
|
||||
GUIEngine::IconButtonWidget* m_screenshot_widget;
|
||||
|
||||
float m_curr_time;
|
||||
|
||||
GrandPrixData* m_gp;
|
||||
|
||||
/** height of the separator over the body */
|
||||
int m_over_body;
|
||||
/** height of the separator under the titlebar, which is equal to
|
||||
* m_over_body in a normal GPInfoDialo and lower in RandomGPInfoDialog. */
|
||||
int m_under_title;
|
||||
/** height of the seperator over the buttons */
|
||||
int m_lower_bound;
|
||||
|
||||
void addTitle();
|
||||
/** \brief display all the tracks according to the current gp
|
||||
* For a normal gp info dialog, it just creates a label for every track.
|
||||
* But with a random gp info dialog, it tries to reuse as many
|
||||
* labels as possible by just changing their text. */
|
||||
void addTracks();
|
||||
void addScreenshot();
|
||||
/** display a ok-button and eventually a continue-button */
|
||||
void addButtons();
|
||||
|
||||
/** only used for track_screen.cpp */
|
||||
GPInfoDialog() : ModalDialog(PERCENT_WIDTH, PERCENT_HEIGHT) {}
|
||||
|
||||
private:
|
||||
static const float PERCENT_WIDTH;
|
||||
static const float PERCENT_HEIGHT;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a modal dialog with given percentage of screen width and height
|
||||
*/
|
||||
GPInfoDialog(const std::string& gpIdent, const float percentWidth, const float percentHeight);
|
||||
GPInfoDialog(const std::string& gpIdent);
|
||||
/** Places the focus back on the selected GP, in the case that the dialog
|
||||
* was cancelled and we're returning to the track selection screen */
|
||||
virtual ~GPInfoDialog();
|
||||
|
||||
|
||||
void onEnterPressedInternal();
|
||||
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
|
||||
|
||||
virtual void onUpdate(float dt);
|
||||
|
||||
virtual void onUpdate(float dt);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
195
src/states_screens/dialogs/random_gp_dialog.cpp
Normal file
195
src/states_screens/dialogs/random_gp_dialog.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 konstin
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/widgets/icon_button_widget.hpp"
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/dialogs/random_gp_dialog.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIStaticText.h>
|
||||
|
||||
using irr::core::stringc;
|
||||
using irr::core::stringw;
|
||||
using irr::gui::IGUIStaticText;
|
||||
|
||||
typedef GUIEngine::SpinnerWidget Spinner;
|
||||
|
||||
RandomGPInfoDialog::RandomGPInfoDialog()
|
||||
{
|
||||
// Defaults - loading selection from last time frrom a file would be better
|
||||
m_number_of_tracks = 2; // We can assume that there are at least 2 standard tracks
|
||||
m_trackgroup = "standard";
|
||||
m_use_reverse = NO_REVERSE;
|
||||
|
||||
doInit();
|
||||
m_curr_time = 0.0f;
|
||||
|
||||
m_under_title = m_area.getHeight()/7;
|
||||
m_over_body = m_area.getHeight()/7 + SPINNER_HEIGHT + 10; // 10px space
|
||||
m_lower_bound = m_area.getHeight()*6/7;
|
||||
|
||||
// The GP manager is be used to make the GP live longer than this dialog
|
||||
if (grand_prix_manager->m_random_gp)
|
||||
{
|
||||
delete grand_prix_manager->m_random_gp;
|
||||
grand_prix_manager->m_random_gp = NULL;
|
||||
}
|
||||
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
|
||||
grand_prix_manager->m_random_gp = m_gp;
|
||||
|
||||
addTitle();
|
||||
addSpinners();
|
||||
addTracks();
|
||||
addScreenshot();
|
||||
addButtons();
|
||||
addRestartButton();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void RandomGPInfoDialog::addSpinners()
|
||||
{
|
||||
const int trackgroup_width = 200, laps_with = 150, reverse_width = 200;
|
||||
const int left = (m_area.getWidth() - trackgroup_width - 150 - 250)/2;
|
||||
|
||||
// Trackgroup chooser
|
||||
Spinner* spinner = new Spinner(false);
|
||||
spinner->m_properties[GUIEngine::PROP_ID] = "Trackgroup";
|
||||
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
|
||||
spinner->setParent(m_irrlicht_window);
|
||||
m_widgets.push_back(spinner);
|
||||
spinner->add();
|
||||
spinner->move(left, m_under_title, trackgroup_width, SPINNER_HEIGHT);
|
||||
// Fill it with all the track group names
|
||||
spinner->addLabel("all");
|
||||
int index_standard;
|
||||
const std::vector<std::string>& groups = track_manager->getAllTrackGroups();
|
||||
for (unsigned int i = 0; i < groups.size(); i++)
|
||||
{
|
||||
// FIXME: The NULL check is necessary until #1348 on github is fixed
|
||||
if (groups[i].c_str() != NULL)
|
||||
{
|
||||
spinner->addLabel(stringw(groups[i].c_str()));
|
||||
if(groups[i] == "standard")
|
||||
index_standard = i+1;
|
||||
}
|
||||
}
|
||||
// The value can only be set here because SpinnerWidget resets the value
|
||||
// every time a label is added
|
||||
spinner->setValue(index_standard);
|
||||
|
||||
// Number of laps chooser
|
||||
spinner = new Spinner(false);
|
||||
spinner->setValue(m_number_of_tracks);
|
||||
spinner->setMin(1);
|
||||
spinner->setMax(track_manager->getTracksInGroup("standard").size());
|
||||
spinner->setParent(m_irrlicht_window);
|
||||
spinner->m_properties[GUIEngine::PROP_ID] = "Number of tracks";
|
||||
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
|
||||
m_widgets.push_back(spinner);
|
||||
spinner->add();
|
||||
spinner->move(left + trackgroup_width + 10, m_under_title, laps_with, SPINNER_HEIGHT);
|
||||
|
||||
// reverse choose
|
||||
spinner = new Spinner(false);
|
||||
spinner->setParent(m_irrlicht_window);
|
||||
spinner->m_properties[GUIEngine::PROP_ID] = "reverse";
|
||||
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
|
||||
m_widgets.push_back(spinner);
|
||||
spinner->add();
|
||||
spinner->move(left + trackgroup_width + laps_with + 10, m_under_title, reverse_width, SPINNER_HEIGHT);
|
||||
spinner->addLabel("no reverse");
|
||||
spinner->addLabel("all reverse");
|
||||
spinner->addLabel("mixed");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void RandomGPInfoDialog::addRestartButton()
|
||||
{
|
||||
GUIEngine::IconButtonWidget* button = new GUIEngine::IconButtonWidget();
|
||||
button->setImage("gui/restart.png");
|
||||
button->setParent(m_irrlicht_window);
|
||||
button->m_properties[GUIEngine::PROP_ID] = "reload";
|
||||
m_widgets.push_back(button);
|
||||
button->add();
|
||||
button->move(m_area.getWidth() - 20 - 32, 20, 32, 32);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GUIEngine::EventPropagation RandomGPInfoDialog::processEvent(
|
||||
const std::string& eventSource)
|
||||
{
|
||||
if (eventSource == "start")
|
||||
{
|
||||
ModalDialog::dismiss();
|
||||
race_manager->startGP(grand_prix_manager->m_random_gp, false, false);
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
else if (eventSource == "Number of tracks")
|
||||
{
|
||||
// The old gp can be reused because there's only track deletion/adding
|
||||
m_number_of_tracks = getWidget<Spinner>("Number of tracks")->getValue();
|
||||
m_gp->changeTrackNumber(m_number_of_tracks, m_trackgroup);
|
||||
addTracks();
|
||||
}
|
||||
else if (eventSource == "Trackgroup")
|
||||
{
|
||||
Spinner* t = getWidget<Spinner>("Trackgroup");
|
||||
Spinner* s = getWidget<Spinner>("Number of tracks");
|
||||
|
||||
m_trackgroup = stringc(t->getStringValue()).c_str();
|
||||
|
||||
// Update the maximum for the number of tracks since it's depending on
|
||||
// the current track. The current value in the Number-of-tracks-spinner
|
||||
// has to be updated, since otherwise the displayed (and used) value
|
||||
// can be bigger than the maximum. (Might be a TODO to fix this)
|
||||
unsigned int max = (m_trackgroup == "all") ?
|
||||
track_manager->getNumberOfTracks() :
|
||||
track_manager->getTracksInGroup(m_trackgroup).size();
|
||||
m_number_of_tracks = std::min(max, m_number_of_tracks);
|
||||
s->setMax(max);
|
||||
if (s->getValue() > (signed)max)
|
||||
s->setValue(max);
|
||||
|
||||
delete m_gp;
|
||||
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
|
||||
grand_prix_manager->m_random_gp = m_gp;
|
||||
addTracks();
|
||||
}
|
||||
else if (eventSource == "reverse")
|
||||
{
|
||||
Spinner* r = getWidget<Spinner>("reverse");
|
||||
m_use_reverse = static_cast<REVERSED>(r->getValue());
|
||||
m_gp->changeReverse(m_use_reverse);
|
||||
}
|
||||
else if (eventSource == "reload")
|
||||
{
|
||||
delete m_gp;
|
||||
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
|
||||
grand_prix_manager->m_random_gp = m_gp;
|
||||
addTracks();
|
||||
}
|
||||
|
||||
return GUIEngine::EVENT_LET;
|
||||
}
|
||||
|
53
src/states_screens/dialogs/random_gp_dialog.hpp
Normal file
53
src/states_screens/dialogs/random_gp_dialog.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 konstin
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_RANDOM_GP_INFO_DIALOG_HPP
|
||||
#define HEADER_RANDOM_GP_INFO_DIALOG_HPP
|
||||
|
||||
#include "states_screens/dialogs/gp_info_dialog.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class RandomGPInfoDialog : public GPInfoDialog
|
||||
{
|
||||
public:
|
||||
enum REVERSED
|
||||
{
|
||||
NO_REVERSE = 0,
|
||||
ALL_REVERSE = 1,
|
||||
MIXED = 2
|
||||
};
|
||||
private:
|
||||
unsigned int m_number_of_tracks;
|
||||
std::string m_trackgroup;
|
||||
REVERSED m_use_reverse;
|
||||
|
||||
public:
|
||||
static const int SPINNER_HEIGHT = 40;
|
||||
|
||||
RandomGPInfoDialog();
|
||||
|
||||
/** Adds a SpinnerWidgets to choose the track groups, one to choose the
|
||||
* number of tracks and one to choose if the tracks should be raced in
|
||||
* reverse. The Spinners are centered. */
|
||||
void addSpinners();
|
||||
void addRestartButton();
|
||||
|
||||
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
|
||||
};
|
||||
|
||||
#endif
|
@ -232,6 +232,31 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
||||
m_player_ident_spinner->m_w = player_name_w;
|
||||
m_player_ident_spinner->m_h = player_name_h;
|
||||
|
||||
// ---- KartStatsWidget
|
||||
m_kart_stats = NULL;
|
||||
|
||||
// area for the stats widget
|
||||
core::recti statsArea;
|
||||
if (!parent->m_multiplayer)
|
||||
{
|
||||
statsArea = core::recti(m_kart_stats_x,
|
||||
m_kart_stats_y,
|
||||
m_kart_stats_x + m_kart_stats_w,
|
||||
m_kart_stats_y + m_kart_stats_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
statsArea = core::recti(m_x , m_y + m_h/2,
|
||||
m_x + m_w, m_y + m_h);
|
||||
}
|
||||
|
||||
|
||||
m_kart_stats = new GUIEngine::KartStatsWidget(statsArea, player_id, kart_group,
|
||||
m_parent_screen->m_multiplayer);
|
||||
m_kart_stats->m_properties[PROP_ID] =
|
||||
StringUtils::insertValues("@p%i_stats", m_player_id);
|
||||
m_children.push_back(m_kart_stats);
|
||||
|
||||
if (parent->m_multiplayer && associated_player)
|
||||
{
|
||||
if (associated_player->getDevice()->getType() == DT_KEYBOARD)
|
||||
@ -272,8 +297,6 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
||||
|
||||
//m_player_ident_spinner->m_event_handler = this;
|
||||
m_children.push_back(m_player_ident_spinner);
|
||||
|
||||
|
||||
|
||||
// ----- Kart model view
|
||||
m_model_view = new ModelViewWidget();
|
||||
@ -347,7 +370,7 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
||||
m_model_view->setRotateContinuously( 35.0f );
|
||||
|
||||
// ---- Kart name label
|
||||
m_kart_name = new LabelWidget();
|
||||
m_kart_name = new LabelWidget(true, true);
|
||||
m_kart_name->setText(props->getName(), false);
|
||||
m_kart_name->m_properties[PROP_TEXT_ALIGN] = "center";
|
||||
m_kart_name->m_properties[PROP_ID] =
|
||||
@ -356,7 +379,6 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
||||
m_kart_name->m_y = kart_name_y;
|
||||
m_kart_name->m_w = kart_name_w;
|
||||
m_kart_name->m_h = kart_name_h;
|
||||
//m_kart_name->setParent(this);
|
||||
m_children.push_back(m_kart_name);
|
||||
} // PlayerKartWidget
|
||||
// ------------------------------------------------------------------------
|
||||
@ -472,7 +494,7 @@ void PlayerKartWidget::add()
|
||||
m_player_ident_spinner->add();
|
||||
m_player_ident_spinner->getIrrlichtElement()->setTabStop(false);
|
||||
m_player_ident_spinner->setListener(this);
|
||||
|
||||
m_kart_stats->add();
|
||||
m_model_view->add();
|
||||
m_kart_name->add();
|
||||
|
||||
@ -660,11 +682,25 @@ void PlayerKartWidget::onUpdate(float delta)
|
||||
core::recti(core::position2di(player_name_x, player_name_y),
|
||||
core::dimension2di(player_name_w, player_name_h)) );
|
||||
}
|
||||
if (!m_parent_screen->m_multiplayer)
|
||||
{
|
||||
m_kart_stats->move(m_kart_stats_x,
|
||||
m_kart_stats_y,
|
||||
m_kart_stats_w,
|
||||
m_kart_stats_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kart_stats->move(m_x, m_y + m_h/2,
|
||||
m_w, m_h/2);
|
||||
}
|
||||
|
||||
|
||||
m_model_view->move(model_x,
|
||||
model_y,
|
||||
model_w,
|
||||
model_h);
|
||||
|
||||
m_kart_name->move(kart_name_x,
|
||||
kart_name_y,
|
||||
kart_name_w,
|
||||
@ -757,15 +793,41 @@ void PlayerKartWidget::setSize(const int x, const int y, const int w, const int
|
||||
player_name_x = x + w/2 - player_name_w/2;
|
||||
player_name_y = y + player_id_h;
|
||||
|
||||
const int modelMaxHeight = h - kart_name_h - player_name_h
|
||||
- player_id_h;
|
||||
const int modelMaxWidth = w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
const int modelY = y + player_name_h + player_id_h;
|
||||
model_x = x + w/2 - (int)(bestSize/2);
|
||||
model_y = modelY + modelMaxHeight/2 - bestSize/2;
|
||||
model_w = (int)(bestSize);
|
||||
model_h = bestSize;
|
||||
if (m_parent_screen->m_multiplayer)
|
||||
{
|
||||
const int modelMaxHeight = (h - kart_name_h - player_name_h
|
||||
- player_id_h)/2;
|
||||
const int modelMaxWidth = w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
model_x = x + w/2 - (int)(bestSize/2);
|
||||
model_y = y + player_name_h + player_id_h;
|
||||
model_w = (int)(bestSize);
|
||||
model_h = bestSize;
|
||||
|
||||
m_kart_stats_w = model_w;
|
||||
m_kart_stats_h = model_h;
|
||||
m_kart_stats_x = x + w/2 - (int)(bestSize/2);
|
||||
m_kart_stats_y = model_y + model_h;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
const int modelMaxHeight = h - kart_name_h - player_name_h
|
||||
- player_id_h;
|
||||
const int modelMaxWidth = w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
const int modelY = y + player_name_h + player_id_h;
|
||||
model_x = x + w/4 - (int)(bestSize/2);
|
||||
model_y = modelY + modelMaxHeight/2 - bestSize/2;
|
||||
model_w = (int)(bestSize);
|
||||
model_h = bestSize;
|
||||
|
||||
m_kart_stats_w = w/2;
|
||||
m_kart_stats_h = h;
|
||||
m_kart_stats_x = x + w/2;
|
||||
m_kart_stats_y = y;
|
||||
}
|
||||
|
||||
kart_name_x = x;
|
||||
kart_name_y = y + h - kart_name_h;
|
||||
@ -850,8 +912,8 @@ void KartHoverListener::onSelectionChanged(DynamicRibbonWidget* theWidget,
|
||||
}
|
||||
|
||||
m_parent->updateKartWidgetModel(playerID, selectionID, selectionText);
|
||||
|
||||
m_parent->m_kart_widgets[playerID].setKartInternalName(selectionID);
|
||||
m_parent->updateKartStats(playerID, selectionID);
|
||||
m_parent->validateKartChoices();
|
||||
} // onSelectionChanged
|
||||
|
||||
@ -1454,6 +1516,23 @@ void KartSelectionScreen::playerConfirm(const int playerID)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void KartSelectionScreen::updateKartStats(uint8_t widget_id,
|
||||
const std::string& selection)
|
||||
{
|
||||
KartStatsWidget* w = m_kart_widgets[widget_id].m_kart_stats;
|
||||
assert(w != NULL);
|
||||
|
||||
const KartProperties *kp =
|
||||
kart_properties_manager->getKart(selection);
|
||||
if (kp != NULL)
|
||||
{
|
||||
w->setValue(KartStatsWidget::SKILL_MASS, (int)(kp->getMass()/5));
|
||||
w->setValue(KartStatsWidget::SKILL_SPEED, (int)((kp->getAbsMaxSpeed()-20)*9));
|
||||
w->setValue(KartStatsWidget::SKILL_POWER, (int)(kp->getAvgPower()));
|
||||
w->update(0);
|
||||
}
|
||||
}
|
||||
|
||||
void KartSelectionScreen::updateKartWidgetModel(uint8_t widget_id,
|
||||
const std::string& selection,
|
||||
const irr::core::stringw& selectionText)
|
||||
@ -1523,6 +1602,11 @@ void KartSelectionScreen::updateKartWidgetModel(uint8_t widget_id,
|
||||
kart_model.getWheelGraphicsPosition(2) );
|
||||
w3->addModel( kart_model.getWheelModel(3),
|
||||
kart_model.getWheelGraphicsPosition(3) );
|
||||
for (size_t i = 0; i < kart_model.getSpeedWeightedObjectsCount(); i++)
|
||||
{
|
||||
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject(i);
|
||||
w3->addModel(obj.m_model, obj.m_position);
|
||||
}
|
||||
w3->update(0);
|
||||
|
||||
m_kart_widgets[widget_id].m_kart_name
|
||||
|
@ -24,7 +24,9 @@
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/model_view_widget.hpp"
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include "guiengine/widgets/progress_bar_widget.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "guiengine/widgets/kart_stats_widget.hpp"
|
||||
|
||||
#include <IGUIImage.h>
|
||||
|
||||
@ -109,6 +111,10 @@ protected:
|
||||
void setKartsFromCurrentGroup();
|
||||
|
||||
virtual void playerConfirm(const int playerID);
|
||||
|
||||
void updateKartStats(uint8_t widget_id,
|
||||
const std::string& selection);
|
||||
|
||||
/** updates model of a kart widget, to have the good selection when the user validates */
|
||||
void updateKartWidgetModel(uint8_t widget_id,
|
||||
const std::string& selection,
|
||||
@ -236,6 +242,7 @@ class PlayerKartWidget : public GUIEngine::Widget,
|
||||
int player_name_x, player_name_y, player_name_w, player_name_h;
|
||||
int model_x, model_y, model_w, model_h;
|
||||
int kart_name_x, kart_name_y, kart_name_w, kart_name_h;
|
||||
int m_kart_stats_x, m_kart_stats_y, m_kart_stats_w, m_kart_stats_h;
|
||||
|
||||
/** A reserved ID for this widget if any, -1 otherwise. (If no ID is
|
||||
* reserved, widget will not be in the regular tabbing order */
|
||||
@ -267,6 +274,7 @@ public:
|
||||
|
||||
/** Sub-widgets created by this widget */
|
||||
PlayerNameSpinner* m_player_ident_spinner;
|
||||
GUIEngine::KartStatsWidget* m_kart_stats;
|
||||
GUIEngine::ModelViewWidget* m_model_view;
|
||||
GUIEngine::LabelWidget* m_kart_name;
|
||||
|
||||
|
@ -80,6 +80,14 @@ void MainMenuScreen::loadedFromFile()
|
||||
{
|
||||
LabelWidget* w = getWidget<LabelWidget>("info_addons");
|
||||
w->setScrollSpeed(15);
|
||||
|
||||
#if DEBUG_MENU_ITEM != 1
|
||||
RibbonWidget* rw = getWidget<RibbonWidget>("menu_bottomrow");
|
||||
rw->removeChildNamed("test_gpwin");
|
||||
rw->removeChildNamed("test_gplose");
|
||||
rw->removeChildNamed("test_unlocked");
|
||||
rw->removeChildNamed("test_unlocked2");
|
||||
#endif
|
||||
} // loadedFromFile
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -230,14 +238,12 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
*/
|
||||
|
||||
#if DEBUG_MENU_ITEM
|
||||
if (selection == "gpEditor")
|
||||
if (selection == "test_gpwin")
|
||||
{
|
||||
// The DEBUG item
|
||||
StoryModeStatus* sms = PlayerManager::getCurrentPlayer()->getStoryModeStatus();
|
||||
sms->unlockFeature(const_cast<ChallengeStatus*>(sms->getChallengeStatus("gp1")),
|
||||
RaceManager::DIFFICULTY_HARD);
|
||||
|
||||
// GP WIN
|
||||
StateManager::get()->enterGameState();
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
|
||||
race_manager->setNumKarts(0);
|
||||
@ -248,9 +254,9 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
StateManager::get()->pushScreen(scene);
|
||||
const std::string winners[] = { "elephpant", "nolok", "pidgin" };
|
||||
scene->setKarts(winners);
|
||||
|
||||
// GP Lose
|
||||
/*
|
||||
}
|
||||
else if (selection == "test_gplose")
|
||||
{
|
||||
StateManager::get()->enterGameState();
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
|
||||
race_manager->setNumKarts(0);
|
||||
@ -265,10 +271,13 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
//losers.push_back("wilber");
|
||||
//losers.push_back("tux");
|
||||
scene->setKarts(losers);
|
||||
*/
|
||||
|
||||
/*
|
||||
// FEATURE UNLOCKED
|
||||
}
|
||||
else if (selection == "test_unlocked" || selection == "test_unlocked2")
|
||||
{
|
||||
StoryModeStatus* sms = PlayerManager::getCurrentPlayer()->getStoryModeStatus();
|
||||
sms->unlockFeature(const_cast<ChallengeStatus*>(sms->getChallengeStatus("gp1")),
|
||||
RaceManager::DIFFICULTY_HARD);
|
||||
|
||||
StateManager::get()->enterGameState();
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
|
||||
race_manager->setNumKarts(0);
|
||||
@ -284,12 +293,8 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
((CutsceneWorld*)World::getWorld())->setParts(parts);
|
||||
|
||||
scene->addTrophy(RaceManager::DIFFICULTY_EASY);
|
||||
//StateManager::get()->pushScreen(scene);
|
||||
|
||||
static int i = 1;
|
||||
i++;
|
||||
|
||||
if (i % 2 == 0)
|
||||
if (selection == "test_unlocked")
|
||||
{
|
||||
// the passed kart will not be modified, that's why I allow myself
|
||||
// to use const_cast
|
||||
@ -299,9 +304,10 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
),
|
||||
L"Unlocked"
|
||||
);
|
||||
scene->addUnlockedTrack(track_manager->getTrack("lighthouse"));
|
||||
StateManager::get()->pushScreen(scene);
|
||||
}
|
||||
else if (i % 2 == 1)
|
||||
else if (selection == "test_unlocked2")
|
||||
{
|
||||
std::vector<video::ITexture*> textures;
|
||||
textures.push_back(irr_driver->getTexture(
|
||||
@ -321,7 +327,6 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
|
||||
StateManager::get()->pushScreen(scene);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -146,6 +146,7 @@ void NetworkKartSelectionScreen::playerSelected(uint8_t race_id, std::string kar
|
||||
assert(widget_id>=0 && widget_id < m_kart_widgets.size());
|
||||
|
||||
KartSelectionScreen::updateKartWidgetModel(widget_id, kart_name, irr::core::stringw(kart_name.c_str()));
|
||||
KartSelectionScreen::updateKartStats(widget_id, kart_name);
|
||||
m_kart_widgets[widget_id].setKartInternalName(kart_name);
|
||||
m_kart_widgets[widget_id].markAsReady(); // mark player ready
|
||||
}
|
||||
|
@ -342,19 +342,28 @@ void RaceGUI::drawGlobalMiniMap()
|
||||
// arenas currently don't have a map.
|
||||
if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
|
||||
|
||||
const video::ITexture *mini_map = world->getTrack()->getMiniMap();
|
||||
const video::ITexture *old_rtt_mini_map = world->getTrack()->getOldRttMiniMap();
|
||||
const FrameBuffer* new_rtt_mini_map = world->getTrack()->getNewRttMiniMap();
|
||||
|
||||
int upper_y = UserConfigParams::m_height - m_map_bottom - m_map_height;
|
||||
int lower_y = UserConfigParams::m_height - m_map_bottom;
|
||||
|
||||
if (mini_map != NULL)
|
||||
core::rect<s32> dest(m_map_left, upper_y,
|
||||
m_map_left + m_map_width, lower_y);
|
||||
|
||||
if (old_rtt_mini_map != NULL)
|
||||
{
|
||||
core::rect<s32> dest(m_map_left, upper_y,
|
||||
m_map_left + m_map_width, lower_y);
|
||||
core::rect<s32> source(core::position2di(0, 0),
|
||||
mini_map->getOriginalSize());
|
||||
draw2DImage(mini_map, dest, source,
|
||||
NULL, NULL, true);
|
||||
old_rtt_mini_map->getOriginalSize());
|
||||
draw2DImage(old_rtt_mini_map, dest, source,
|
||||
NULL, NULL, true);
|
||||
}
|
||||
else if (new_rtt_mini_map != NULL)
|
||||
{
|
||||
core::rect<s32> source(0, 0, new_rtt_mini_map->getWidth(), new_rtt_mini_map->getHeight());
|
||||
draw2DImageFromRTT(new_rtt_mini_map->getRTT()[0],
|
||||
new_rtt_mini_map->getWidth(), new_rtt_mini_map->getHeight(),
|
||||
dest, source, NULL, video::SColor(127, 255, 255, 255), true);
|
||||
}
|
||||
|
||||
for(unsigned int i=0; i<world->getNumKarts(); i++)
|
||||
|
@ -321,17 +321,26 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
}
|
||||
|
||||
|
||||
const video::ITexture *mini_map = world->getTrack()->getMiniMap();
|
||||
const video::ITexture *old_rtt_mini_map = world->getTrack()->getOldRttMiniMap();
|
||||
const FrameBuffer* new_rtt_mini_map = world->getTrack()->getNewRttMiniMap();
|
||||
|
||||
int upper_y = m_map_bottom - m_map_height;
|
||||
int lower_y = m_map_bottom;
|
||||
|
||||
if (mini_map != NULL)
|
||||
core::rect<s32> dest(m_map_left, upper_y,
|
||||
m_map_left + m_map_width, lower_y);
|
||||
|
||||
if (old_rtt_mini_map != NULL)
|
||||
{
|
||||
core::rect<s32> dest(m_map_left, upper_y,
|
||||
m_map_left + m_map_width, lower_y);
|
||||
core::rect<s32> source(core::position2di(0, 0), mini_map->getOriginalSize());
|
||||
draw2DImage(mini_map, dest, source, 0, 0, true);
|
||||
core::rect<s32> source(core::position2di(0, 0), old_rtt_mini_map->getOriginalSize());
|
||||
draw2DImage(old_rtt_mini_map, dest, source, 0, 0, true);
|
||||
}
|
||||
else if (new_rtt_mini_map != NULL)
|
||||
{
|
||||
core::rect<s32> source(0, 0, new_rtt_mini_map->getWidth(), new_rtt_mini_map->getHeight());
|
||||
draw2DImageFromRTT(new_rtt_mini_map->getRTT()[0],
|
||||
new_rtt_mini_map->getWidth(), new_rtt_mini_map->getHeight(),
|
||||
dest, source, NULL, video::SColor(127, 255, 255, 255), true);
|
||||
}
|
||||
|
||||
Vec3 kart_xyz;
|
||||
|
@ -92,7 +92,7 @@ void RaceResultGUI::init()
|
||||
|
||||
// Calculate screenshot scrolling parameters
|
||||
const std::vector<std::string> tracks =
|
||||
race_manager->getGrandPrix()->getTrackNames();
|
||||
race_manager->getGrandPrix().getTrackNames();
|
||||
int n_tracks = tracks.size();
|
||||
int currentTrack = race_manager->getTrackNumber();
|
||||
m_start_track = currentTrack;
|
||||
@ -208,7 +208,7 @@ void RaceResultGUI::enableAllButtons()
|
||||
void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
const std::string& name, const int playerID)
|
||||
{
|
||||
int n_tracks = race_manager->getGrandPrix()->getNumberOfTracks();
|
||||
int n_tracks = race_manager->getGrandPrix().getNumberOfTracks();
|
||||
if (name == "up_button" && n_tracks > m_max_tracks && m_start_track > 0)
|
||||
{
|
||||
m_start_track--;
|
||||
@ -1121,7 +1121,7 @@ void RaceResultGUI::enableGPProgress()
|
||||
status_label->m_h = font_height;
|
||||
status_label->add();
|
||||
status_label->setText(_("Track %i/%i", currentTrack + 1,
|
||||
race_manager->getGrandPrix()->getNumberOfTracks()), true);
|
||||
race_manager->getGrandPrix().getNumberOfTracks()), true);
|
||||
addGPProgressWidget(status_label);
|
||||
y = (status_label->m_y + status_label->m_h + 5);
|
||||
|
||||
@ -1316,7 +1316,7 @@ void RaceResultGUI::displayHighScores()
|
||||
void RaceResultGUI::displayScreenShots()
|
||||
{
|
||||
const std::vector<std::string> tracks =
|
||||
race_manager->getGrandPrix()->getTrackNames();
|
||||
race_manager->getGrandPrix().getTrackNames();
|
||||
int currentTrack = race_manager->getTrackNumber();
|
||||
|
||||
int n_sshot = 1;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/dialogs/gp_info_dialog.hpp"
|
||||
#include "states_screens/dialogs/random_gp_dialog.hpp"
|
||||
#include "states_screens/dialogs/track_info_dialog.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
@ -121,9 +122,16 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
gps_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
||||
|
||||
if (selection == "locked")
|
||||
{
|
||||
unlock_manager->playLockSound();
|
||||
}
|
||||
else
|
||||
new GPInfoDialog(selection, 0.8f, 0.7f);
|
||||
{
|
||||
if (selection == "Random Grand Prix")
|
||||
new RandomGPInfoDialog();
|
||||
else
|
||||
new GPInfoDialog(selection);
|
||||
}
|
||||
}
|
||||
else if (name == "trackgroups")
|
||||
{
|
||||
@ -214,12 +222,13 @@ void TracksScreen::init()
|
||||
}
|
||||
}
|
||||
|
||||
/*// Random GP - not finished yet
|
||||
// Random GP
|
||||
std::vector<std::string> screenshots;
|
||||
screenshots.push_back("gui/main_help.png");
|
||||
gps_widget->addAnimatedItem(translations->fribidize("Random"), "Random",
|
||||
screenshots.push_back(file_manager->getAsset(FileManager::GUI, "main_help.png"));
|
||||
gps_widget->addAnimatedItem(translations->fribidize("Random Grand Prix"),
|
||||
"Random Grand Prix",
|
||||
screenshots, 1.5f, 0,
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);*/
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
|
||||
gps_widget->updateItemDisplay();
|
||||
|
||||
|
@ -460,12 +460,12 @@ void QuadGraph::createMesh(bool show_invisible,
|
||||
// Set up the indices for the triangles
|
||||
// (note, afaik with opengl we could use quads directly, but the code
|
||||
// would not be portable to directx anymore).
|
||||
ind[6*i ] = 4*i; // First triangle: vertex 0, 1, 2
|
||||
ind[6*i ] = 4*i+2; // First triangle: vertex 0, 1, 2
|
||||
ind[6*i+1] = 4*i+1;
|
||||
ind[6*i+2] = 4*i+2;
|
||||
ind[6*i+3] = 4*i; // second triangle: vertex 0, 1, 3
|
||||
ind[6*i+2] = 4*i;
|
||||
ind[6*i+3] = 4*i+3; // second triangle: vertex 0, 1, 3
|
||||
ind[6*i+4] = 4*i+2;
|
||||
ind[6*i+5] = 4*i+3;
|
||||
ind[6*i+5] = 4*i;
|
||||
i++;
|
||||
} // for i=1; i<QuadSet::get()
|
||||
|
||||
@ -499,12 +499,12 @@ void QuadGraph::createMesh(bool show_invisible,
|
||||
lap_v[2].Pos = lap_v[1].Pos+core::vector3df(0, 0, 1);
|
||||
else
|
||||
lap_v[2].Pos = lap_v[1].Pos+dr*length/sqrt(lr2);
|
||||
lap_ind[0] = 0;
|
||||
lap_ind[0] = 2;
|
||||
lap_ind[1] = 1;
|
||||
lap_ind[2] = 2;
|
||||
lap_ind[3] = 0;
|
||||
lap_ind[2] = 0;
|
||||
lap_ind[3] = 3;
|
||||
lap_ind[4] = 2;
|
||||
lap_ind[5] = 3;
|
||||
lap_ind[5] = 0;
|
||||
// Set it a bit higher to avoid issued with z fighting,
|
||||
// i.e. part of the lap line might not be visible.
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
@ -1084,20 +1084,37 @@ int QuadGraph::findOutOfRoadSector(const Vec3& xyz,
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Takes a snapshot of the driveline quads so they can be used as minimap.
|
||||
*/
|
||||
video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &origdimension,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color)
|
||||
void QuadGraph::makeMiniMap(const core::dimension2du &dimension,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color,
|
||||
video::ITexture** oldRttMinimap,
|
||||
FrameBuffer** newRttMinimap)
|
||||
{
|
||||
const core::dimension2du dimension = origdimension * 2;
|
||||
const SColor oldClearColor = World::getWorld()->getClearColor();
|
||||
World::getWorld()->setClearbackBufferColor(SColor(0, 255, 255, 255));
|
||||
*oldRttMinimap = NULL;
|
||||
*newRttMinimap = NULL;
|
||||
|
||||
RTT* newRttProvider = NULL;
|
||||
IrrDriver::RTTProvider* oldRttProvider = NULL;
|
||||
if (irr_driver->isGLSL())
|
||||
{
|
||||
newRttProvider = new RTT(dimension.Width, dimension.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldRttProvider = new IrrDriver::RTTProvider(dimension, name, true);
|
||||
}
|
||||
|
||||
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 255, 255, 255));
|
||||
|
||||
IrrDriver::RTTProvider rttProvider(dimension, name, true);
|
||||
video::SColor red(128, 255, 0, 0);
|
||||
createMesh(/*show_invisible part of the track*/ false,
|
||||
/*enable_transparency*/ false,
|
||||
/*track_color*/ &fill_color,
|
||||
/*lap line color*/ &red );
|
||||
|
||||
m_node = irr_driver->getSceneManager()->addMeshSceneNode(m_mesh); // add Debug Mesh
|
||||
m_node = irr_driver->addMesh(m_mesh);
|
||||
#ifdef DEBUG
|
||||
m_node->setName("minimap-mesh");
|
||||
#endif
|
||||
@ -1145,32 +1162,54 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2du &origdimension,
|
||||
float range = (dx>dz) ? dx : dz;
|
||||
|
||||
core::matrix4 projection;
|
||||
projection.buildProjectionMatrixOrthoLH(range,
|
||||
range,
|
||||
projection.buildProjectionMatrixOrthoLH(range /* width */,
|
||||
range /* height */,
|
||||
-1, bb_max.getY()-bb_min.getY()+1);
|
||||
camera->setProjectionMatrix(projection, true);
|
||||
|
||||
irr_driver->suppressSkyBox();
|
||||
irr_driver->clearLights();
|
||||
|
||||
// Adjust Y position by +1 for max, -1 for min - this helps in case that
|
||||
// the maximum Y coordinate is negative (otherwise the minimap is mirrored)
|
||||
// and avoids problems for tracks which have a flat (max Y = min Y) minimap.
|
||||
camera->setPosition(core::vector3df(center.getX(), bb_max.getY()+1, center.getZ()));
|
||||
camera->setPosition(core::vector3df(center.getX(), bb_min.getY() + 1.0f, center.getZ()));
|
||||
//camera->setPosition(core::vector3df(center.getX() - 5.0f, bb_min.getY() - 1 - 5.0f, center.getZ() - 15.0f));
|
||||
camera->setUpVector(core::vector3df(0, 0, 1));
|
||||
camera->setTarget(core::vector3df(center.getX(),bb_min.getY()-1,center.getZ()));
|
||||
//camera->setAspectRatio(1.0f);
|
||||
camera->updateAbsolutePosition();
|
||||
|
||||
video::ITexture *texture = rttProvider.renderToTexture();
|
||||
video::ITexture* texture = NULL;
|
||||
FrameBuffer* frame_buffer = NULL;
|
||||
|
||||
if (irr_driver->isGLSL())
|
||||
{
|
||||
frame_buffer = newRttProvider->render(camera, GUIEngine::getLatestDt());
|
||||
|
||||
// TODO: leak
|
||||
//delete newRttProvider;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = oldRttProvider->renderToTexture();
|
||||
delete oldRttProvider;
|
||||
}
|
||||
|
||||
cleanupDebugMesh();
|
||||
irr_driver->removeCameraSceneNode(camera);
|
||||
m_min_coord = bb_min;
|
||||
|
||||
|
||||
if (texture == NULL)
|
||||
if (texture == NULL && frame_buffer == NULL)
|
||||
{
|
||||
Log::error("Quad Graph", "[makeMiniMap] WARNING: RTT does not appear to work,"
|
||||
"mini-map will not be available.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return texture;
|
||||
*oldRttMinimap = texture;
|
||||
*newRttMinimap = frame_buffer;
|
||||
World::getWorld()->setClearbackBufferColor(oldClearColor);
|
||||
} // makeMiniMap
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -37,6 +37,7 @@ namespace irr
|
||||
using namespace irr;
|
||||
|
||||
class CheckLine;
|
||||
class FrameBuffer;
|
||||
|
||||
/**
|
||||
* \brief This class stores a graph of quads. It uses a 'simplified singleton'
|
||||
@ -128,10 +129,11 @@ public:
|
||||
float forwards_distance=1.5f,
|
||||
float sidewards_distance=1.5f,
|
||||
float upwards_distance=0.0f) const;
|
||||
video::ITexture *makeMiniMap(const core::dimension2du &where,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color
|
||||
=video::SColor(127, 255, 255, 255) );
|
||||
void makeMiniMap(const core::dimension2du &where,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color,
|
||||
video::ITexture** oldRttMinimap,
|
||||
FrameBuffer** newRttMinimap);
|
||||
void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const;
|
||||
void updateDistancesForAllSuccessors(unsigned int indx,
|
||||
float delta,
|
||||
|
@ -115,7 +115,8 @@ Track::Track(const std::string &filename)
|
||||
m_is_soccer = false;
|
||||
m_is_cutscene = false;
|
||||
m_camera_far = 1000.0f;
|
||||
m_mini_map = NULL;
|
||||
m_old_rtt_mini_map = NULL;
|
||||
m_new_rtt_mini_map = NULL;
|
||||
m_bloom = true;
|
||||
m_bloom_threshold = 0.75f;
|
||||
m_color_inlevel = core::vector3df(0.0,1.0, 255.0);
|
||||
@ -266,6 +267,7 @@ void Track::cleanup()
|
||||
{
|
||||
QuadGraph::destroy();
|
||||
ItemManager::destroy();
|
||||
resetVAO();
|
||||
|
||||
ParticleKindManager::get()->cleanUpTrackSpecificGfx();
|
||||
// Clear reminder of transformed textures
|
||||
@ -273,13 +275,13 @@ void Track::cleanup()
|
||||
// Clear reminder of the link between textures and file names.
|
||||
irr_driver->clearTexturesFileName();
|
||||
|
||||
for(unsigned int i=0; i<m_animated_textures.size(); i++)
|
||||
for (unsigned int i = 0; i < m_animated_textures.size(); i++)
|
||||
{
|
||||
delete m_animated_textures[i];
|
||||
}
|
||||
m_animated_textures.clear();
|
||||
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||
for (unsigned int i = 0; i < m_all_nodes.size(); i++)
|
||||
{
|
||||
irr_driver->removeNode(m_all_nodes[i]);
|
||||
}
|
||||
@ -310,37 +312,42 @@ void Track::cleanup()
|
||||
// than once are in m_all_cached_mesh more than once (which is easier
|
||||
// than storing the mesh only once, but then having to test for each
|
||||
// mesh if it is already contained in the list or not).
|
||||
for(unsigned int i=0; i<m_all_cached_meshes.size(); i++)
|
||||
for (unsigned int i = 0; i < m_all_cached_meshes.size(); i++)
|
||||
{
|
||||
irr_driver->dropAllTextures(m_all_cached_meshes[i]);
|
||||
// If a mesh is not in Irrlicht's texture cache, its refcount is
|
||||
// 1 (since its scene node was removed, so the only other reference
|
||||
// is in m_all_cached_meshes). In this case we only drop it once
|
||||
// and don't try to remove it from the cache.
|
||||
if(m_all_cached_meshes[i]->getReferenceCount()==1)
|
||||
if (m_all_cached_meshes[i]->getReferenceCount() == 1)
|
||||
{
|
||||
m_all_cached_meshes[i]->drop();
|
||||
continue;
|
||||
}
|
||||
m_all_cached_meshes[i]->drop();
|
||||
if(m_all_cached_meshes[i]->getReferenceCount()==1)
|
||||
if (m_all_cached_meshes[i]->getReferenceCount() == 1)
|
||||
irr_driver->removeMeshFromCache(m_all_cached_meshes[i]);
|
||||
}
|
||||
m_all_cached_meshes.clear();
|
||||
|
||||
// Now free meshes that are not associated to any scene node.
|
||||
for (unsigned int i=0; i<m_detached_cached_meshes.size(); i++)
|
||||
for (unsigned int i = 0; i < m_detached_cached_meshes.size(); i++)
|
||||
{
|
||||
irr_driver->dropAllTextures(m_detached_cached_meshes[i]);
|
||||
irr_driver->removeMeshFromCache(m_detached_cached_meshes[i]);
|
||||
}
|
||||
m_detached_cached_meshes.clear();
|
||||
|
||||
if(m_mini_map)
|
||||
if (m_old_rtt_mini_map)
|
||||
{
|
||||
assert(m_mini_map->getReferenceCount()==1);
|
||||
irr_driver->removeTexture(m_mini_map);
|
||||
m_mini_map = NULL;
|
||||
assert(m_old_rtt_mini_map->getReferenceCount() == 1);
|
||||
irr_driver->removeTexture(m_old_rtt_mini_map);
|
||||
m_old_rtt_mini_map = NULL;
|
||||
}
|
||||
if (m_new_rtt_mini_map)
|
||||
{
|
||||
delete m_new_rtt_mini_map;
|
||||
m_new_rtt_mini_map = NULL;
|
||||
}
|
||||
|
||||
for(unsigned int i=0; i<m_sky_textures.size(); i++)
|
||||
@ -515,10 +522,10 @@ void Track::loadTrackInfo()
|
||||
delete root;
|
||||
|
||||
std::string dir = StringUtils::getPath(m_filename);
|
||||
std::string easter_name = dir+"/easter_eggs.xml";
|
||||
std::string easter_name = dir + "/easter_eggs.xml";
|
||||
|
||||
XMLNode *easter = file_manager->createXMLTree(easter_name);
|
||||
|
||||
|
||||
if(easter)
|
||||
{
|
||||
for(unsigned int i=0; i<easter->getNumNodes(); i++)
|
||||
@ -637,11 +644,18 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
||||
m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize();
|
||||
core::dimension2du size = m_mini_map_size
|
||||
.getOptimalSize(!nonpower,!nonsquare);
|
||||
m_mini_map = QuadGraph::get()->makeMiniMap(size, "minimap::"+m_ident);
|
||||
if (m_mini_map)
|
||||
|
||||
QuadGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255),
|
||||
&m_old_rtt_mini_map, &m_new_rtt_mini_map);
|
||||
if (m_old_rtt_mini_map)
|
||||
{
|
||||
m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_mini_map->getSize().Width);
|
||||
m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_mini_map->getSize().Height);
|
||||
m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_old_rtt_mini_map->getSize().Width);
|
||||
m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_old_rtt_mini_map->getSize().Height);
|
||||
}
|
||||
else if (m_new_rtt_mini_map)
|
||||
{
|
||||
m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_new_rtt_mini_map->getWidth());
|
||||
m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_new_rtt_mini_map->getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -692,6 +706,8 @@ void Track::createPhysicsModel(unsigned int main_track_count)
|
||||
} // createPhysicsModel
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** Convert the graohics track into its physics equivalents.
|
||||
* \param mesh The mesh to convert.
|
||||
* \param node The scene node.
|
||||
@ -919,7 +935,7 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
{
|
||||
mesh = irr_driver->getMesh(full_path);
|
||||
}
|
||||
|
||||
|
||||
if(!mesh)
|
||||
{
|
||||
Log::fatal("track",
|
||||
@ -939,9 +955,7 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
merged_mesh->addMesh(mesh);
|
||||
merged_mesh->finalize();
|
||||
|
||||
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
|
||||
// TODO: memory leak?
|
||||
scene::IMesh* tangent_mesh = manip->createMeshWithTangents(merged_mesh);
|
||||
scene::IMesh* tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);
|
||||
|
||||
adjustForFog(tangent_mesh, NULL);
|
||||
|
||||
@ -1150,8 +1164,6 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
|
||||
if (tangent)
|
||||
{
|
||||
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
|
||||
|
||||
scene::IMesh* original_mesh = irr_driver->getMesh(full_path);
|
||||
|
||||
if (std::find(m_detached_cached_meshes.begin(),
|
||||
@ -1173,7 +1185,7 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
scene_node->remove();
|
||||
irr_driver->grabAllTextures(original_mesh);
|
||||
|
||||
scene::IMesh* mesh = manip->createMeshWithTangents(original_mesh);
|
||||
scene::IMesh* mesh = MeshTools::createMeshWithTangents(original_mesh, &MeshTools::isNormalMap);
|
||||
mesh->grab();
|
||||
irr_driver->grabAllTextures(mesh);
|
||||
|
||||
@ -1947,7 +1959,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
|
||||
libroot = library_nodes[name];
|
||||
create_lod_definitions = false; // LOD definitions are already created, don't create them again
|
||||
}
|
||||
|
||||
|
||||
scene::ISceneNode* parent = irr_driver->getSceneManager()->addEmptySceneNode();
|
||||
parent->setPosition(xyz);
|
||||
parent->setRotation(hpr);
|
||||
|
@ -371,7 +371,8 @@ private:
|
||||
video::SColor m_fog_color;
|
||||
|
||||
/** The texture for the mini map, which is displayed in the race gui. */
|
||||
video::ITexture *m_mini_map;
|
||||
video::ITexture *m_old_rtt_mini_map;
|
||||
FrameBuffer *m_new_rtt_mini_map;
|
||||
core::dimension2du m_mini_map_size;
|
||||
float m_minimap_x_scale;
|
||||
float m_minimap_y_scale;
|
||||
@ -448,7 +449,8 @@ public:
|
||||
std::vector< std::vector<float> > buildHeightMap();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the texture with the mini map for this track. */
|
||||
const video::ITexture* getMiniMap () const { return m_mini_map; }
|
||||
const video::ITexture* getOldRttMiniMap() const { return m_old_rtt_mini_map; }
|
||||
const FrameBuffer* getNewRttMiniMap() const { return m_new_rtt_mini_map; }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::dimension2du& getMiniMapSize() const { return m_mini_map_size; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -220,6 +220,8 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
if (xml_node.get("displacing", &displacing) && displacing && glownode)
|
||||
{
|
||||
irr_driver->addDisplacingNode(glownode);
|
||||
glownode->setVisible(false);
|
||||
glownode->updateAbsolutePosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/mesh_tools.hpp"
|
||||
#include "graphics/particle_emitter.hpp"
|
||||
#include "graphics/particle_kind_manager.hpp"
|
||||
#include "graphics/stkinstancedscenenode.hpp"
|
||||
@ -96,13 +97,22 @@ const core::vector3df& TrackObjectPresentationSceneNode::getScale() const
|
||||
|
||||
|
||||
void TrackObjectPresentationSceneNode::move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
const core::vector3df& scale)
|
||||
const core::vector3df& scale)
|
||||
{
|
||||
if (m_node == NULL) return;
|
||||
|
||||
m_node->setPosition(xyz);
|
||||
if (m_node->getParent() != NULL)
|
||||
{
|
||||
scene::ISceneNode* parent = m_node->getParent();
|
||||
m_node->setPosition((xyz - parent->getAbsolutePosition()) / parent->getScale());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_node->setPosition(xyz);
|
||||
}
|
||||
m_node->setRotation(hpr);
|
||||
m_node->setScale(scale);
|
||||
m_node->updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void TrackObjectPresentationSceneNode::setEnable(bool enabled)
|
||||
@ -257,10 +267,8 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node
|
||||
|
||||
if (tangent)
|
||||
{
|
||||
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
|
||||
// TODO: perhaps the original mesh leaks here?
|
||||
m_mesh = manip->createMeshWithTangents(m_mesh);
|
||||
}
|
||||
m_mesh = MeshTools::createMeshWithTangents(m_mesh, &MeshTools::isNormalMap);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_mesh)
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
inline Vec3(const btVector3& a) : btVector3(a) {}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Empty constructor. */
|
||||
inline Vec3() : btVector3() {}
|
||||
inline Vec3() : btVector3(0, 0, 0) {}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates a 3d vector from three scalars. */
|
||||
inline Vec3(float x, float y, float z) : btVector3(x,y,z) {}
|
||||
|
103
tools/batch.py
Normal file
103
tools/batch.py
Normal file
@ -0,0 +1,103 @@
|
||||
from matplotlib import pyplot
|
||||
from os import listdir
|
||||
|
||||
|
||||
def is_numeric(x):
|
||||
try:
|
||||
float(x)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
avg_lap_time = {}
|
||||
avg_pos = {}
|
||||
avg_speed = {}
|
||||
avg_top = {}
|
||||
total_rescued = {}
|
||||
|
||||
tests = len(listdir('../../batch'))-1
|
||||
for file in listdir('../../batch'):
|
||||
if (file == '.DS_Store'):
|
||||
continue
|
||||
f = open('../../batch/'+file,'r')
|
||||
|
||||
|
||||
'''
|
||||
name_index = file.find('.')
|
||||
kart_name = str(file[:name_index])
|
||||
first = file.find('.',name_index+1)
|
||||
track_name = file[name_index+1:first]
|
||||
second = file.find('.',first+1)
|
||||
run = int(file[first+1:second])
|
||||
'''
|
||||
track_name = "snowmountain"
|
||||
kart_names = ["gnu", "sara", "tux", "elephpant"]
|
||||
|
||||
if track_name == "snowmountain":
|
||||
contents = f.readlines()
|
||||
'''
|
||||
contents = contents[2:contents.index("[debug ] profile: \n")-1]
|
||||
content = [s for s in contents if kart_name in s]
|
||||
data = [float(x) for x in content[0].split() if is_numeric(x)]
|
||||
if kart_name not in avg_lap_time:
|
||||
avg_lap_time[kart_name] = []
|
||||
avg_pos[kart_name] = []
|
||||
avg_speed[kart_name] = []
|
||||
avg_top[kart_name] = []
|
||||
total_rescued[kart_name] = []
|
||||
|
||||
avg_lap_time[kart_name].append(data[2]/4)
|
||||
avg_pos[kart_name].append(data[1])
|
||||
avg_speed[kart_name].append(data[3])
|
||||
avg_top[kart_name].append(data[4])
|
||||
total_rescued[kart_name].append(data[7])
|
||||
'''
|
||||
|
||||
contents = contents[2:6] #TODO check if all is in here
|
||||
for kart in kart_names:
|
||||
content = [s for s in contents if kart in s]
|
||||
data = [float(x) for x in content[0].split() if is_numeric(x)]
|
||||
if kart not in avg_lap_time:
|
||||
avg_lap_time[kart] = []
|
||||
avg_pos[kart] = []
|
||||
avg_speed[kart] = []
|
||||
avg_top[kart] = []
|
||||
total_rescued[kart] = []
|
||||
|
||||
avg_lap_time[kart].append(data[2]/4)
|
||||
avg_pos[kart].append(data[1])
|
||||
avg_speed[kart].append(data[3])
|
||||
avg_top[kart].append(data[4])
|
||||
total_rescued[kart].append(data[7])
|
||||
|
||||
tests = len(avg_lap_time["gnu"])
|
||||
print total_rescued
|
||||
|
||||
|
||||
for kart in kart_names:
|
||||
print "rescues for ", kart , ": ", sum(total_rescued[kart])/tests
|
||||
print "avg_lap_time for " , kart , ": " , sum(avg_lap_time[kart])/tests
|
||||
print "avg_pos for " , kart , ": " , sum(avg_pos[kart])/tests
|
||||
print "avg_speed for " , kart , ": " , sum(avg_speed[kart])/tests
|
||||
print "avg_top for " , kart , ": " , sum(avg_top[kart])/tests
|
||||
|
||||
|
||||
pyplot.subplot(2,2,1)
|
||||
pyplot.plot(list(xrange(tests)),avg_pos["gnu"], "b-")
|
||||
pyplot.xlabel("tests")
|
||||
pyplot.ylabel("gnu")
|
||||
pyplot.subplot(2,2,2)
|
||||
pyplot.plot(list(xrange(tests)),avg_pos["sara"], "r-")
|
||||
pyplot.xlabel("tests")
|
||||
pyplot.ylabel("sara")
|
||||
pyplot.subplot(2,2,3)
|
||||
pyplot.plot(list(xrange(tests)),avg_pos["elephpant"], "y-")
|
||||
pyplot.xlabel("tests")
|
||||
pyplot.ylabel("elephpant")
|
||||
pyplot.subplot(2,2,4)
|
||||
pyplot.plot(list(xrange(tests)),avg_pos["tux"], "g-")
|
||||
pyplot.xlabel("tests")
|
||||
pyplot.ylabel("tux")
|
||||
|
||||
pyplot.show()
|
19
tools/test.sh
Executable file
19
tools/test.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p ../../batch
|
||||
#tracks='snowmountain city lighthouse olivermath hacienda startrack farm zengarden'
|
||||
#karts='gnu tux sara elephpant'
|
||||
laps=4
|
||||
|
||||
#for track in $tracks; do
|
||||
#for kart in $karts; do
|
||||
for run in {901..1500}; do
|
||||
for lap in $laps; do
|
||||
./../cmake_build/bin/supertuxkart.app/Contents/MacOS/supertuxkart -R --mode=3 --numkarts=4 --track=snowmountain --with-profile --profile-laps=4 --kart=gnu --ai=sara,tux,elephpant --no-graphics > /dev/null
|
||||
#./cmake_build/bin/supertuxkart.app/Contents/MacOS/supertuxkart -R --mode=3 --numkarts=4 --track=$track --with-profile --profile-laps=$lap --kart=$kart --ai=beastie,beastie,beastie --no-graphics > /dev/null
|
||||
#grep "profile" ~/Library/Application\ Support/SuperTuxKart/stdout.log > ../batch/$kart.$track.$run.txt
|
||||
grep "profile" ~/Library/Application\ Support/SuperTuxKart/stdout.log > ../../batch/faceoff.$run.txt
|
||||
done
|
||||
done
|
||||
# done
|
||||
#done
|
Loading…
Reference in New Issue
Block a user