@ -24,7 +24,11 @@ title_font, by Marianne Gagnon (Auria), released under CC-BY-SA 3+
|
||||
|
||||
screen*.png, by Marianne Gagnon (Auria), including elements from the public domain Tango icon set
|
||||
|
||||
Gauge and bar by Totoplus62, released under CC-BY-SA 3
|
||||
speed.png by Alayan, with elements by Totoplus62, released under CC-BY-SA 3
|
||||
|
||||
speed*.png by Alayan, released under CC-0
|
||||
|
||||
gauge*.png by Alayan, released under CC-0
|
||||
|
||||
menu_story by tavariz91, released under CC-0
|
||||
|
||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 126 KiB |
@ -11,13 +11,7 @@ layout(location = 1) in vec4 i_normal;
|
||||
layout(location = 2) in vec4 i_color;
|
||||
layout(location = 3) in vec2 i_uv;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
layout(location = 12) in ivec2 i_misc_data;
|
||||
|
||||
@ -32,16 +26,14 @@ void main()
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_normal = convert10BitVector(i_normal_orig);
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec3 test = sin(wind_direction * (i_position.y * 0.1));
|
||||
test += cos(wind_direction) * 0.7;
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 world_position = getWorldPosition(i_origin + test * i_color.r,
|
||||
quaternion, i_scale.xyz, i_position);
|
||||
vec3 world_normal = rotateVector(quaternion, i_normal.xyz);
|
||||
i_rotation, i_scale.xyz, i_position);
|
||||
vec3 world_normal = rotateVector(i_rotation, i_normal.xyz);
|
||||
|
||||
normal = (u_view_matrix * vec4(world_normal, 0.0)).xyz;
|
||||
uv = i_uv;
|
||||
|
@ -5,13 +5,7 @@ layout(location = 0) in vec3 i_position;
|
||||
layout(location = 2) in vec4 i_color;
|
||||
layout(location = 3) in vec2 i_uv;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
|
||||
#stk_include "utils/get_world_location.vert"
|
||||
@ -20,17 +14,10 @@ out vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec3 test = sin(wind_direction * (i_position.y * 0.1));
|
||||
test += cos(wind_direction) * 0.7;
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 world_position = getWorldPosition(i_origin + test * i_color.r,
|
||||
quaternion, i_scale.xyz, i_position);
|
||||
i_rotation, i_scale.xyz, i_position);
|
||||
|
||||
uv = i_uv;
|
||||
gl_Position = u_shadow_projection_view_matrices[layer] * world_position;
|
||||
|
@ -17,13 +17,7 @@ layout(location = 5) in vec4 i_tangent;
|
||||
layout(location = 6) in ivec4 i_joint;
|
||||
layout(location = 7) in vec4 i_weight;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
layout(location = 12) in ivec2 i_misc_data;
|
||||
|
||||
@ -39,7 +33,6 @@ void main()
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_normal = convert10BitVector(i_normal_orig);
|
||||
vec4 i_tangent = convert10BitVector(i_tangent_orig);
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec4 idle_position = vec4(i_position, 1.0);
|
||||
@ -104,12 +97,11 @@ void main()
|
||||
skinned_position = mix(skinned_position, idle_position, step_mix);
|
||||
skinned_normal = mix(skinned_normal, idle_normal, step_mix);
|
||||
skinned_tangent = mix(skinned_tangent, idle_tangent, step_mix);
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
|
||||
gl_Position = getWorldPosition(i_origin, quaternion, i_scale.xyz,
|
||||
gl_Position = getWorldPosition(i_origin, i_rotation, i_scale.xyz,
|
||||
skinned_position.xyz);
|
||||
o_normal = normalize(rotateVector(quaternion, skinned_normal.xyz));
|
||||
o_tangent = normalize(rotateVector(quaternion, skinned_tangent.xyz));
|
||||
o_normal = normalize(rotateVector(i_rotation, skinned_normal.xyz));
|
||||
o_tangent = normalize(rotateVector(i_rotation, skinned_tangent.xyz));
|
||||
o_bitangent = cross(o_normal, o_tangent) * i_tangent.w;
|
||||
|
||||
}
|
||||
|
@ -17,13 +17,7 @@ layout(location = 5) in vec4 i_tangent;
|
||||
#endif
|
||||
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
layout(location = 11) in vec2 i_texture_trans;
|
||||
layout(location = 12) in ivec2 i_misc_data;
|
||||
@ -47,14 +41,12 @@ void main()
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_normal = convert10BitVector(i_normal_orig);
|
||||
vec4 i_tangent = convert10BitVector(i_tangent_orig);
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 v_world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz,
|
||||
vec4 v_world_position = getWorldPosition(i_origin, i_rotation, i_scale.xyz,
|
||||
i_position);
|
||||
vec3 v_world_normal = rotateVector(quaternion, i_normal.xyz);
|
||||
vec3 world_tangent = rotateVector(quaternion, i_tangent.xyz);
|
||||
vec3 v_world_normal = rotateVector(i_rotation, i_normal.xyz);
|
||||
vec3 world_tangent = rotateVector(i_rotation, i_tangent.xyz);
|
||||
|
||||
tangent = (u_view_matrix * vec4(world_tangent, 0.0)).xyz;
|
||||
bitangent = (u_view_matrix *
|
||||
|
@ -3,13 +3,7 @@ uniform int layer;
|
||||
layout(location = 0) in vec3 i_position;
|
||||
layout(location = 3) in vec2 i_uv;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
|
||||
#stk_include "utils/get_world_location.vert"
|
||||
@ -18,13 +12,7 @@ out vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz,
|
||||
vec4 world_position = getWorldPosition(i_origin, i_rotation, i_scale.xyz,
|
||||
i_position);
|
||||
uv = i_uv;
|
||||
gl_Position = u_shadow_projection_view_matrices[layer] * world_position;
|
||||
|
@ -24,13 +24,7 @@ layout(location = 5) in vec4 i_tangent;
|
||||
layout(location = 6) in ivec4 i_joint;
|
||||
layout(location = 7) in vec4 i_weight;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
layout(location = 11) in vec2 i_texture_trans;
|
||||
layout(location = 12) in ivec2 i_misc_data;
|
||||
@ -52,7 +46,6 @@ void main()
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_normal = convert10BitVector(i_normal_orig);
|
||||
vec4 i_tangent = convert10BitVector(i_tangent_orig);
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec4 idle_position = vec4(i_position, 1.0);
|
||||
@ -113,11 +106,10 @@ void main()
|
||||
skinned_normal = joint_matrix * idle_normal;
|
||||
skinned_tangent = joint_matrix * idle_tangent;
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz,
|
||||
vec4 world_position = getWorldPosition(i_origin, i_rotation, i_scale.xyz,
|
||||
skinned_position.xyz);
|
||||
vec3 world_normal = rotateVector(quaternion, skinned_normal.xyz);
|
||||
vec3 world_tangent = rotateVector(quaternion, skinned_tangent.xyz);
|
||||
vec3 world_normal = rotateVector(i_rotation, skinned_normal.xyz);
|
||||
vec3 world_tangent = rotateVector(i_rotation, skinned_tangent.xyz);
|
||||
|
||||
tangent = (u_view_matrix * vec4(world_tangent, 0.0)).xyz;
|
||||
bitangent = (u_view_matrix *
|
||||
|
@ -11,13 +11,7 @@ layout(location = 3) in vec2 i_uv;
|
||||
layout(location = 6) in ivec4 i_joint;
|
||||
layout(location = 7) in vec4 i_weight;
|
||||
layout(location = 8) in vec3 i_origin;
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
layout(location = 9) in vec4 i_rotation_orig;
|
||||
#else
|
||||
layout(location = 9) in vec4 i_rotation;
|
||||
#endif
|
||||
|
||||
layout(location = 10) in vec4 i_scale;
|
||||
layout(location = 12) in ivec2 i_misc_data;
|
||||
|
||||
@ -27,11 +21,6 @@ out vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
#if defined(Converts_10bit_Vector)
|
||||
vec4 i_rotation = convert10BitVector(i_rotation_orig);
|
||||
#endif
|
||||
|
||||
vec4 idle_position = vec4(i_position, 1.0);
|
||||
vec4 skinned_position = vec4(0.0);
|
||||
int skinning_offset = i_misc_data.x;
|
||||
@ -83,9 +72,7 @@ void main()
|
||||
#endif
|
||||
|
||||
skinned_position = joint_matrix * idle_position;
|
||||
|
||||
vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w));
|
||||
vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz,
|
||||
vec4 world_position = getWorldPosition(i_origin, i_rotation, i_scale.xyz,
|
||||
skinned_position.xyz);
|
||||
uv = i_uv;
|
||||
gl_Position = u_shadow_projection_view_matrices[layer] * world_position;
|
||||
|
@ -1,12 +1,10 @@
|
||||
<spshader>
|
||||
<shader-info name="tillingMitigation" fallback-shader="solid" use-tangents="Y"/>
|
||||
<first-pass vertex-shader="sp_pass.vert"
|
||||
fragment-shader="sp_tilling_mitigation.frag"
|
||||
skinned-mesh-shader="sp_skinning.vert">
|
||||
fragment-shader="sp_tilling_mitigation.frag">
|
||||
</first-pass>
|
||||
<shadow-pass vertex-shader="sp_shadow.vert"
|
||||
fragment-shader="white.frag"
|
||||
skinned-mesh-shader="sp_skinning_shadow.vert">
|
||||
fragment-shader="white.frag">
|
||||
</shadow-pass>
|
||||
<uniform-assigners>
|
||||
<uniform-assigner name="layer"
|
||||
|
@ -1,12 +1,10 @@
|
||||
<spshader>
|
||||
<shader-info name="verticalMapping" fallback-shader="solid" use-tangents="Y"/>
|
||||
<first-pass vertex-shader="sp_pass.vert"
|
||||
fragment-shader="sp_vertical_mapping.frag"
|
||||
skinned-mesh-shader="sp_skinning.vert">
|
||||
fragment-shader="sp_vertical_mapping.frag">
|
||||
</first-pass>
|
||||
<shadow-pass vertex-shader="sp_shadow.vert"
|
||||
fragment-shader="white.frag"
|
||||
skinned-mesh-shader="sp_skinning_shadow.vert">
|
||||
fragment-shader="white.frag">
|
||||
</shadow-pass>
|
||||
<uniform-assigners>
|
||||
<uniform-assigner name="layer"
|
||||
|
@ -500,6 +500,11 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "screen_keyboard",
|
||||
&m_multitouch_group,
|
||||
"Enable screen keyboard.") );
|
||||
|
||||
PARAM_PREFIX BoolUserConfigParam m_hidpi_enabled
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "hidpi_enabled",
|
||||
&m_multitouch_group,
|
||||
"Enable high-DPI support.") );
|
||||
|
||||
// ---- GP start order
|
||||
PARAM_PREFIX GroupUserConfigParam m_gp_start_order
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "font/font_with_face.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "font/face_ttf.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/font_settings.hpp"
|
||||
@ -331,23 +332,24 @@ void FontWithFace::setDPI()
|
||||
const int screen_width = irr_driver->getFrameSize().Width;
|
||||
const int screen_height = irr_driver->getFrameSize().Height;
|
||||
|
||||
#ifdef ANDROID
|
||||
float scale = screen_height / 480.0f;
|
||||
m_face_dpi = getScalingFactorTwo() * getScalingFactorOne() * scale;
|
||||
|
||||
#else
|
||||
float scale = std::max(0, screen_width - 640) / 564.0f;
|
||||
|
||||
// attempt to compensate for small screens
|
||||
if (screen_width < 1200)
|
||||
scale = std::max(0, screen_width - 640) / 750.0f;
|
||||
if (screen_width < 900 || screen_height < 700)
|
||||
scale = std::min(scale, 0.05f);
|
||||
|
||||
m_face_dpi = unsigned((getScalingFactorOne() + 0.2f * scale) *
|
||||
getScalingFactorTwo());
|
||||
#endif
|
||||
|
||||
if (UserConfigParams::m_hidpi_enabled)
|
||||
{
|
||||
float scale = screen_height / 480.0f;
|
||||
m_face_dpi = getScalingFactorTwo() * getScalingFactorOne() * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = std::max(0, screen_width - 640) / 564.0f;
|
||||
|
||||
// attempt to compensate for small screens
|
||||
if (screen_width < 1200)
|
||||
scale = std::max(0, screen_width - 640) / 750.0f;
|
||||
if (screen_width < 900 || screen_height < 700)
|
||||
scale = std::min(scale, 0.05f);
|
||||
|
||||
m_face_dpi = unsigned((getScalingFactorOne() + 0.2f * scale) *
|
||||
getScalingFactorTwo());
|
||||
}
|
||||
} // setDPI
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -31,13 +31,13 @@ namespace SP
|
||||
class SPInstancedData
|
||||
{
|
||||
private:
|
||||
char m_data[32];
|
||||
char m_data[44];
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
SPInstancedData()
|
||||
{
|
||||
memset(m_data, 0, 32);
|
||||
memset(m_data, 0, 44);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
SPInstancedData(const core::matrix4& model_mat,
|
||||
@ -65,21 +65,19 @@ public:
|
||||
rotation.W = -rotation.W;
|
||||
}
|
||||
memcpy(m_data, position, 12);
|
||||
uint32_t _2101010 = normalizedSignedFloatsTo1010102(
|
||||
{{ rotation.X, rotation.Y, rotation.Z, 0.0f }});
|
||||
memcpy(m_data + 12, &_2101010, 4);
|
||||
memcpy(m_data + 12, &rotation, 16);
|
||||
short s[4] = { toFloat16(scale.X), toFloat16(scale.Y),
|
||||
toFloat16(scale.Z), toFloat16(rotation.W) };
|
||||
memcpy(m_data + 16, s, 8);
|
||||
toFloat16(scale.Z), 0 };
|
||||
memcpy(m_data + 28, s, 8);
|
||||
short tm[2] =
|
||||
{
|
||||
short(texture_trans_x * 32767.0f),
|
||||
short(texture_trans_y * 32767.0f)
|
||||
};
|
||||
memcpy(m_data + 24, tm, 4);
|
||||
memcpy(m_data + 28, &skinning_offset, 2);
|
||||
memcpy(m_data + 36, tm, 4);
|
||||
memcpy(m_data + 40, &skinning_offset, 2);
|
||||
short hue_packed = short(core::clamp(int(hue * 100.0f), 0, 100));
|
||||
memcpy(m_data + 30, &hue_packed, 2);
|
||||
memcpy(m_data + 42, &hue_packed, 2);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
const void* getData() const { return m_data; }
|
||||
|
@ -247,16 +247,16 @@ void SPMeshBuffer::recreateVAO(unsigned i)
|
||||
#ifndef USE_GLES2
|
||||
if (CVS->isARBBufferStorageUsable())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, m_gl_instance_size[i] * 32, NULL,
|
||||
glBufferStorage(GL_ARRAY_BUFFER, m_gl_instance_size[i] * 44, NULL,
|
||||
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
|
||||
m_ins_dat_mapped_ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0,
|
||||
m_gl_instance_size[i] * 32,
|
||||
m_gl_instance_size[i] * 44,
|
||||
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, m_gl_instance_size[i] * 32, NULL,
|
||||
glBufferData(GL_ARRAY_BUFFER, m_gl_instance_size[i] * 44, NULL,
|
||||
GL_DYNAMIC_DRAW);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
@ -346,26 +346,23 @@ void SPMeshBuffer::recreateVAO(unsigned i)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ins_array[i]);
|
||||
// Origin
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 32, (void*)0);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 44, (void*)0);
|
||||
glVertexAttribDivisorARB(8, 1);
|
||||
// Rotation (quaternion .xyz)
|
||||
// Rotation (quaternion in 4 32bit floats)
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 4, GL_INT_2_10_10_10_REV,
|
||||
GraphicsRestrictions::isDisabled
|
||||
(GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION) ? GL_FALSE : GL_TRUE, 32,
|
||||
(void*)12);
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, 44, (void*)12);
|
||||
glVertexAttribDivisorARB(9, 1);
|
||||
// Scale (3 half floats and .w for quaternion .w)
|
||||
// Scale (3 half floats and .w unused)
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 32, (void*)16);
|
||||
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 44, (void*)28);
|
||||
glVertexAttribDivisorARB(10, 1);
|
||||
// Texture translation
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 32, (void*)24);
|
||||
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 44, (void*)36);
|
||||
glVertexAttribDivisorARB(11, 1);
|
||||
// Misc data (skinning offset and hue change)
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribIPointer(12, 2, GL_SHORT, 32, (void*)28);
|
||||
glVertexAttribIPointer(12, 2, GL_SHORT, 44, (void*)40);
|
||||
glVertexAttribDivisorARB(12, 1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
@ -400,15 +397,15 @@ void SPMeshBuffer::uploadInstanceData()
|
||||
if (CVS->isARBBufferStorageUsable())
|
||||
{
|
||||
memcpy(m_ins_dat_mapped_ptr[i], m_ins_dat[i].data(),
|
||||
m_ins_dat[i].size() * 32);
|
||||
m_ins_dat[i].size() * 44);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ins_array[i]);
|
||||
void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0,
|
||||
m_ins_dat[i].size() * 32, GL_MAP_WRITE_BIT |
|
||||
m_ins_dat[i].size() * 44, GL_MAP_WRITE_BIT |
|
||||
GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
memcpy(ptr, m_ins_dat[i].data(), m_ins_dat[i].size() * 32);
|
||||
memcpy(ptr, m_ins_dat[i].data(), m_ins_dat[i].size() * 44);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ void STKTextBillboard::init(core::stringw text, FontWithFace* face)
|
||||
glGenBuffers(1, &m_instanced_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
12 /*position*/ + 4/*quaternion*/ + 8 /*scale*/, NULL,
|
||||
12 /*position*/ + 16/*quaternion*/ + 8 /*scale*/, NULL,
|
||||
GL_DYNAMIC_DRAW);
|
||||
for (auto& p : m_gl_tbs)
|
||||
{
|
||||
@ -213,20 +213,17 @@ void STKTextBillboard::init(core::stringw text, FontWithFace* face)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
// Origin
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 24, (void*)0);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 36, (void*)0);
|
||||
glVertexAttribDivisorARB(8, 1);
|
||||
|
||||
// Rotation (quaternion .xyz)
|
||||
// Rotation (quaternion in 4 32bit floats)
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 4, GL_INT_2_10_10_10_REV,
|
||||
GraphicsRestrictions::isDisabled
|
||||
(GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION) ?
|
||||
GL_FALSE : GL_TRUE, 24, (void*)12);
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, 36, (void*)12);
|
||||
glVertexAttribDivisorARB(9, 1);
|
||||
|
||||
// Scale (3 half floats and .w for quaternion .w)
|
||||
// Scale (3 half floats and .w unused)
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 24, (void*)16);
|
||||
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 36, (void*)28);
|
||||
glVertexAttribDivisorARB(10, 1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
@ -143,7 +143,7 @@ public:
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, 24, m_instanced_data.getData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, 36, m_instanced_data.getData());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/regular_face.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
@ -151,9 +152,12 @@ void DynamicRibbonWidget::add()
|
||||
unsigned int screen_height = irr_driver->getActualScreenSize().Height;
|
||||
m_arrows_w = (int)(screen_height / 15);
|
||||
m_arrows_w = std::max(m_arrows_w, 40);
|
||||
#ifdef ANDROID
|
||||
m_arrows_w *= 1.5f;
|
||||
#endif
|
||||
|
||||
if (UserConfigParams::m_hidpi_enabled)
|
||||
{
|
||||
m_arrows_w *= 1.5f;
|
||||
}
|
||||
|
||||
const int button_h = m_arrows_w;
|
||||
|
||||
// right arrow
|
||||
|
@ -49,6 +49,9 @@ void override_default_params()
|
||||
UserConfigParams::m_screen_keyboard = true;
|
||||
}
|
||||
|
||||
// Set bigger fonts and buttons
|
||||
UserConfigParams::m_hidpi_enabled = true;
|
||||
|
||||
// It shouldn't matter, but STK is always run in fullscreen on android
|
||||
UserConfigParams::m_fullscreen = true;
|
||||
|
||||
|
@ -276,6 +276,7 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt)
|
||||
drawLap(kart, viewport, scaling);
|
||||
} // renderPlayerView
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Shows the current soccer result.
|
||||
*/
|
||||
@ -460,7 +461,7 @@ void RaceGUI::drawGlobalMiniMap()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Energy meter that gets filled with nitro. This function is called from
|
||||
* drawSpeedAndEnergy, which defines the correct position of the energy
|
||||
* drawSpeedEnergyRank, which defines the correct position of the energy
|
||||
* meter.
|
||||
* \param x X position of the meter.
|
||||
* \param y Y position of the meter.
|
||||
@ -473,7 +474,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
float min_ratio = std::min(scaling.X, scaling.Y);
|
||||
const int GAUGEWIDTH = 78;
|
||||
const int GAUGEWIDTH = 94;//same inner radius as the inner speedometer circle
|
||||
int gauge_width = (int)(GAUGEWIDTH*min_ratio);
|
||||
int gauge_height = (int)(GAUGEWIDTH*min_ratio);
|
||||
|
||||
@ -483,8 +484,8 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
else if (state > 1.0f) state = 1.0f;
|
||||
|
||||
core::vector2df offset;
|
||||
offset.X = (float)(x-gauge_width) - 9.0f*scaling.X;
|
||||
offset.Y = (float)y-30.0f*scaling.Y;
|
||||
offset.X = (float)(x-gauge_width) - 9.5f*scaling.X;
|
||||
offset.Y = (float)y-11.5f*scaling.Y;
|
||||
|
||||
|
||||
// Background
|
||||
@ -497,156 +498,58 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
NULL /* clip rect */, NULL /* colors */,
|
||||
true /* alpha */);
|
||||
|
||||
// Target
|
||||
// The positions for A to G are defined here.
|
||||
// They are calculated from gauge_full.png
|
||||
// They are further than the nitrometer farther position because
|
||||
// the lines between them would otherwise cut through the outside circle.
|
||||
|
||||
const int vertices_count = 7;
|
||||
|
||||
if (race_manager->getCoinTarget() > 0)
|
||||
{
|
||||
float coin_target = (float)race_manager->getCoinTarget()
|
||||
/ kart->getKartProperties()->getNitroMax();
|
||||
|
||||
video::S3DVertex vertices[5];
|
||||
unsigned int count=2;
|
||||
|
||||
// There are three different polygons used, depending on
|
||||
// the target. Consider the nitro-display texture:
|
||||
//
|
||||
// ----E-x--D (position of v,w,x vary depending on
|
||||
// | nitro)
|
||||
// A w
|
||||
// |
|
||||
// -B--v----C
|
||||
// For nitro state <= r1 the triangle ABv is used, with v between B and C.
|
||||
// For nitro state <= r2 the quad ABCw is used, with w between C and D.
|
||||
// For nitro state > r2 the poly ABCDx is used, with x between D and E.
|
||||
|
||||
vertices[0].TCoords = core::vector2df(0.3f, 0.4f);
|
||||
vertices[0].Pos = core::vector3df(offset.X+0.3f*gauge_width,
|
||||
offset.Y-(1-0.4f)*gauge_height, 0);
|
||||
vertices[1].TCoords = core::vector2df(0, 1.0f);
|
||||
vertices[1].Pos = core::vector3df(offset.X, offset.Y, 0);
|
||||
// The targets at which different polygons must be used.
|
||||
|
||||
const float r1 = 0.4f;
|
||||
const float r2 = 0.65f;
|
||||
if(coin_target<=r1)
|
||||
{
|
||||
count = 3;
|
||||
float f = coin_target/r1;
|
||||
vertices[2].TCoords = core::vector2df(0.08f + (1.0f-0.08f)*f, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + (0.08f*gauge_width)
|
||||
+ (1.0f - 0.08f)*f*gauge_width,
|
||||
offset.Y,0);
|
||||
}
|
||||
else if(coin_target<=r2)
|
||||
{
|
||||
count = 4;
|
||||
float f = (coin_target - r1)/(r2-r1);
|
||||
vertices[2].TCoords = core::vector2df(1.0f, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(1.0f, (1.0f-f));
|
||||
vertices[3].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y-f*gauge_height,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 5;
|
||||
float f = (coin_target - r2)/(1-r2);
|
||||
vertices[2].TCoords = core::vector2df(1.0, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(1.0,0);
|
||||
vertices[3].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y-gauge_height, 0);
|
||||
vertices[4].TCoords = core::vector2df(1.0f - f*(1-0.61f), 0);
|
||||
vertices[4].Pos = core::vector3df(offset.X + gauge_width
|
||||
- (1.0f-0.61f)*f*gauge_width,
|
||||
offset.Y-gauge_height, 0);
|
||||
}
|
||||
short int index[5]={0};
|
||||
for(unsigned int i=0; i<count; i++)
|
||||
{
|
||||
index[i]=count-i-1;
|
||||
vertices[i].Color = video::SColor(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
video::SMaterial m;
|
||||
m.setTexture(0, m_gauge_goal);
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_driver->getVideoDriver()->setMaterial(m);
|
||||
draw2DVertexPrimitiveList(m_gauge_goal, vertices, count,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
|
||||
}
|
||||
core::vector2df position[vertices_count];
|
||||
position[0].X = 0.324f;//A
|
||||
position[0].Y = 0.35f;//A
|
||||
position[1].X = 0.029f;//B
|
||||
position[1].Y = 0.918f;//B
|
||||
position[2].X = 0.307f;//C
|
||||
position[2].Y = 0.99f;//C
|
||||
position[3].X = 0.589f;//D
|
||||
position[3].Y = 0.932f;//D
|
||||
position[4].X = 0.818f;//E
|
||||
position[4].Y = 0.755f;//E
|
||||
position[5].X = 0.945f;//F
|
||||
position[5].Y = 0.497f;//F
|
||||
position[6].X = 0.948f;//G
|
||||
position[6].Y = 0.211f;//G
|
||||
|
||||
|
||||
// The states at which different polygons must be used.
|
||||
|
||||
float threshold[vertices_count-2];
|
||||
threshold[0] = 0.2f;
|
||||
threshold[1] = 0.4f;
|
||||
threshold[2] = 0.6f;
|
||||
threshold[3] = 0.8f;
|
||||
threshold[4] = 1.0f;
|
||||
|
||||
// Filling (current state)
|
||||
|
||||
if(state <=0) return; //Nothing to do
|
||||
|
||||
if (state > 0.0f)
|
||||
{
|
||||
video::S3DVertex vertices[5];
|
||||
unsigned int count=2;
|
||||
video::S3DVertex vertices[vertices_count];
|
||||
|
||||
// There are three different polygons used, depending on
|
||||
// the nitro state. Consider the nitro-display texture:
|
||||
//
|
||||
// ----E-x--D (position of v,w,x vary depending on
|
||||
// | nitro)
|
||||
// A w
|
||||
// |
|
||||
// -B--v----C
|
||||
// For nitro state <= r1 the triangle ABv is used, with v between B and C.
|
||||
// For nitro state <= r2 the quad ABCw is used, with w between C and D.
|
||||
// For nitro state > r2 the poly ABCDx is used, with x between D and E.
|
||||
|
||||
vertices[0].TCoords = core::vector2df(0.3f, 0.4f);
|
||||
vertices[0].Pos = core::vector3df(offset.X+0.3f*gauge_width,
|
||||
offset.Y-(1-0.4f)*gauge_height, 0);
|
||||
vertices[1].TCoords = core::vector2df(0, 1.0f);
|
||||
vertices[1].Pos = core::vector3df(offset.X, offset.Y, 0);
|
||||
// The states at which different polygons must be used.
|
||||
|
||||
const float r1 = 0.4f;
|
||||
const float r2 = 0.65f;
|
||||
if(state<=r1)
|
||||
//3D effect : wait for the full border to appear before drawing
|
||||
for (int i=0;i<5;i++)
|
||||
{
|
||||
count = 3;
|
||||
float f = state/r1;
|
||||
vertices[2].TCoords = core::vector2df(0.08f + (1.0f-0.08f)*f, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + (0.08f*gauge_width)
|
||||
+ (1.0f - 0.08f)
|
||||
*f*gauge_width,
|
||||
offset.Y,0);
|
||||
}
|
||||
else if(state<=r2)
|
||||
{
|
||||
count = 4;
|
||||
float f = (state - r1)/(r2-r1);
|
||||
vertices[2].TCoords = core::vector2df(1.0f, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(1.0f, (1.0f-f));
|
||||
vertices[3].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y-f*gauge_height,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 5;
|
||||
float f = (state - r2)/(1-r2);
|
||||
vertices[2].TCoords = core::vector2df(1.0, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(1.0,0);
|
||||
vertices[3].Pos = core::vector3df(offset.X + gauge_width,
|
||||
offset.Y-gauge_height, 0);
|
||||
vertices[4].TCoords = core::vector2df(1.0f - f*(1-0.61f), 0);
|
||||
vertices[4].Pos =
|
||||
core::vector3df(offset.X + gauge_width - (1.0f-0.61f)*f*gauge_width,
|
||||
offset.Y-gauge_height, 0);
|
||||
if ((state-0.2f*i < 0.006f && state-0.2f*i >= 0.0f) || (0.2f*i-state < 0.003f && 0.2f*i-state >= 0.0f) )
|
||||
{
|
||||
state = 0.2f*i-0.003f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int count = computeVerticesForMeter(position, threshold, vertices, vertices_count,
|
||||
state, gauge_width, gauge_height, offset);
|
||||
|
||||
short int index[5]={0};
|
||||
for(unsigned int i=0; i<count; i++)
|
||||
{
|
||||
@ -666,6 +569,33 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
|
||||
}
|
||||
|
||||
// Target
|
||||
|
||||
if (race_manager->getCoinTarget() > 0)
|
||||
{
|
||||
float coin_target = (float)race_manager->getCoinTarget()
|
||||
/ kart->getKartProperties()->getNitroMax();
|
||||
|
||||
video::S3DVertex vertices[vertices_count];
|
||||
|
||||
unsigned int count = computeVerticesForMeter(position, threshold, vertices, vertices_count,
|
||||
coin_target, gauge_width, gauge_height, offset);
|
||||
|
||||
short int index[5]={0};
|
||||
for(unsigned int i=0; i<count; i++)
|
||||
{
|
||||
index[i]=count-i-1;
|
||||
vertices[i].Color = video::SColor(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
video::SMaterial m;
|
||||
m.setTexture(0, m_gauge_goal);
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_driver->getVideoDriver()->setMaterial(m);
|
||||
draw2DVertexPrimitiveList(m_gauge_goal, vertices, count,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
}
|
||||
#endif
|
||||
} // drawEnergyMeter
|
||||
|
||||
@ -743,10 +673,10 @@ void RaceGUI::drawRank(const AbstractKart *kart,
|
||||
oss << rank; // the current font has no . :( << ".";
|
||||
|
||||
core::recti pos;
|
||||
pos.LowerRightCorner = core::vector2di(int(offset.X + 0.65f*meter_width),
|
||||
int(offset.Y - 0.55f*meter_height));
|
||||
pos.UpperLeftCorner = core::vector2di(int(offset.X + 0.65f*meter_width),
|
||||
int(offset.Y - 0.55f*meter_height));
|
||||
pos.LowerRightCorner = core::vector2di(int(offset.X + 0.64f*meter_width),
|
||||
int(offset.Y - 0.49f*meter_height));
|
||||
pos.UpperLeftCorner = core::vector2di(int(offset.X + 0.64f*meter_width),
|
||||
int(offset.Y - 0.49f*meter_height));
|
||||
|
||||
static video::SColor color = video::SColor(255, 255, 255, 255);
|
||||
font->draw(oss.str().c_str(), pos, color, true, true);
|
||||
@ -803,65 +733,83 @@ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart,
|
||||
|
||||
// Draw the actual speed bar (if the speed is >0)
|
||||
// ----------------------------------------------
|
||||
float speed_ratio = speed/KILOMETERS_PER_HOUR/110.0f;
|
||||
float speed_ratio = speed/40.0f; //max displayed speed of 40
|
||||
if(speed_ratio>1) speed_ratio = 1;
|
||||
|
||||
video::S3DVertex vertices[5];
|
||||
unsigned int count;
|
||||
// see computeVerticesForMeter for the detail of the drawing
|
||||
|
||||
// There are three different polygons used, depending on
|
||||
// the speed ratio. Consider the speed-display texture:
|
||||
//
|
||||
// D----x----D (position of v,w,x vary depending on
|
||||
// | speed)
|
||||
// w A
|
||||
// |
|
||||
// C--v-B----E
|
||||
// For speed ratio <= r1 the triangle ABv is used, with v between B and C.
|
||||
// For speed ratio <= r2 the quad ABCw is used, with w between C and D.
|
||||
// For speed ratio > r2 the poly ABCDx is used, with x between D and E.
|
||||
const int vertices_count = 12;
|
||||
|
||||
video::S3DVertex vertices[vertices_count];
|
||||
|
||||
// The positions for A to J2 are defined here.
|
||||
|
||||
// They are calculated from speedometer.png
|
||||
// A is the center of the speedometer's circle
|
||||
// B2, C, D, E, F, G, H, I and J1 are points on the line
|
||||
// from A to their respective 1/8th threshold division
|
||||
// B2 is 36,9° clockwise from the vertical (on bottom-left)
|
||||
// J1 s 70,7° clockwise from the vertical (on upper-right)
|
||||
// B1 and J2 are used for correct display of the 3D effect
|
||||
// They are 1,13* further than the speedometer farther position because
|
||||
// the lines between them would otherwise cut through the outside circle.
|
||||
|
||||
core::vector2df position[vertices_count];
|
||||
|
||||
position[0].X = 0.546f;//A
|
||||
position[0].Y = 0.566f;//A
|
||||
position[1].X = 0.216f;//B1
|
||||
position[1].Y = 1.036f;//B1
|
||||
position[2].X = 0.201f;//B2
|
||||
position[2].Y = 1.023f;//B2
|
||||
position[3].X = 0.036f;//C
|
||||
position[3].Y = 0.831f;//C
|
||||
position[4].X = -0.029f;//D
|
||||
position[4].Y = 0.589f;//D
|
||||
position[5].X = 0.018f;//E
|
||||
position[5].Y = 0.337f;//E
|
||||
position[6].X = 0.169f;//F
|
||||
position[6].Y = 0.134f;//F
|
||||
position[7].X = 0.391f;//G
|
||||
position[7].Y = 0.014f;//G
|
||||
position[8].X = 0.642f;//H
|
||||
position[8].Y = 0.0f;//H
|
||||
position[9].X = 0.878f;//I
|
||||
position[9].Y = 0.098f;//I
|
||||
position[10].X = 1.046f;//J1
|
||||
position[10].Y = 0.285f;//J1
|
||||
position[11].X = 1.052f;//J2
|
||||
position[11].Y = 0.297f;//J2
|
||||
|
||||
vertices[0].TCoords = core::vector2df(0.7f, 0.5f);
|
||||
vertices[0].Pos = core::vector3df(offset.X+0.7f*meter_width,
|
||||
offset.Y-0.5f*meter_height, 0);
|
||||
vertices[1].TCoords = core::vector2df(0.52f, 1.0f);
|
||||
vertices[1].Pos = core::vector3df(offset.X+0.52f*meter_width, offset.Y, 0);
|
||||
// The speed ratios at which different triangles must be used.
|
||||
// These values should be adjusted in case that the speed display
|
||||
// is not linear enough. Mostly the speed values are below 0.7, it
|
||||
// needs some zipper to get closer to 1.
|
||||
const float r1 = 0.2f;
|
||||
const float r2 = 0.6f;
|
||||
if(speed_ratio<=r1)
|
||||
|
||||
float threshold[vertices_count-2];
|
||||
threshold[0] = 0.00001f;//for the 3D margin
|
||||
threshold[1] = 0.125f;
|
||||
threshold[2] = 0.25f;
|
||||
threshold[3] = 0.375f;
|
||||
threshold[4] = 0.50f;
|
||||
threshold[5] = 0.625f;
|
||||
threshold[6] = 0.750f;
|
||||
threshold[7] = 0.875f;
|
||||
threshold[8] = 0.99999f;//for the 3D margin
|
||||
threshold[9] = 1.0f;
|
||||
|
||||
//3D effect : wait for the full border to appear before drawing
|
||||
for (int i=0;i<8;i++)
|
||||
{
|
||||
count = 3;
|
||||
float f = speed_ratio/r1;
|
||||
vertices[2].TCoords = core::vector2df(0.52f*(1-f), 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X+ (0.52f*(1.0f-f)*meter_width),
|
||||
offset.Y,0);
|
||||
if ((speed_ratio-0.125f*i < 0.00625f && speed_ratio-0.125f*i >= 0.0f) || (0.125f*i-speed_ratio < 0.0045f && 0.125f*i-speed_ratio >= 0.0f) )
|
||||
{
|
||||
speed_ratio = 0.125f*i-0.0045f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(speed_ratio<=r2)
|
||||
{
|
||||
count = 4;
|
||||
float f = (speed_ratio - r1)/(r2-r1);
|
||||
vertices[2].TCoords = core::vector2df(0, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X, offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(0, (1-f));
|
||||
vertices[3].Pos = core::vector3df(offset.X, offset.Y-f*meter_height,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 5;
|
||||
float f = (speed_ratio - r2)/(1-r2);
|
||||
vertices[2].TCoords = core::vector2df(0, 1.0f);
|
||||
vertices[2].Pos = core::vector3df(offset.X, offset.Y, 0);
|
||||
vertices[3].TCoords = core::vector2df(0,0);
|
||||
vertices[3].Pos = core::vector3df(offset.X, offset.Y-meter_height, 0);
|
||||
vertices[4].TCoords = core::vector2df(f, 0);
|
||||
vertices[4].Pos = core::vector3df(offset.X+f*meter_width,
|
||||
offset.Y-meter_height, 0);
|
||||
}
|
||||
short int index[5];
|
||||
|
||||
unsigned int count = computeVerticesForMeter(position, threshold, vertices, vertices_count,
|
||||
speed_ratio, meter_width, meter_height, offset);
|
||||
|
||||
|
||||
short int index[vertices_count];
|
||||
for(unsigned int i=0; i<count; i++)
|
||||
{
|
||||
index[i]=i;
|
||||
@ -876,6 +824,100 @@ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart,
|
||||
#endif
|
||||
} // drawSpeedEnergyRank
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function computes a polygon used for drawing the measure for a meter (speedometer, etc.)
|
||||
* The variable measured by the meter is compared to the thresholds, and is then used to
|
||||
* compute a point between the two points associated with the lower and upper threshold
|
||||
* Then, a polygon is calculated linking all the previous points and the variable point
|
||||
* which link back to the first point. This polygon is used for drawing.
|
||||
*
|
||||
* Consider the following example :
|
||||
*
|
||||
* A E
|
||||
* -|
|
||||
* x
|
||||
* |
|
||||
* -D-|
|
||||
* -w-|
|
||||
* |-C--|
|
||||
* -B--v-|
|
||||
*
|
||||
* If the measure is inferior to the first threshold, the function will create a triangle ABv
|
||||
* with the position of v varying proportionally on a line between B and C ;
|
||||
* at B with 0 and at C when it reaches the first threshold.
|
||||
* If the measure is between the first and second thresholds, the function will create a quad ABCw,
|
||||
* with w varying in the same way than v.
|
||||
* If the measure exceds the higher threshold, the function will return the poly ABCDE.
|
||||
*
|
||||
* \param position The relative positions of the vertices.
|
||||
* \param threshold The thresholds at which the variable point switch from a segment to the next.
|
||||
* The size of this array should be smaller by two than the position array.
|
||||
* The last threshold determines the measure over which the meter is full
|
||||
* \param vertices Where the results of the computation are put, for use by the calling function.
|
||||
* \param vertices_count The maximum number of vertices to use. Should be superior or equal to the
|
||||
* size of the arrays.
|
||||
* \param measure The value of the variable measured by the meter.
|
||||
* \param gauge_width The width of the meter
|
||||
* \param gauge_height The height of the meter
|
||||
* \param offset The offset to position the meter
|
||||
*/
|
||||
unsigned int RaceGUI::computeVerticesForMeter(core::vector2df position[], float threshold[], video::S3DVertex vertices[], unsigned int vertices_count,
|
||||
float measure, int gauge_width, int gauge_height, core::vector2df offset)
|
||||
{
|
||||
//Nothing to draw ; we need at least three points to draw a triangle
|
||||
if (vertices_count <= 2 || measure < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int count=2;
|
||||
float f = 1.0f;
|
||||
|
||||
for (unsigned int i=2 ; i < vertices_count ; i++)
|
||||
{
|
||||
count++;
|
||||
|
||||
//Stop when we have found between which thresholds the measure is
|
||||
if (measure < threshold[i-2])
|
||||
{
|
||||
if (i-2 == 0)
|
||||
{
|
||||
f = measure/threshold[i-2];
|
||||
}
|
||||
else
|
||||
{
|
||||
f = (measure - threshold[i-3])/(threshold[i-2]-threshold[i-3]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i=0 ; i < count ; i++)
|
||||
{
|
||||
//if the measure don't fall in this segment, use the next predefined point
|
||||
if (i<count-1 || (count == vertices_count && f == 1.0f))
|
||||
{
|
||||
vertices[i].TCoords = core::vector2df(position[i].X, position[i].Y);
|
||||
vertices[i].Pos = core::vector3df(offset.X+position[i].X*gauge_width,
|
||||
offset.Y-(1-position[i].Y)*gauge_height, 0);
|
||||
}
|
||||
//if the measure fall in this segment, compute the variable position
|
||||
else
|
||||
{
|
||||
//f : the proportion of the next point. 1-f : the proportion of the previous point
|
||||
vertices[i].TCoords = core::vector2df(position[i].X*(f)+position[i-1].X*(1.0f-f),
|
||||
position[i].Y*(f)+position[i-1].Y*(1.0f-f));
|
||||
vertices[i].Pos = core::vector3df(offset.X+ ((position[i].X*(f)+position[i-1].X*(1.0f-f))*gauge_width),
|
||||
offset.Y-(((1-position[i].Y)*(f)+(1-position[i-1].Y)*(1.0f-f))*gauge_height),0);
|
||||
}
|
||||
}
|
||||
|
||||
//the count is used in the drawing functions
|
||||
return count;
|
||||
} //computeVerticesForMeter
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Displays the rank and the lap of the kart.
|
||||
* \param info Info object c
|
||||
|
@ -109,6 +109,12 @@ private:
|
||||
float min_ratio, int meter_width,
|
||||
int meter_height, float dt);
|
||||
|
||||
/* Helper function for drawing meters */
|
||||
|
||||
unsigned int computeVerticesForMeter(core::vector2df position[], float threshold[], video::S3DVertex vertices[],
|
||||
unsigned int vertices_count, float measure, int gauge_width,
|
||||
int gauge_height, core::vector2df offset);
|
||||
|
||||
/** Display items that are shown once only (for all karts). */
|
||||
void drawGlobalMiniMap ();
|
||||
void drawGlobalTimer ();
|
||||
|
@ -327,10 +327,10 @@ void RaceGUIMultitouch::draw(const AbstractKart* kart,
|
||||
m_race_gui != NULL)
|
||||
{
|
||||
float scale = UserConfigParams::m_multitouch_scale *
|
||||
(float)(irr_driver->getActualScreenSize().Height) / 720.0f;
|
||||
(float)(irr_driver->getActualScreenSize().Height) / 760.0f;
|
||||
|
||||
m_race_gui->drawEnergyMeter(int(button->x + button->width * 1.15f),
|
||||
int(button->y + button->height * 1.35f),
|
||||
int(button->y + button->height * 1.15f),
|
||||
kart, viewport,
|
||||
core::vector2df(scale, scale));
|
||||
}
|
||||
|