Merge remote-tracking branch 'upstream/master' into walldriving

Conflicts:
	src/graphics/irr_driver.cpp
	src/karts/kart.cpp
This commit is contained in:
nixt 2014-07-09 23:40:26 +05:30
commit 732c3a4b2f
91 changed files with 3709 additions and 1752 deletions

View File

@ -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"

View File

@ -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()

View File

@ -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.);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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.);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.;
}

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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 &center, 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 &center, 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;

View File

@ -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 &center, 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 &center, float mask_radius, unsigned TU_cb, unsigned TU_dtex);
};
class GodFadeShader

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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)

View 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
// -----------------------------------------------------------------------------

View 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

View File

@ -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();

View File

@ -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());
}
}
// -----------------------------------------------------------------------------

View File

@ -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. */

View 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);
}

View 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

View File

@ -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)
{

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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; }

View File

@ -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 */

View File

@ -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; }

View File

@ -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))

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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)
{
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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; }
// ------------------------------------------------------------------------

View File

@ -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++)

View File

@ -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);
}
// ------------------------------------------------------------------------------------------------------

View File

@ -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

View 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;
}

View 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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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
}

View File

@ -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++)

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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,

View File

@ -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);

View File

@ -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; }
// ------------------------------------------------------------------------

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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
View 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
View 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