Little Bits
-=-=-=-=-=- -Fixed small bugs all around -Added ability to show/hide entire sections of the spatial (3D) tree -WIP new vehicle (not ready yet) based on Bullet
This commit is contained in:
parent
c3e1d7b7c7
commit
2ee4ac183b
56 changed files with 3943 additions and 1757 deletions
|
@ -264,6 +264,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
|
|||
//VCALL_LOCALMEM2R(String,erase);
|
||||
VCALL_LOCALMEM0R(String,hash);
|
||||
VCALL_LOCALMEM0R(String,md5_text);
|
||||
VCALL_LOCALMEM0R(String,md5_buffer);
|
||||
VCALL_LOCALMEM0R(String,empty);
|
||||
VCALL_LOCALMEM0R(String,is_abs_path);
|
||||
VCALL_LOCALMEM0R(String,is_rel_path);
|
||||
|
@ -573,7 +574,6 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
|
|||
VCALL_PTR0R( Matrix32, affine_inverse );
|
||||
VCALL_PTR0R( Matrix32, get_rotation );
|
||||
VCALL_PTR0R( Matrix32, get_origin );
|
||||
VCALL_PTR0R( Matrix32, get_scale );
|
||||
VCALL_PTR0R( Matrix32, orthonormalized );
|
||||
VCALL_PTR1R( Matrix32, rotated );
|
||||
VCALL_PTR1R( Matrix32, scaled );
|
||||
|
@ -1167,7 +1167,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
|
|||
ADDFUNC1(STRING,STRING,String,ord_at,INT,"at",varray());
|
||||
// ADDFUNC2(STRING,String,erase,INT,INT,varray());
|
||||
ADDFUNC0(STRING,INT,String,hash,varray());
|
||||
ADDFUNC0(STRING,STRING,String,md5_text,varray());
|
||||
ADDFUNC0(STRING,INT,String,md5_text,varray());
|
||||
ADDFUNC0(STRING,INT,String,md5_buffer,varray());
|
||||
ADDFUNC0(STRING,BOOL,String,empty,varray());
|
||||
ADDFUNC0(STRING,BOOL,String,is_abs_path,varray());
|
||||
ADDFUNC0(STRING,BOOL,String,is_rel_path,varray());
|
||||
|
@ -1390,7 +1391,6 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
|
|||
ADDFUNC0(MATRIX32,MATRIX32,Matrix32,affine_inverse,varray());
|
||||
ADDFUNC0(MATRIX32,REAL,Matrix32,get_rotation,varray());
|
||||
ADDFUNC0(MATRIX32,VECTOR2,Matrix32,get_origin,varray());
|
||||
ADDFUNC0(MATRIX32,VECTOR2,Matrix32,get_scale,varray());
|
||||
ADDFUNC0(MATRIX32,MATRIX32,Matrix32,orthonormalized,varray());
|
||||
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,rotated,REAL,"phi",varray());
|
||||
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,scaled,VECTOR2,"scale",varray());
|
||||
|
|
|
@ -82,6 +82,8 @@
|
|||
|
||||
#endif
|
||||
|
||||
static RasterizerGLES2* _singleton = NULL;
|
||||
|
||||
static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN};
|
||||
|
||||
_FORCE_INLINE_ static void _set_color_attrib(const Color& p_color) {
|
||||
|
@ -381,39 +383,96 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
|
|||
} break;
|
||||
case Image::FORMAT_BC1: {
|
||||
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
r_compressed=true;
|
||||
if (!s3tc_supported) {
|
||||
|
||||
if (!image.empty()) {
|
||||
image.decompress();
|
||||
}
|
||||
r_gl_components=4;
|
||||
r_gl_format=GL_RGBA;
|
||||
r_has_alpha_cache=true;
|
||||
|
||||
} else {
|
||||
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
r_compressed=true;
|
||||
};
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_BC2: {
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
r_has_alpha_cache=true;
|
||||
r_compressed=true;
|
||||
|
||||
if (!s3tc_supported) {
|
||||
|
||||
if (!image.empty()) {
|
||||
image.decompress();
|
||||
}
|
||||
r_gl_components=4;
|
||||
r_gl_format=GL_RGBA;
|
||||
r_has_alpha_cache=true;
|
||||
|
||||
} else {
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
r_has_alpha_cache=true;
|
||||
r_compressed=true;
|
||||
};
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_BC3: {
|
||||
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
r_has_alpha_cache=true;
|
||||
r_compressed=true;
|
||||
if (!s3tc_supported) {
|
||||
|
||||
if (!image.empty()) {
|
||||
image.decompress();
|
||||
}
|
||||
r_gl_components=4;
|
||||
r_gl_format=GL_RGBA;
|
||||
r_has_alpha_cache=true;
|
||||
|
||||
} else {
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
r_has_alpha_cache=true;
|
||||
r_compressed=true;
|
||||
};
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_BC4: {
|
||||
|
||||
r_gl_format=_EXT_COMPRESSED_RED_RGTC1;
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_compressed=true;
|
||||
if (!s3tc_supported) {
|
||||
|
||||
if (!image.empty()) {
|
||||
image.decompress();
|
||||
}
|
||||
r_gl_components=4;
|
||||
r_gl_format=GL_RGBA;
|
||||
r_has_alpha_cache=true;
|
||||
|
||||
} else {
|
||||
|
||||
r_gl_format=_EXT_COMPRESSED_RED_RGTC1;
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_compressed=true;
|
||||
};
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_BC5: {
|
||||
|
||||
if (!s3tc_supported) {
|
||||
|
||||
r_gl_format=_EXT_COMPRESSED_RG_RGTC2;
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_compressed=true;
|
||||
if (!image.empty()) {
|
||||
image.decompress();
|
||||
}
|
||||
r_gl_components=4;
|
||||
r_gl_format=GL_RGBA;
|
||||
r_has_alpha_cache=true;
|
||||
|
||||
} else {
|
||||
r_gl_format=_EXT_COMPRESSED_RG_RGTC2;
|
||||
r_gl_components=1; //doesn't matter much
|
||||
r_compressed=true;
|
||||
};
|
||||
} break;
|
||||
case Image::FORMAT_PVRTC2: {
|
||||
|
||||
|
@ -1078,6 +1137,15 @@ void RasterizerGLES2::texture_set_reload_hook(RID p_texture,ObjectID p_owner,con
|
|||
}
|
||||
|
||||
|
||||
GLuint RasterizerGLES2::_texture_get_name(RID p_tex) {
|
||||
|
||||
Texture * texture = texture_owner.get(p_tex);
|
||||
ERR_FAIL_COND_V(!texture, 0);
|
||||
|
||||
return texture->tex_id;
|
||||
};
|
||||
|
||||
|
||||
/* SHADER API */
|
||||
|
||||
RID RasterizerGLES2::shader_create(VS::ShaderMode p_mode) {
|
||||
|
@ -3995,17 +4063,17 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
|
|||
if (p_shader->mode==VS::SHADER_MATERIAL) {
|
||||
//print_line("setting code to id.. "+itos(p_shader->custom_code_id));
|
||||
Vector<const char*> enablers;
|
||||
if (fragment_flags.use_color_interp)
|
||||
if (fragment_flags.use_color_interp || vertex_flags.use_color_interp)
|
||||
enablers.push_back("#define ENABLE_COLOR_INTERP\n");
|
||||
if (fragment_flags.use_uv_interp)
|
||||
if (fragment_flags.use_uv_interp || vertex_flags.use_uv_interp)
|
||||
enablers.push_back("#define ENABLE_UV_INTERP\n");
|
||||
if (fragment_flags.use_uv2_interp)
|
||||
if (fragment_flags.use_uv2_interp || vertex_flags.use_uv2_interp)
|
||||
enablers.push_back("#define ENABLE_UV2_INTERP\n");
|
||||
if (fragment_flags.use_tangent_interp)
|
||||
if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp)
|
||||
enablers.push_back("#define ENABLE_TANGENT_INTERP\n");
|
||||
if (fragment_flags.use_var1_interp)
|
||||
if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp)
|
||||
enablers.push_back("#define ENABLE_VAR1_INTERP\n");
|
||||
if (fragment_flags.use_var2_interp)
|
||||
if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp)
|
||||
enablers.push_back("#define ENABLE_VAR2_INTERP\n");
|
||||
if (fragment_flags.uses_texscreen) {
|
||||
enablers.push_back("#define ENABLE_TEXSCREEN\n");
|
||||
|
@ -4444,6 +4512,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
|
|||
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter==SHADOW_FILTER_PCF5 || shadow_filter==SHADOW_FILTER_PCF13);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]);
|
||||
|
||||
if (p_opaque_pass && p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) {
|
||||
|
||||
|
@ -4716,7 +4785,8 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) {
|
|||
|
||||
}
|
||||
//print_line("shadow split: "+rtos(li->shadow_split));
|
||||
} else
|
||||
}
|
||||
|
||||
material_shader.set_uniform(MaterialShaderGLES2::SHADOW_DARKENING,li->base->vars[VS::LIGHT_PARAM_SHADOW_DARKENING]);
|
||||
//matrix
|
||||
|
||||
|
@ -5545,6 +5615,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
const Skeleton *prev_skeleton =NULL;
|
||||
uint8_t prev_sort_flags=0xFF;
|
||||
const BakedLightData *prev_baked_light=NULL;
|
||||
RID prev_baked_light_texture;
|
||||
|
||||
Geometry::Type prev_geometry_type=Geometry::GEOMETRY_INVALID;
|
||||
|
||||
|
@ -5561,6 +5632,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false);
|
||||
// material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_TEXTURE,false);
|
||||
|
||||
}
|
||||
|
@ -5585,6 +5657,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
|
||||
bool rebind=false;
|
||||
bool bind_baked_light_octree=false;
|
||||
bool bind_baked_lightmap=false;
|
||||
bool additive=false;
|
||||
|
||||
|
||||
|
@ -5704,7 +5777,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
}
|
||||
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false);
|
||||
// material_shader.set_conditional(MaterialShaderGLES2::USE_AMBIENT_TEXTURE,false);
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false);
|
||||
|
||||
if (!additive && baked_light) {
|
||||
|
||||
|
@ -5722,7 +5795,37 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
}
|
||||
} else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) {
|
||||
|
||||
//material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_TEXTURE,true);
|
||||
|
||||
int lightmap_idx = e->instance->baked_lightmap_id;
|
||||
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false);
|
||||
bind_baked_lightmap=false;
|
||||
|
||||
|
||||
if (baked_light->lightmaps.has(lightmap_idx)) {
|
||||
|
||||
|
||||
RID texid = baked_light->lightmaps[lightmap_idx];
|
||||
|
||||
if (prev_baked_light!=baked_light || texid!=prev_baked_light_texture) {
|
||||
|
||||
|
||||
Texture *tex = texture_owner.get(texid);
|
||||
if (tex) {
|
||||
|
||||
glActiveTexture(GL_TEXTURE5);
|
||||
glBindTexture(tex->target,tex->tex_id); //bind the texture
|
||||
}
|
||||
|
||||
prev_baked_light_texture=texid;
|
||||
}
|
||||
|
||||
if (texid.is_valid()) {
|
||||
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,true);
|
||||
bind_baked_lightmap=true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5793,6 +5896,14 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
|
||||
}
|
||||
|
||||
if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) {
|
||||
|
||||
material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, 5);
|
||||
material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier);
|
||||
|
||||
}
|
||||
|
||||
|
||||
_set_cull(e->mirror,p_reverse_cull);
|
||||
|
||||
|
||||
|
@ -8212,9 +8323,13 @@ void RasterizerGLES2::_update_framebuffer() {
|
|||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::set_base_framebuffer(GLuint p_id) {
|
||||
void RasterizerGLES2::set_base_framebuffer(GLuint p_id, Vector2 p_size) {
|
||||
|
||||
base_framebuffer=p_id;
|
||||
|
||||
if (p_size.x != 0) {
|
||||
window_size = p_size;
|
||||
};
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -8753,8 +8868,15 @@ void RasterizerGLES2::set_use_framebuffers(bool p_use) {
|
|||
use_framebuffers=p_use;
|
||||
}
|
||||
|
||||
RasterizerGLES2* RasterizerGLES2::get_singleton() {
|
||||
|
||||
return _singleton;
|
||||
};
|
||||
|
||||
RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,bool p_default_fragment_lighting,bool p_use_reload_hooks) {
|
||||
|
||||
_singleton = this;
|
||||
|
||||
keep_copies=p_keep_ram_copy;
|
||||
use_reload_hooks=p_use_reload_hooks;
|
||||
pack_arrays=p_compress_arrays;
|
||||
|
|
|
@ -1175,6 +1175,8 @@ public:
|
|||
virtual void texture_set_size_override(RID p_texture,int p_width, int p_height);
|
||||
virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const;
|
||||
|
||||
GLuint _texture_get_name(RID p_tex);
|
||||
|
||||
/* SHADER API */
|
||||
|
||||
virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL);
|
||||
|
@ -1508,7 +1510,7 @@ public:
|
|||
|
||||
virtual int get_render_info(VS::RenderInfo p_info);
|
||||
|
||||
void set_base_framebuffer(GLuint p_id);
|
||||
void set_base_framebuffer(GLuint p_id, Vector2 p_size = Vector2(0, 0));
|
||||
|
||||
virtual void flush_frame(); //not necesary in most cases
|
||||
void set_extensions(const char *p_strings);
|
||||
|
@ -1520,6 +1522,7 @@ public:
|
|||
|
||||
virtual bool has_feature(VS::Features p_feature) const;
|
||||
|
||||
static RasterizerGLES2* get_singleton();
|
||||
|
||||
RasterizerGLES2(bool p_compress_arrays=false,bool p_keep_ram_copy=true,bool p_default_fragment_lighting=true,bool p_use_reload_hooks=false);
|
||||
virtual ~RasterizerGLES2();
|
||||
|
|
|
@ -150,6 +150,26 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
|
|||
if (vnode->name==vname_vertex && p_assign_left) {
|
||||
vertex_code_writes_vertex=true;
|
||||
}
|
||||
if (vnode->name==vname_color_interp) {
|
||||
flags->use_color_interp=true;
|
||||
}
|
||||
if (vnode->name==vname_uv_interp) {
|
||||
flags->use_uv_interp=true;
|
||||
}
|
||||
if (vnode->name==vname_uv2_interp) {
|
||||
flags->use_uv2_interp=true;
|
||||
}
|
||||
if (vnode->name==vname_var1_interp) {
|
||||
flags->use_var1_interp=true;
|
||||
}
|
||||
if (vnode->name==vname_var2_interp) {
|
||||
flags->use_var2_interp=true;
|
||||
}
|
||||
if (vnode->name==vname_tangent_interp || vnode->name==vname_binormal_interp) {
|
||||
flags->use_tangent_interp=true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) {
|
||||
|
||||
|
@ -614,6 +634,11 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
|
|||
replace_table["texscreen"]= "texscreen";
|
||||
replace_table["texpos"]= "texpos";
|
||||
|
||||
mode_replace_table[0]["SRC_VERTEX"]="vertex_in.xyz";
|
||||
mode_replace_table[0]["SRC_NORMAL"]="normal_in";
|
||||
mode_replace_table[0]["SRC_TANGENT"]="tangent_in";
|
||||
mode_replace_table[0]["SRC_BINORMALF"]="binormalf";
|
||||
|
||||
mode_replace_table[0]["VERTEX"]="vertex_interp";
|
||||
mode_replace_table[0]["NORMAL"]="normal_interp";
|
||||
mode_replace_table[0]["TANGENT"]="tangent_interp";
|
||||
|
@ -626,6 +651,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
|
|||
mode_replace_table[0]["WORLD_MATRIX"]="world_transform";
|
||||
mode_replace_table[0]["INV_CAMERA_MATRIX"]="camera_inverse_transform";
|
||||
mode_replace_table[0]["PROJECTION_MATRIX"]="projection_transform";
|
||||
mode_replace_table[0]["MODELVIEW_MATRIX"]="modelview";
|
||||
mode_replace_table[0]["POINT_SIZE"]="gl_PointSize";
|
||||
mode_replace_table[0]["VAR1"]="var1_interp";
|
||||
mode_replace_table[0]["VAR2"]="var2_interp";
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
from VisualServer:
|
||||
|
||||
|
@ -22,6 +25,26 @@ ARRAY_WEIGHTS=7,
|
|||
ARRAY_INDEX=8,
|
||||
*/
|
||||
|
||||
//hack to use uv if no uv present so it works with lightmap
|
||||
#ifdef ENABLE_AMBIENT_LIGHTMAP
|
||||
|
||||
#ifdef USE_LIGHTMAP_ON_UV2
|
||||
|
||||
#ifndef ENABLE_UV2_INTERP
|
||||
#define ENABLE_UV2_INTERP
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef ENABLE_UV_INTERP
|
||||
#define ENABLE_UV_INTERP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* INPUT ATTRIBS */
|
||||
|
||||
attribute highp vec4 vertex_attrib; // attrib:0
|
||||
|
@ -238,6 +261,7 @@ void main() {
|
|||
#if defined(ENABLE_TANGENT_INTERP)
|
||||
vec3 tangent_in = tangent_attrib.xyz;
|
||||
tangent_in*=normal_mult;
|
||||
float binormalf = tangent_attrib.a;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SKELETON
|
||||
|
@ -272,7 +296,7 @@ void main() {
|
|||
|
||||
#if defined(ENABLE_TANGENT_INTERP)
|
||||
tangent_interp=normalize(tangent_in);
|
||||
binormal_interp = normalize( cross(normal_interp,tangent_interp) * tangent_attrib.a );
|
||||
binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf );
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_UV_INTERP)
|
||||
|
@ -453,6 +477,27 @@ precision mediump int;
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
//hack to use uv if no uv present so it works with lightmap
|
||||
#ifdef ENABLE_AMBIENT_LIGHTMAP
|
||||
|
||||
#ifdef USE_LIGHTMAP_ON_UV2
|
||||
|
||||
#ifndef ENABLE_UV2_INTERP
|
||||
#define ENABLE_UV2_INTERP
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef ENABLE_UV_INTERP
|
||||
#define ENABLE_UV_INTERP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Varyings */
|
||||
|
||||
#if defined(ENABLE_COLOR_INTERP)
|
||||
|
@ -545,6 +590,13 @@ uniform int ambient_octree_steps;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMBIENT_LIGHTMAP
|
||||
|
||||
uniform highp sampler2D ambient_lightmap;
|
||||
uniform float ambient_lightmap_multiplier;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
|
||||
|
@ -783,6 +835,34 @@ FRAGMENT_SHADER_CODE
|
|||
}
|
||||
#endif
|
||||
|
||||
float shadow_attenuation = 1.0;
|
||||
|
||||
#ifdef ENABLE_AMBIENT_LIGHTMAP
|
||||
|
||||
vec3 ambientmap_color = vec3(0.0,0.0,0.0);
|
||||
vec2 ambientmap_uv = vec2(0.0,0.0);
|
||||
|
||||
#ifdef USE_LIGHTMAP_ON_UV2
|
||||
|
||||
ambientmap_uv = uv2_interp;
|
||||
|
||||
#else
|
||||
|
||||
ambientmap_uv = uv_interp;
|
||||
|
||||
#endif
|
||||
|
||||
vec4 amcol = texture2D(ambient_lightmap,ambientmap_uv);
|
||||
shadow_attenuation=amcol.a;
|
||||
ambientmap_color = amcol.rgb;
|
||||
ambientmap_color*=ambient_lightmap_multiplier;
|
||||
ambientmap_color*=diffuse.rgb;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_AMBIENT_OCTREE
|
||||
|
||||
vec3 ambientmap_color = vec3(0.0,0.0,0.0);
|
||||
|
@ -828,7 +908,7 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#endif
|
||||
|
||||
float shadow_attenuation = 1.0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1120,7 +1200,7 @@ LIGHT_SHADER_CODE
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_AMBIENT_OCTREE
|
||||
#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP)
|
||||
|
||||
diffuse.rgb+=ambientmap_color;
|
||||
#endif
|
||||
|
|
|
@ -1443,7 +1443,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
|||
}
|
||||
|
||||
|
||||
print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size()));
|
||||
//print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size()));
|
||||
|
||||
|
||||
for(int i=0;i<p_class->variables.size();i++) {
|
||||
|
|
|
@ -349,12 +349,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
|||
io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
|
||||
GodotLib.io=io;
|
||||
Log.d("GODOT", "command_line is null? " + ((command_line == null)?"yes":"no"));
|
||||
if(command_line != null){
|
||||
/*if(command_line != null){
|
||||
Log.d("GODOT", "Command Line:");
|
||||
for(int w=0;w <command_line.length;w++){
|
||||
Log.d("GODOT"," " + command_line[w]);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
GodotLib.initialize(this,io.needsReloadHooks(),command_line);
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
|
@ -418,12 +418,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
|||
}
|
||||
|
||||
if (new_args.isEmpty()){
|
||||
Log.d("GODOT", "new_args is empty");
|
||||
command_line=null;
|
||||
}else{
|
||||
Log.d("GODOT", "new_args is not empty");
|
||||
|
||||
command_line = new_args.toArray(new String[new_args.size()]);
|
||||
Log.d("GODOT", "command line is null? " + ( (command_line == null) ? "yes":"no"));
|
||||
}
|
||||
if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) {
|
||||
//check that environment is ok!
|
||||
|
@ -461,7 +459,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
|||
}
|
||||
|
||||
if (!pack_valid) {
|
||||
Log.d("GODOT", "Tengo que bajarme el apk");
|
||||
Log.d("GODOT", "Pack Invalid, try re-downloading.");
|
||||
|
||||
Intent notifierIntent = new Intent(this, this.getClass());
|
||||
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||
|
@ -472,7 +470,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
|||
|
||||
int startResult;
|
||||
try {
|
||||
Log.d("GODOT", "INICIANDO DOWNLOAD SERVICE");
|
||||
Log.d("GODOT", "INITIALIZING DOWNLOAD");
|
||||
startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
|
||||
getApplicationContext(),
|
||||
pendingIntent,
|
||||
|
|
|
@ -32,9 +32,9 @@ abstract public class GenericConsumeTask extends AsyncTask<String, String, Strin
|
|||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
try {
|
||||
Log.d("godot", "Requesting to consume an item with token ." + token);
|
||||
// Log.d("godot", "Requesting to consume an item with token ." + token);
|
||||
int response = mService.consumePurchase(3, context.getPackageName(), token);
|
||||
Log.d("godot", "consumePurchase response: " + response);
|
||||
// Log.d("godot", "consumePurchase response: " + response);
|
||||
if(response == 0 || response == 8){
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,19 +28,19 @@ abstract public class HandlePurchaseTask {
|
|||
|
||||
|
||||
public void handlePurchaseRequest(int resultCode, Intent data){
|
||||
Log.d("XXX", "Handling purchase response");
|
||||
// Log.d("XXX", "Handling purchase response");
|
||||
// int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
|
||||
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
|
||||
Log.d("XXX", "Purchase data:" + purchaseData);
|
||||
// Log.d("XXX", "Purchase data:" + purchaseData);
|
||||
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
|
||||
Log.d("XXX", "Purchase signature:" + dataSignature);
|
||||
//Log.d("XXX", "Purchase signature:" + dataSignature);
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
||||
try {
|
||||
Log.d("SARLANGA", purchaseData);
|
||||
// Log.d("SARLANGA", purchaseData);
|
||||
|
||||
|
||||
JSONObject jo = new JSONObject(purchaseData);
|
||||
|
@ -58,7 +58,7 @@ abstract public class HandlePurchaseTask {
|
|||
error("Untrusted callback");
|
||||
return;
|
||||
}
|
||||
Log.d("XXX", "Este es el product ID:" + productId);
|
||||
// Log.d("XXX", "Este es el product ID:" + productId);
|
||||
pc.setConsumableValue("ticket_signautre", productId, dataSignature);
|
||||
pc.setConsumableValue("ticket", productId, purchaseData);
|
||||
pc.setConsumableFlag("block", productId, true);
|
||||
|
|
|
@ -31,14 +31,14 @@ public class PaymentsCache {
|
|||
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPref.edit();
|
||||
editor.putString(sku, value);
|
||||
Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
|
||||
// Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public String getConsumableValue(String set, String sku){
|
||||
SharedPreferences sharedPref = context.getSharedPreferences(
|
||||
"consumables_" + set, Context.MODE_PRIVATE);
|
||||
Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
|
||||
// Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
|
||||
return sharedPref.getString(sku, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@ abstract public class ReleaseAllConsumablesTask {
|
|||
|
||||
public void consumeItAll(){
|
||||
try{
|
||||
Log.d("godot", "consumeItall for " + context.getPackageName());
|
||||
// Log.d("godot", "consumeItall for " + context.getPackageName());
|
||||
Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp",null);
|
||||
|
||||
for (String key : bundle.keySet()) {
|
||||
Object value = bundle.get(key);
|
||||
Log.d("godot", String.format("%s %s (%s)", key,
|
||||
value.toString(), value.getClass().getName()));
|
||||
// Log.d("godot", String.format("%s %s (%s)", key,
|
||||
// value.toString(), value.getClass().getName()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,13 +45,13 @@ abstract public class ReleaseAllConsumablesTask {
|
|||
|
||||
|
||||
if (myPurchases == null || myPurchases.size() == 0){
|
||||
Log.d("godot", "No purchases!");
|
||||
// Log.d("godot", "No purchases!");
|
||||
notRequired();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Log.d("godot", "# products to be consumed:" + myPurchases.size());
|
||||
// Log.d("godot", "# products to be consumed:" + myPurchases.size());
|
||||
for (int i=0;i<myPurchases.size();i++)
|
||||
{
|
||||
|
||||
|
@ -61,7 +61,7 @@ abstract public class ReleaseAllConsumablesTask {
|
|||
String sku = inappPurchaseData.getString("productId");
|
||||
String token = inappPurchaseData.getString("purchaseToken");
|
||||
String signature = mySignatures.get(i);
|
||||
Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
|
||||
// Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
|
||||
new GenericConsumeTask(context, mService, sku, receipt,signature, token) {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1577,14 +1577,14 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env
|
|||
int count = env->GetArrayLength(params);
|
||||
Variant args[VARIANT_ARG_MAX];
|
||||
|
||||
print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
|
||||
// print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
|
||||
|
||||
for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) {
|
||||
|
||||
jobject obj = env->GetObjectArrayElement(params, i);
|
||||
if (obj)
|
||||
args[i] = _jobject_to_variant(env, obj);
|
||||
print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
|
||||
// print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,10 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (area)
|
||||
Physics2DServer::get_singleton()->area_set_transform(rid,get_global_transform());
|
||||
else
|
||||
Physics2DServer::get_singleton()->body_set_state(rid,Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
RID space = get_world_2d()->get_space();
|
||||
if (area) {
|
||||
|
|
|
@ -129,6 +129,9 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
|
|||
if (!get_scene())
|
||||
return;
|
||||
|
||||
if (p_event.device != 0)
|
||||
return;
|
||||
|
||||
if (passby_press) {
|
||||
|
||||
if (p_event.type==InputEvent::SCREEN_TOUCH && !p_event.screen_touch.pressed && finger_pressed==p_event.screen_touch.index) {
|
||||
|
|
|
@ -460,7 +460,7 @@ void Light::_bind_methods() {
|
|||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/enabled"), _SCS("set_enabled"), _SCS("is_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Indirect+Shadows,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode"));
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY );
|
||||
/*
|
||||
if (type == VisualServer::LIGHT_OMNI || type == VisualServer::LIGHT_SPOT) {
|
||||
|
@ -477,7 +477,7 @@ void Light::_bind_methods() {
|
|||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "colors/diffuse"), _SCS("set_color"), _SCS("get_color"),COLOR_DIFFUSE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "colors/specular"), _SCS("set_color"), _SCS("get_color"),COLOR_SPECULAR);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/shadow"), _SCS("set_project_shadows"), _SCS("has_project_shadows"));
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/esm_multiplier", PROPERTY_HINT_RANGE, "1.0,512.0,0.1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_ESM_MULTIPLIER);
|
||||
|
@ -498,6 +498,12 @@ void Light::_bind_methods() {
|
|||
BIND_CONSTANT( COLOR_DIFFUSE );
|
||||
BIND_CONSTANT( COLOR_SPECULAR );
|
||||
|
||||
BIND_CONSTANT( BAKE_MODE_DISABLED );
|
||||
BIND_CONSTANT( BAKE_MODE_INDIRECT );
|
||||
BIND_CONSTANT( BAKE_MODE_INDIRECT_AND_SHADOWS );
|
||||
BIND_CONSTANT( BAKE_MODE_FULL );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
|
||||
BAKE_MODE_DISABLED,
|
||||
BAKE_MODE_INDIRECT,
|
||||
BAKE_MODE_INDIRECT_AND_SHADOWS,
|
||||
BAKE_MODE_FULL
|
||||
|
||||
};
|
||||
|
|
|
@ -180,7 +180,7 @@ void Navigation::navmesh_remove(int p_id){
|
|||
|
||||
}
|
||||
|
||||
Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end) {
|
||||
Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end, bool p_optimize) {
|
||||
|
||||
|
||||
Polygon *begin_poly=NULL;
|
||||
|
@ -332,25 +332,113 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector
|
|||
|
||||
if (found_route) {
|
||||
|
||||
//use midpoints for now
|
||||
Polygon *p=end_poly;
|
||||
Vector<Vector3> path;
|
||||
path.push_back(end_point);
|
||||
while(true) {
|
||||
int prev = p->prev_edge;
|
||||
int prev_n = (p->prev_edge+1)%p->edges.size();
|
||||
Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5;
|
||||
path.push_back(point);
|
||||
p = p->edges[prev].C;
|
||||
if (p==begin_poly)
|
||||
break;
|
||||
|
||||
if (p_optimize) {
|
||||
//string pulling
|
||||
|
||||
Polygon *apex_poly=end_poly;
|
||||
Vector3 apex_point=end_point;
|
||||
Vector3 portal_left=apex_point;
|
||||
Vector3 portal_right=apex_point;
|
||||
Polygon *left_poly=end_poly;
|
||||
Polygon *right_poly=end_poly;
|
||||
Polygon *p=end_poly;
|
||||
path.push_back(end_point);
|
||||
|
||||
while(p) {
|
||||
|
||||
Vector3 left;
|
||||
Vector3 right;
|
||||
|
||||
#define CLOCK_TANGENT(m_a,m_b,m_c) ( ((m_a)-(m_c)).cross((m_a)-(m_b)) )
|
||||
|
||||
if (p==begin_poly) {
|
||||
left=begin_point;
|
||||
right=begin_point;
|
||||
} else {
|
||||
int prev = p->prev_edge;
|
||||
int prev_n = (p->prev_edge+1)%p->edges.size();
|
||||
left = _get_vertex(p->edges[prev].point);
|
||||
right = _get_vertex(p->edges[prev_n].point);
|
||||
|
||||
if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){
|
||||
SWAP(left,right);
|
||||
}
|
||||
}
|
||||
|
||||
bool skip=false;
|
||||
|
||||
|
||||
if (CLOCK_TANGENT(apex_point,portal_left,left).dot(up) >= 0){
|
||||
//process
|
||||
if (portal_left==apex_point || CLOCK_TANGENT(apex_point,left,portal_right).dot(up) > 0) {
|
||||
left_poly=p;
|
||||
portal_left=left;
|
||||
} else {
|
||||
|
||||
apex_point=portal_right;
|
||||
p=right_poly;
|
||||
left_poly=p;
|
||||
portal_left=apex_point;
|
||||
portal_right=apex_point;
|
||||
path.push_back(apex_point);
|
||||
skip=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip && CLOCK_TANGENT(apex_point,portal_right,right).dot(up) <= 0){
|
||||
//process
|
||||
if (portal_right==apex_point || CLOCK_TANGENT(apex_point,right,portal_left).dot(up) < 0) {
|
||||
right_poly=p;
|
||||
portal_right=right;
|
||||
} else {
|
||||
|
||||
apex_point=portal_left;
|
||||
p=left_poly;
|
||||
right_poly=p;
|
||||
portal_right=apex_point;
|
||||
portal_left=apex_point;
|
||||
path.push_back(apex_point);
|
||||
}
|
||||
}
|
||||
|
||||
if (p!=begin_poly)
|
||||
p=p->edges[p->prev_edge].C;
|
||||
else
|
||||
p=NULL;
|
||||
|
||||
}
|
||||
|
||||
if (path[path.size()-1]!=begin_point)
|
||||
path.push_back(begin_point);
|
||||
|
||||
path.invert();
|
||||
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
//midpoints
|
||||
Polygon *p=end_poly;
|
||||
|
||||
path.push_back(end_point);
|
||||
while(true) {
|
||||
int prev = p->prev_edge;
|
||||
int prev_n = (p->prev_edge+1)%p->edges.size();
|
||||
Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5;
|
||||
path.push_back(point);
|
||||
p = p->edges[prev].C;
|
||||
if (p==begin_poly)
|
||||
break;
|
||||
}
|
||||
|
||||
path.push_back(begin_point);
|
||||
|
||||
|
||||
path.invert();;
|
||||
}
|
||||
|
||||
path.push_back(begin_point);
|
||||
|
||||
|
||||
path.invert();;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -475,17 +563,33 @@ Vector3 Navigation::get_closest_point_normal(const Vector3& p_point){
|
|||
}
|
||||
|
||||
|
||||
void Navigation::set_up_vector(const Vector3& p_up) {
|
||||
|
||||
|
||||
up=p_up;
|
||||
}
|
||||
|
||||
Vector3 Navigation::get_up_vector() const{
|
||||
|
||||
return up;
|
||||
}
|
||||
|
||||
|
||||
void Navigation::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create);
|
||||
ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
|
||||
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_simple_path","start","end"),&Navigation::get_simple_path);
|
||||
ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true));
|
||||
ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end"),&Navigation::get_closest_point_to_segment);
|
||||
ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point);
|
||||
ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_up_vector","up"),&Navigation::set_up_vector);
|
||||
ObjectTypeDB::bind_method(_MD("get_up_vector"),&Navigation::get_up_vector);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"up_vector"),_SCS("set_up_vector"),_SCS("get_up_vector"));
|
||||
}
|
||||
|
||||
Navigation::Navigation() {
|
||||
|
@ -493,5 +597,7 @@ Navigation::Navigation() {
|
|||
ERR_FAIL_COND( sizeof(Point)!=8 );
|
||||
cell_size=0.01; //one centimeter
|
||||
last_id=1;
|
||||
up=Vector3(0,1,0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -103,6 +103,8 @@ class Navigation : public Spatial {
|
|||
return Vector3(p_point.x,p_point.y,p_point.z)*cell_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _navmesh_link(int p_id);
|
||||
void _navmesh_unlink(int p_id);
|
||||
|
||||
|
@ -110,18 +112,23 @@ class Navigation : public Spatial {
|
|||
Map<int,NavMesh> navmesh_map;
|
||||
int last_id;
|
||||
|
||||
Vector3 up;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_up_vector(const Vector3& p_up);
|
||||
Vector3 get_up_vector() const;
|
||||
|
||||
//API should be as dynamic as possible
|
||||
int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform);
|
||||
void navmesh_set_transform(int p_id, const Transform& p_xform);
|
||||
void navmesh_remove(int p_id);
|
||||
|
||||
Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end);
|
||||
Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end,bool p_optimize=true);
|
||||
Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to);
|
||||
Vector3 get_closest_point(const Vector3& p_point);
|
||||
Vector3 get_closest_point_normal(const Vector3& p_point);
|
||||
|
|
|
@ -43,6 +43,20 @@ void PhysicsBody::_notification(int p_what) {
|
|||
*/
|
||||
}
|
||||
|
||||
Vector3 PhysicsBody::get_linear_velocity() const {
|
||||
|
||||
return Vector3();
|
||||
}
|
||||
Vector3 PhysicsBody::get_angular_velocity() const {
|
||||
|
||||
return Vector3();
|
||||
}
|
||||
|
||||
float PhysicsBody::get_inverse_mass() const {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : CollisionObject( PhysicsServer::get_singleton()->body_create(p_mode), false) {
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ protected:
|
|||
PhysicsBody(PhysicsServer::BodyMode p_mode);
|
||||
public:
|
||||
|
||||
virtual Vector3 get_linear_velocity() const;
|
||||
virtual Vector3 get_angular_velocity() const;
|
||||
virtual float get_inverse_mass() const;
|
||||
|
||||
PhysicsBody();
|
||||
|
||||
};
|
||||
|
@ -183,6 +187,8 @@ public:
|
|||
void set_mass(real_t p_mass);
|
||||
real_t get_mass() const;
|
||||
|
||||
virtual float get_inverse_mass() const { return 1.0/mass; }
|
||||
|
||||
void set_weight(real_t p_weight);
|
||||
real_t get_weight() const;
|
||||
|
||||
|
|
|
@ -237,6 +237,14 @@ Transform Skeleton::get_bone_transform(int p_bone) const {
|
|||
return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse;
|
||||
}
|
||||
|
||||
Transform Skeleton::get_bone_global_pose(int p_bone) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform());
|
||||
if (dirty)
|
||||
const_cast<Skeleton*>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
|
||||
return bones[p_bone].pose_global;
|
||||
}
|
||||
|
||||
RID Skeleton::get_skeleton() const {
|
||||
|
||||
return skeleton;
|
||||
|
@ -511,6 +519,8 @@ void Skeleton::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose);
|
||||
ObjectTypeDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose);
|
||||
ObjectTypeDB::bind_method(_MD("set_bone_custom_pose","bone_idx","custom_pose"),&Skeleton::set_bone_custom_pose);
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
void set_bone_rest(int p_bone, const Transform& p_rest);
|
||||
Transform get_bone_rest(int p_bone) const;
|
||||
Transform get_bone_transform(int p_bone) const;
|
||||
Transform get_bone_global_pose(int p_bone) const;
|
||||
|
||||
void set_bone_enabled(int p_bone, bool p_enabled);
|
||||
bool is_bone_enabled(int p_bone) const;
|
||||
|
|
|
@ -506,6 +506,86 @@ Transform Spatial::get_import_transform() const {
|
|||
#endif
|
||||
|
||||
|
||||
void Spatial::_propagate_visibility_changed() {
|
||||
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
_change_notify("visibility/visible");
|
||||
|
||||
for (List<Spatial*>::Element*E=data.children.front();E;E=E->next()) {
|
||||
|
||||
Spatial *c=E->get();
|
||||
if (!c || !c->data.visible)
|
||||
continue;
|
||||
c->_propagate_visibility_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Spatial::show() {
|
||||
|
||||
if (data.visible)
|
||||
return;
|
||||
|
||||
data.visible=true;
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (!data.parent || is_visible()) {
|
||||
|
||||
_propagate_visibility_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Spatial::hide(){
|
||||
|
||||
if (!data.visible)
|
||||
return;
|
||||
|
||||
bool was_visible = is_visible();
|
||||
data.visible=false;
|
||||
|
||||
if (!data.parent || was_visible) {
|
||||
|
||||
_propagate_visibility_changed();
|
||||
}
|
||||
|
||||
}
|
||||
bool Spatial::is_visible() const{
|
||||
|
||||
const Spatial *s=this;
|
||||
|
||||
while(s) {
|
||||
if (!s->data.visible) {
|
||||
return false;
|
||||
}
|
||||
s=s->data.parent;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Spatial::is_hidden() const{
|
||||
|
||||
return !data.visible;
|
||||
}
|
||||
|
||||
void Spatial::_set_visible_(bool p_visible) {
|
||||
|
||||
if (p_visible)
|
||||
show();
|
||||
else
|
||||
hide();
|
||||
}
|
||||
|
||||
bool Spatial::_is_visible_() const {
|
||||
|
||||
return !is_hidden();
|
||||
}
|
||||
|
||||
|
||||
void Spatial::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_transform","local"), &Spatial::set_transform);
|
||||
|
@ -537,9 +617,18 @@ void Spatial::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_gizmo","gizmo:SpatialGizmo"), &Spatial::set_gizmo);
|
||||
ObjectTypeDB::bind_method(_MD("get_gizmo:SpatialGizmo"), &Spatial::get_gizmo);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("show"), &Spatial::show);
|
||||
ObjectTypeDB::bind_method(_MD("hide"), &Spatial::hide);
|
||||
ObjectTypeDB::bind_method(_MD("is_visible"), &Spatial::is_visible);
|
||||
ObjectTypeDB::bind_method(_MD("is_hidden"), &Spatial::is_hidden);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_);
|
||||
ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_);
|
||||
|
||||
BIND_CONSTANT( NOTIFICATION_TRANSFORM_CHANGED );
|
||||
BIND_CONSTANT( NOTIFICATION_ENTER_WORLD );
|
||||
BIND_CONSTANT( NOTIFICATION_EXIT_WORLD );
|
||||
BIND_CONSTANT( NOTIFICATION_VISIBILITY_CHANGED );
|
||||
|
||||
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), _SCS("set_global_transform"), _SCS("get_global_transform") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"transform/local",PROPERTY_HINT_NONE,""), _SCS("set_transform"), _SCS("get_transform") );
|
||||
|
@ -547,8 +636,11 @@ void Spatial::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("_set_rotation_deg"), _SCS("_get_rotation_deg") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation_rad",PROPERTY_HINT_NONE,"",0), _SCS("set_rotation"), _SCS("get_rotation") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/scale",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_scale"), _SCS("get_scale") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"), _SCS("_is_visible_") );
|
||||
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/local"), _SCS("set_transform"), _SCS("get_transform") );
|
||||
|
||||
ADD_SIGNAL( MethodInfo("visibility_changed" ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -564,6 +656,7 @@ Spatial::Spatial() : xform_change(this)
|
|||
data.scale=Vector3(1,1,1);
|
||||
data.viewport=NULL;
|
||||
data.inside_world=false;
|
||||
data.visible=true;
|
||||
#ifdef TOOLS_ENABLED
|
||||
data.gizmo_disabled=false;
|
||||
data.gizmo_dirty=false;
|
||||
|
|
|
@ -91,6 +91,8 @@ class Spatial : public Node {
|
|||
|
||||
bool ignore_notification;
|
||||
|
||||
bool visible;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Ref<SpatialGizmo> gizmo;
|
||||
bool gizmo_disabled;
|
||||
|
@ -109,6 +111,8 @@ class Spatial : public Node {
|
|||
void _set_rotation_deg(const Vector3& p_deg);
|
||||
Vector3 _get_rotation_deg() const;
|
||||
|
||||
void _propagate_visibility_changed();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -118,7 +122,9 @@ protected:
|
|||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
||||
void _set_visible_(bool p_visible);
|
||||
bool _is_visible_() const;
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
@ -126,6 +132,7 @@ public:
|
|||
NOTIFICATION_TRANSFORM_CHANGED=SceneMainLoop::NOTIFICATION_TRANSFORM_CHANGED,
|
||||
NOTIFICATION_ENTER_WORLD=41,
|
||||
NOTIFICATION_EXIT_WORLD=42,
|
||||
NOTIFICATION_VISIBILITY_CHANGED=43,
|
||||
};
|
||||
|
||||
Spatial *get_parent_spatial() const;
|
||||
|
@ -159,6 +166,11 @@ public:
|
|||
|
||||
Transform get_relative_transform(const Node *p_parent) const;
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
bool is_visible() const;
|
||||
bool is_hidden() const;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void set_import_transform(const Transform& p_transform) ;
|
||||
Transform get_import_transform() const;
|
||||
|
|
846
scene/3d/vehicle_body.cpp
Normal file
846
scene/3d/vehicle_body.cpp
Normal file
|
@ -0,0 +1,846 @@
|
|||
#include "vehicle_body.h"
|
||||
|
||||
#define ROLLING_INFLUENCE_FIX
|
||||
|
||||
class btVehicleJacobianEntry
|
||||
{
|
||||
public:
|
||||
|
||||
Vector3 m_linearJointAxis;
|
||||
Vector3 m_aJ;
|
||||
Vector3 m_bJ;
|
||||
Vector3 m_0MinvJt;
|
||||
Vector3 m_1MinvJt;
|
||||
//Optimization: can be stored in the w/last component of one of the vectors
|
||||
real_t m_Adiag;
|
||||
|
||||
real_t getDiagonal() const { return m_Adiag; }
|
||||
|
||||
btVehicleJacobianEntry() {};
|
||||
//constraint between two different rigidbodies
|
||||
btVehicleJacobianEntry(
|
||||
const Matrix3& world2A,
|
||||
const Matrix3& world2B,
|
||||
const Vector3& rel_pos1,
|
||||
const Vector3& rel_pos2,
|
||||
const Vector3& jointAxis,
|
||||
const Vector3& inertiaInvA,
|
||||
const real_t massInvA,
|
||||
const Vector3& inertiaInvB,
|
||||
const real_t massInvB)
|
||||
:m_linearJointAxis(jointAxis)
|
||||
{
|
||||
m_aJ = world2A.xform(rel_pos1.cross(m_linearJointAxis));
|
||||
m_bJ = world2B.xform(rel_pos2.cross(-m_linearJointAxis));
|
||||
m_0MinvJt = inertiaInvA * m_aJ;
|
||||
m_1MinvJt = inertiaInvB * m_bJ;
|
||||
m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
|
||||
|
||||
//btAssert(m_Adiag > real_t(0.0));
|
||||
}
|
||||
|
||||
real_t getRelativeVelocity(const Vector3& linvelA,const Vector3& angvelA,const Vector3& linvelB,const Vector3& angvelB)
|
||||
{
|
||||
Vector3 linrel = linvelA - linvelB;
|
||||
Vector3 angvela = angvelA * m_aJ;
|
||||
Vector3 angvelb = angvelB * m_bJ;
|
||||
linrel *= m_linearJointAxis;
|
||||
angvela += angvelb;
|
||||
angvela += linrel;
|
||||
real_t rel_vel2 = angvela[0]+angvela[1]+angvela[2];
|
||||
return rel_vel2 + CMP_EPSILON;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
void VehicleWheel::_notification(int p_what) {
|
||||
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_SCENE) {
|
||||
|
||||
if (!get_parent())
|
||||
return;
|
||||
VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
|
||||
if (!cb)
|
||||
return;
|
||||
body=cb;
|
||||
local_xform=get_transform();
|
||||
cb->wheels.push_back(this);
|
||||
|
||||
m_chassisConnectionPointCS = get_transform().origin;
|
||||
m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
|
||||
m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
|
||||
|
||||
}
|
||||
if (p_what==NOTIFICATION_EXIT_SCENE) {
|
||||
|
||||
if (!get_parent())
|
||||
return;
|
||||
VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
|
||||
if (!cb)
|
||||
return;
|
||||
cb->wheels.erase(this);
|
||||
body=NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VehicleWheel::_update(PhysicsDirectBodyState *s) {
|
||||
|
||||
|
||||
|
||||
if (m_raycastInfo.m_isInContact)
|
||||
|
||||
{
|
||||
real_t project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
|
||||
Vector3 chassis_velocity_at_contactPoint;
|
||||
Vector3 relpos = m_raycastInfo.m_contactPointWS - s->get_transform().origin;
|
||||
|
||||
chassis_velocity_at_contactPoint = s->get_linear_velocity() +
|
||||
(s->get_angular_velocity()).cross(relpos);// * mPos);
|
||||
|
||||
real_t projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
|
||||
if ( project >= real_t(-0.1))
|
||||
{
|
||||
m_suspensionRelativeVelocity = real_t(0.0);
|
||||
m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
|
||||
}
|
||||
else
|
||||
{
|
||||
real_t inv = real_t(-1.) / project;
|
||||
m_suspensionRelativeVelocity = projVel * inv;
|
||||
m_clippedInvContactDotSuspension = inv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else // Not in contact : position wheel in a nice (rest length) position
|
||||
{
|
||||
m_raycastInfo.m_suspensionLength = m_suspensionRestLength;
|
||||
m_suspensionRelativeVelocity = real_t(0.0);
|
||||
m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
|
||||
m_clippedInvContactDotSuspension = real_t(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void VehicleWheel::_bind_methods() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
VehicleWheel::VehicleWheel() {
|
||||
|
||||
|
||||
|
||||
m_steering = real_t(0.);
|
||||
m_engineForce = real_t(0.);
|
||||
m_rotation = real_t(0.);
|
||||
m_deltaRotation = real_t(0.);
|
||||
m_brake = real_t(0.);
|
||||
m_rollInfluence = real_t(0.1);
|
||||
|
||||
m_suspensionRestLength = 0.15;
|
||||
m_wheelRadius = 0.5;//0.28;
|
||||
m_suspensionStiffness = 5.88;
|
||||
m_wheelsDampingCompression = 0.83;
|
||||
m_wheelsDampingRelaxation = 0.88;
|
||||
m_frictionSlip = 10.5;
|
||||
m_bIsFrontWheel = false;
|
||||
m_maxSuspensionTravelCm = 500;
|
||||
m_maxSuspensionForce = 6000;
|
||||
|
||||
m_suspensionRelativeVelocity=0;
|
||||
m_clippedInvContactDotSuspension=1.0;
|
||||
m_raycastInfo.m_isInContact=false;
|
||||
|
||||
body=NULL;
|
||||
}
|
||||
|
||||
|
||||
void VehicleBody::_update_wheel_transform(VehicleWheel& wheel ,PhysicsDirectBodyState *s) {
|
||||
|
||||
wheel.m_raycastInfo.m_isInContact = false;
|
||||
|
||||
Transform chassisTrans = s->get_transform();
|
||||
//if (interpolatedTransform && (getRigidBody()->getMotionState()))
|
||||
//{
|
||||
// getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
|
||||
//}
|
||||
|
||||
wheel.m_raycastInfo.m_hardPointWS = chassisTrans.xform( wheel.m_chassisConnectionPointCS );
|
||||
wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.get_basis().xform( wheel.m_wheelDirectionCS).normalized();
|
||||
wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform( wheel.m_wheelAxleCS ).normalized();
|
||||
}
|
||||
|
||||
void VehicleBody::_update_wheel(int p_idx,PhysicsDirectBodyState *s) {
|
||||
|
||||
VehicleWheel& wheel = *wheels[p_idx];
|
||||
_update_wheel_transform(wheel,s);
|
||||
|
||||
Vector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
|
||||
const Vector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
|
||||
Vector3 fwd = up.cross(right);
|
||||
fwd = fwd.normalized();
|
||||
// up = right.cross(fwd);
|
||||
// up.normalize();
|
||||
|
||||
//rotate around steering over de wheelAxleWS
|
||||
real_t steering = wheel.m_steering;
|
||||
|
||||
Matrix3 steeringMat(up,steering);
|
||||
|
||||
Matrix3 rotatingMat(right,-wheel.m_rotation);
|
||||
|
||||
Matrix3 basis2(
|
||||
right[0],up[0],fwd[0],
|
||||
right[1],up[1],fwd[1],
|
||||
right[2],up[2],fwd[2]
|
||||
);
|
||||
|
||||
wheel.m_worldTransform.set_basis(steeringMat * rotatingMat * basis2);
|
||||
wheel.m_worldTransform.set_origin(
|
||||
wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
real_t VehicleBody::_ray_cast(int p_idx,PhysicsDirectBodyState *s) {
|
||||
|
||||
|
||||
VehicleWheel& wheel = *wheels[p_idx];
|
||||
|
||||
_update_wheel_transform(wheel,s);
|
||||
|
||||
|
||||
real_t depth = -1;
|
||||
|
||||
real_t raylen = wheel.m_suspensionRestLength+wheel.m_wheelRadius;
|
||||
|
||||
Vector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
|
||||
const Vector3& source = wheel.m_raycastInfo.m_hardPointWS;
|
||||
wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
|
||||
const Vector3& target = wheel.m_raycastInfo.m_contactPointWS;
|
||||
|
||||
real_t param = real_t(0.);
|
||||
|
||||
|
||||
PhysicsDirectSpaceState::RayResult rr;
|
||||
|
||||
|
||||
PhysicsDirectSpaceState *ss=s->get_space_state();
|
||||
|
||||
bool col = ss->intersect_ray(source,target,rr,exclude);
|
||||
|
||||
|
||||
wheel.m_raycastInfo.m_groundObject = 0;
|
||||
|
||||
if (col)
|
||||
{
|
||||
//print_line("WHEEL "+itos(p_idx)+" FROM "+source+" TO: "+target);
|
||||
//print_line("WHEEL "+itos(p_idx)+" COLLIDE? "+itos(col));
|
||||
param = source.distance_to(rr.position)/source.distance_to(target);
|
||||
depth = raylen * param;
|
||||
wheel.m_raycastInfo.m_contactNormalWS = rr.normal;
|
||||
|
||||
wheel.m_raycastInfo.m_isInContact = true;
|
||||
if (rr.collider)
|
||||
wheel.m_raycastInfo.m_groundObject=rr.collider->cast_to<PhysicsBody>();
|
||||
|
||||
|
||||
real_t hitDistance = param*raylen;
|
||||
wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
|
||||
//clamp on max suspension travel
|
||||
|
||||
real_t minSuspensionLength = wheel.m_suspensionRestLength - wheel.m_maxSuspensionTravelCm*real_t(0.01);
|
||||
real_t maxSuspensionLength = wheel.m_suspensionRestLength+ wheel.m_maxSuspensionTravelCm*real_t(0.01);
|
||||
if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
|
||||
{
|
||||
wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
|
||||
}
|
||||
if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
|
||||
{
|
||||
wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
|
||||
}
|
||||
|
||||
wheel.m_raycastInfo.m_contactPointWS = rr.position;
|
||||
|
||||
real_t denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
|
||||
|
||||
Vector3 chassis_velocity_at_contactPoint;
|
||||
//Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
|
||||
|
||||
//chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
|
||||
|
||||
chassis_velocity_at_contactPoint = s->get_linear_velocity() +
|
||||
(s->get_angular_velocity()).cross(wheel.m_raycastInfo.m_contactPointWS-s->get_transform().origin);// * mPos);
|
||||
|
||||
|
||||
real_t projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
|
||||
|
||||
if ( denominator >= real_t(-0.1))
|
||||
{
|
||||
wheel.m_suspensionRelativeVelocity = real_t(0.0);
|
||||
wheel.m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
|
||||
}
|
||||
else
|
||||
{
|
||||
real_t inv = real_t(-1.) / denominator;
|
||||
wheel.m_suspensionRelativeVelocity = projVel * inv;
|
||||
wheel.m_clippedInvContactDotSuspension = inv;
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
wheel.m_raycastInfo.m_isInContact = false;
|
||||
//put wheel info as in rest position
|
||||
wheel.m_raycastInfo.m_suspensionLength = wheel.m_suspensionRestLength;
|
||||
wheel.m_suspensionRelativeVelocity = real_t(0.0);
|
||||
wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
|
||||
wheel.m_clippedInvContactDotSuspension = real_t(1.0);
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
void VehicleBody::_update_suspension(PhysicsDirectBodyState *s)
|
||||
{
|
||||
|
||||
real_t deltaTime = s->get_step();
|
||||
real_t chassisMass = mass;
|
||||
|
||||
for (int w_it=0; w_it<wheels.size(); w_it++)
|
||||
{
|
||||
VehicleWheel& wheel_info = *wheels[w_it];
|
||||
|
||||
|
||||
if ( wheel_info.m_raycastInfo.m_isInContact )
|
||||
{
|
||||
real_t force;
|
||||
// Spring
|
||||
{
|
||||
real_t susp_length = wheel_info.m_suspensionRestLength;
|
||||
real_t current_length = wheel_info.m_raycastInfo.m_suspensionLength;
|
||||
|
||||
real_t length_diff = (susp_length - current_length);
|
||||
|
||||
force = wheel_info.m_suspensionStiffness
|
||||
* length_diff * wheel_info.m_clippedInvContactDotSuspension;
|
||||
}
|
||||
|
||||
// Damper
|
||||
{
|
||||
real_t projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
|
||||
{
|
||||
real_t susp_damping;
|
||||
if ( projected_rel_vel < real_t(0.0) )
|
||||
{
|
||||
susp_damping = wheel_info.m_wheelsDampingCompression;
|
||||
}
|
||||
else
|
||||
{
|
||||
susp_damping = wheel_info.m_wheelsDampingRelaxation;
|
||||
}
|
||||
force -= susp_damping * projected_rel_vel;
|
||||
}
|
||||
}
|
||||
|
||||
// RESULT
|
||||
wheel_info.m_wheelsSuspensionForce = force * chassisMass;
|
||||
if (wheel_info.m_wheelsSuspensionForce < real_t(0.))
|
||||
{
|
||||
wheel_info.m_wheelsSuspensionForce = real_t(0.);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wheel_info.m_wheelsSuspensionForce = real_t(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//bilateral constraint between two dynamic objects
|
||||
void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3& pos1,
|
||||
PhysicsBody* body2, const Vector3& pos2, const Vector3& normal,real_t& impulse)
|
||||
{
|
||||
|
||||
real_t normalLenSqr = normal.length_squared();
|
||||
//ERR_FAIL_COND( normalLenSqr < real_t(1.1));
|
||||
|
||||
if (normalLenSqr > real_t(1.1))
|
||||
{
|
||||
impulse = real_t(0.);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 rel_pos1 = pos1 - s->get_transform().origin;
|
||||
Vector3 rel_pos2;
|
||||
if (body2)
|
||||
rel_pos2 = pos2 - body2->get_global_transform().origin;
|
||||
//this jacobian entry could be re-used for all iterations
|
||||
|
||||
Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1);// * mPos);
|
||||
Vector3 vel2;
|
||||
|
||||
if (body2)
|
||||
vel2=body2->get_linear_velocity() + body2->get_angular_velocity().cross(rel_pos2);
|
||||
|
||||
Vector3 vel = vel1 - vel2;
|
||||
|
||||
Matrix3 b2trans;
|
||||
float b2invmass=0;
|
||||
Vector3 b2lv;
|
||||
Vector3 b2av;
|
||||
Vector3 b2invinertia; //todo
|
||||
|
||||
if (body2) {
|
||||
b2trans = body2->get_global_transform().basis.transposed();
|
||||
b2invmass = body2->get_inverse_mass();
|
||||
b2lv = body2->get_linear_velocity();
|
||||
b2av = body2->get_angular_velocity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
btVehicleJacobianEntry jac(s->get_transform().basis.transposed(),
|
||||
b2trans,
|
||||
rel_pos1,
|
||||
rel_pos2,
|
||||
normal,
|
||||
s->get_inverse_inertia(),
|
||||
1.0/mass,
|
||||
b2invinertia,
|
||||
b2invmass);
|
||||
|
||||
real_t jacDiagAB = jac.getDiagonal();
|
||||
real_t jacDiagABInv = real_t(1.) / jacDiagAB;
|
||||
|
||||
real_t rel_vel = jac.getRelativeVelocity(
|
||||
s->get_linear_velocity(),
|
||||
s->get_transform().basis.transposed().xform(s->get_angular_velocity()),
|
||||
b2lv,
|
||||
b2trans.xform(b2av));
|
||||
real_t a;
|
||||
a=jacDiagABInv;
|
||||
|
||||
|
||||
rel_vel = normal.dot(vel);
|
||||
|
||||
//todo: move this into proper structure
|
||||
real_t contactDamping = real_t(0.4);
|
||||
#define ONLY_USE_LINEAR_MASS
|
||||
#ifdef ONLY_USE_LINEAR_MASS
|
||||
real_t massTerm = real_t(1.) / ((1.0/mass) + b2invmass);
|
||||
impulse = - contactDamping * rel_vel * massTerm;
|
||||
#else
|
||||
real_t velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
|
||||
impulse = velocityImpulse;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s,PhysicsBody* body1,const Vector3& frictionPosWorld,const Vector3& frictionDirectionWorld, real_t maxImpulse)
|
||||
:m_s(s),
|
||||
m_body1(body1),
|
||||
m_frictionPositionWorld(frictionPosWorld),
|
||||
m_frictionDirectionWorld(frictionDirectionWorld),
|
||||
m_maxImpulse(maxImpulse)
|
||||
{
|
||||
float denom0=0;
|
||||
float denom1=0;
|
||||
|
||||
{
|
||||
Vector3 r0 = frictionPosWorld - s->get_transform().origin;
|
||||
Vector3 c0 = (r0).cross(frictionDirectionWorld);
|
||||
Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
|
||||
denom0= s->get_inverse_mass() + frictionDirectionWorld.dot(vec);
|
||||
}
|
||||
|
||||
if (body1) {
|
||||
|
||||
Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin;
|
||||
Vector3 c0 = (r0).cross(frictionDirectionWorld);
|
||||
Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
|
||||
//denom1= body1->get_inverse_mass() + frictionDirectionWorld.dot(vec);
|
||||
denom1=0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
real_t relaxation = 1.f;
|
||||
m_jacDiagABInv = relaxation/(denom0+denom1);
|
||||
}
|
||||
|
||||
|
||||
real_t VehicleBody::_calc_rolling_friction(btVehicleWheelContactPoint& contactPoint) {
|
||||
|
||||
real_t j1=0.f;
|
||||
|
||||
const Vector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
|
||||
|
||||
Vector3 rel_pos1 = contactPosWorld - contactPoint.m_s->get_transform().origin;
|
||||
Vector3 rel_pos2;
|
||||
if (contactPoint.m_body1)
|
||||
rel_pos2 = contactPosWorld - contactPoint.m_body1->get_global_transform().origin;
|
||||
|
||||
real_t maxImpulse = contactPoint.m_maxImpulse;
|
||||
|
||||
Vector3 vel1 = contactPoint.m_s->get_linear_velocity() + (contactPoint.m_s->get_angular_velocity()).cross(rel_pos1);// * mPos);
|
||||
|
||||
Vector3 vel2;
|
||||
if (contactPoint.m_body1) {
|
||||
vel2=contactPoint.m_body1->get_linear_velocity() + contactPoint.m_body1->get_angular_velocity().cross(rel_pos2);
|
||||
|
||||
}
|
||||
|
||||
Vector3 vel = vel1 - vel2;
|
||||
|
||||
real_t vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
|
||||
|
||||
// calculate j that moves us to zero relative velocity
|
||||
j1 = -vrel * contactPoint.m_jacDiagABInv;
|
||||
|
||||
return CLAMP(j1,-maxImpulse,maxImpulse);
|
||||
}
|
||||
|
||||
|
||||
static const real_t sideFrictionStiffness2 = real_t(1.0);
|
||||
void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
|
||||
|
||||
//calculate the impulse, so that the wheels don't move sidewards
|
||||
int numWheel = wheels.size();
|
||||
if (!numWheel)
|
||||
return;
|
||||
|
||||
m_forwardWS.resize(numWheel);
|
||||
m_axle.resize(numWheel);
|
||||
m_forwardImpulse.resize(numWheel);
|
||||
m_sideImpulse.resize(numWheel);
|
||||
|
||||
int numWheelsOnGround = 0;
|
||||
|
||||
|
||||
//collapse all those loops into one!
|
||||
for (int i=0;i<wheels.size();i++)
|
||||
{
|
||||
VehicleWheel& wheelInfo = *wheels[i];
|
||||
if (wheelInfo.m_raycastInfo.m_isInContact)
|
||||
numWheelsOnGround++;
|
||||
m_sideImpulse[i] = real_t(0.);
|
||||
m_forwardImpulse[i] = real_t(0.);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
for (int i=0;i<wheels.size();i++)
|
||||
{
|
||||
|
||||
VehicleWheel& wheelInfo = *wheels[i];
|
||||
|
||||
|
||||
if (wheelInfo.m_raycastInfo.m_isInContact)
|
||||
{
|
||||
|
||||
//const btTransform& wheelTrans = getWheelTransformWS( i );
|
||||
|
||||
Matrix3 wheelBasis0 = wheelInfo.get_global_transform().basis;
|
||||
m_axle[i] = wheelBasis0.get_axis(Vector3::AXIS_X);
|
||||
m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS;
|
||||
|
||||
const Vector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
|
||||
real_t proj = m_axle[i].dot(surfNormalWS);
|
||||
m_axle[i] -= surfNormalWS * proj;
|
||||
m_axle[i] = m_axle[i].normalized();
|
||||
|
||||
m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
|
||||
m_forwardWS[i].normalize();
|
||||
|
||||
|
||||
_resolve_single_bilateral(s, wheelInfo.m_raycastInfo.m_contactPointWS,
|
||||
wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
|
||||
m_axle[i],m_sideImpulse[i]);
|
||||
|
||||
m_sideImpulse[i] *= sideFrictionStiffness2;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
real_t sideFactor = real_t(1.);
|
||||
real_t fwdFactor = 0.5;
|
||||
|
||||
bool sliding = false;
|
||||
{
|
||||
for (int wheel =0;wheel <wheels.size();wheel++)
|
||||
{
|
||||
VehicleWheel& wheelInfo = *wheels[wheel];
|
||||
|
||||
|
||||
//class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
|
||||
|
||||
real_t rollingFriction = 0.f;
|
||||
|
||||
if (wheelInfo.m_raycastInfo.m_isInContact)
|
||||
{
|
||||
if (wheelInfo.m_engineForce != 0.f)
|
||||
{
|
||||
rollingFriction = wheelInfo.m_engineForce* s->get_step();
|
||||
} else
|
||||
{
|
||||
real_t defaultRollingFrictionImpulse = 0.f;
|
||||
real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
|
||||
btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
|
||||
rollingFriction = _calc_rolling_friction(contactPt);
|
||||
}
|
||||
}
|
||||
|
||||
//switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
|
||||
|
||||
|
||||
|
||||
|
||||
m_forwardImpulse[wheel] = real_t(0.);
|
||||
wheelInfo.m_skidInfo= real_t(1.);
|
||||
|
||||
if (wheelInfo.m_raycastInfo.m_isInContact)
|
||||
{
|
||||
wheelInfo.m_skidInfo= real_t(1.);
|
||||
|
||||
real_t maximp = wheelInfo.m_wheelsSuspensionForce * s->get_step() * wheelInfo.m_frictionSlip;
|
||||
real_t maximpSide = maximp;
|
||||
|
||||
real_t maximpSquared = maximp * maximpSide;
|
||||
|
||||
|
||||
m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
|
||||
|
||||
real_t x = (m_forwardImpulse[wheel] ) * fwdFactor;
|
||||
real_t y = (m_sideImpulse[wheel] ) * sideFactor;
|
||||
|
||||
real_t impulseSquared = (x*x + y*y);
|
||||
|
||||
if (impulseSquared > maximpSquared)
|
||||
{
|
||||
sliding = true;
|
||||
|
||||
real_t factor = maximp / Math::sqrt(impulseSquared);
|
||||
|
||||
wheelInfo.m_skidInfo *= factor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (sliding)
|
||||
{
|
||||
for (int wheel = 0;wheel < wheels.size(); wheel++)
|
||||
{
|
||||
if (m_sideImpulse[wheel] != real_t(0.))
|
||||
{
|
||||
if (wheels[wheel]->m_skidInfo< real_t(1.))
|
||||
{
|
||||
m_forwardImpulse[wheel] *= wheels[wheel]->m_skidInfo;
|
||||
m_sideImpulse[wheel] *= wheels[wheel]->m_skidInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply the impulses
|
||||
{
|
||||
for (int wheel = 0;wheel<wheels.size(); wheel++)
|
||||
{
|
||||
VehicleWheel& wheelInfo = *wheels[wheel];
|
||||
|
||||
Vector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
|
||||
s->get_transform().origin;
|
||||
|
||||
if (m_forwardImpulse[wheel] != real_t(0.))
|
||||
{
|
||||
s->apply_impulse(rel_pos,m_forwardWS[wheel]*(m_forwardImpulse[wheel]));
|
||||
}
|
||||
if (m_sideImpulse[wheel] != real_t(0.))
|
||||
{
|
||||
PhysicsBody* groundObject = wheelInfo.m_raycastInfo.m_groundObject;
|
||||
|
||||
Vector3 rel_pos2;
|
||||
if (groundObject) {
|
||||
rel_pos2=wheelInfo.m_raycastInfo.m_contactPointWS - groundObject->get_global_transform().origin;
|
||||
}
|
||||
|
||||
|
||||
Vector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
|
||||
|
||||
#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
|
||||
Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1];//getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
|
||||
rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
|
||||
#else
|
||||
rel_pos[1] *= wheelInfo.m_rollInfluence; //?
|
||||
#endif
|
||||
s->apply_impulse(rel_pos,sideImp);
|
||||
|
||||
//apply friction impulse on the ground
|
||||
//todo
|
||||
//groundObject->applyImpulse(-sideImp,rel_pos2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VehicleBody::_direct_state_changed(Object *p_state) {
|
||||
|
||||
|
||||
PhysicsDirectBodyState *s = p_state->cast_to<PhysicsDirectBodyState>();
|
||||
|
||||
set_ignore_transform_notification(true);
|
||||
set_global_transform(s->get_transform());
|
||||
set_ignore_transform_notification(false);
|
||||
|
||||
|
||||
float step = s->get_step();
|
||||
|
||||
for(int i=0;i<wheels.size();i++) {
|
||||
|
||||
_update_wheel(i,s);
|
||||
}
|
||||
|
||||
for(int i=0;i<wheels.size();i++) {
|
||||
|
||||
_ray_cast(i,s);
|
||||
}
|
||||
|
||||
_update_suspension(s);
|
||||
|
||||
for(int i=0;i<wheels.size();i++) {
|
||||
|
||||
//apply suspension force
|
||||
VehicleWheel& wheel = *wheels[i];
|
||||
|
||||
real_t suspensionForce = wheel.m_wheelsSuspensionForce;
|
||||
|
||||
if (suspensionForce > wheel.m_maxSuspensionForce)
|
||||
{
|
||||
suspensionForce = wheel.m_maxSuspensionForce;
|
||||
}
|
||||
Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
|
||||
Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin;
|
||||
|
||||
s->apply_impulse(relpos,impulse);
|
||||
//getRigidBody()->applyImpulse(impulse, relpos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
_update_friction(s);
|
||||
|
||||
|
||||
for (int i=0;i<wheels.size();i++)
|
||||
{
|
||||
VehicleWheel& wheel = *wheels[i];
|
||||
Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - s->get_transform().origin;
|
||||
Vector3 vel = s->get_linear_velocity() + (s->get_angular_velocity()).cross(relpos);// * mPos);
|
||||
|
||||
if (wheel.m_raycastInfo.m_isInContact)
|
||||
{
|
||||
const Transform& chassisWorldTransform = s->get_transform();
|
||||
|
||||
Vector3 fwd (
|
||||
chassisWorldTransform.basis[0][Vector3::AXIS_Z],
|
||||
chassisWorldTransform.basis[1][Vector3::AXIS_Z],
|
||||
chassisWorldTransform.basis[2][Vector3::AXIS_Z]);
|
||||
|
||||
real_t proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
|
||||
fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
|
||||
|
||||
real_t proj2 = fwd.dot(vel);
|
||||
|
||||
wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelRadius);
|
||||
wheel.m_rotation += wheel.m_deltaRotation;
|
||||
|
||||
} else
|
||||
{
|
||||
wheel.m_rotation += wheel.m_deltaRotation;
|
||||
}
|
||||
|
||||
wheel.m_deltaRotation *= real_t(0.99);//damping of rotation when not in contact
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VehicleBody::set_mass(real_t p_mass) {
|
||||
|
||||
mass=p_mass;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass);
|
||||
}
|
||||
|
||||
real_t VehicleBody::get_mass() const{
|
||||
|
||||
return mass;
|
||||
}
|
||||
|
||||
|
||||
void VehicleBody::set_friction(real_t p_friction) {
|
||||
|
||||
friction=p_friction;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction);
|
||||
}
|
||||
|
||||
real_t VehicleBody::get_friction() const{
|
||||
|
||||
return friction;
|
||||
}
|
||||
|
||||
void VehicleBody::_bind_methods(){
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mass","mass"),&VehicleBody::set_mass);
|
||||
ObjectTypeDB::bind_method(_MD("get_mass"),&VehicleBody::get_mass);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_friction","friction"),&VehicleBody::set_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_friction"),&VehicleBody::get_friction);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
VehicleBody::VehicleBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
|
||||
|
||||
|
||||
m_pitchControl=0;
|
||||
m_currentVehicleSpeedKmHour = real_t(0.);
|
||||
m_steeringValue = real_t(0.);
|
||||
|
||||
|
||||
mass=1;
|
||||
friction=1;
|
||||
|
||||
ccd=false;
|
||||
|
||||
exclude.insert(get_rid());
|
||||
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
|
||||
|
||||
}
|
||||
|
142
scene/3d/vehicle_body.h
Normal file
142
scene/3d/vehicle_body.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
#ifndef VEHICLE_BODY_H
|
||||
#define VEHICLE_BODY_H
|
||||
|
||||
#include "scene/3d/physics_body.h"
|
||||
|
||||
class VehicleBody;
|
||||
|
||||
class VehicleWheel : public Spatial {
|
||||
|
||||
OBJ_TYPE(VehicleWheel,Spatial);
|
||||
|
||||
friend class VehicleBody;
|
||||
|
||||
|
||||
Transform m_worldTransform;
|
||||
Transform local_xform;
|
||||
|
||||
|
||||
Vector3 m_chassisConnectionPointCS; //const
|
||||
Vector3 m_wheelDirectionCS;//const
|
||||
Vector3 m_wheelAxleCS; // const or modified by steering
|
||||
|
||||
real_t m_suspensionRestLength;
|
||||
real_t m_maxSuspensionTravelCm;
|
||||
real_t m_wheelRadius;
|
||||
|
||||
real_t m_suspensionStiffness;
|
||||
real_t m_wheelsDampingCompression;
|
||||
real_t m_wheelsDampingRelaxation;
|
||||
real_t m_frictionSlip;
|
||||
real_t m_maxSuspensionForce;
|
||||
bool m_bIsFrontWheel;
|
||||
|
||||
VehicleBody *body;
|
||||
|
||||
// btVector3 m_wheelAxleCS; // const or modified by steering ?
|
||||
|
||||
real_t m_steering;
|
||||
real_t m_rotation;
|
||||
real_t m_deltaRotation;
|
||||
real_t m_rollInfluence;
|
||||
real_t m_engineForce;
|
||||
real_t m_brake;
|
||||
|
||||
real_t m_clippedInvContactDotSuspension;
|
||||
real_t m_suspensionRelativeVelocity;
|
||||
//calculated by suspension
|
||||
real_t m_wheelsSuspensionForce;
|
||||
real_t m_skidInfo;
|
||||
|
||||
|
||||
struct RaycastInfo {
|
||||
//set by raycaster
|
||||
Vector3 m_contactNormalWS;//contactnormal
|
||||
Vector3 m_contactPointWS;//raycast hitpoint
|
||||
real_t m_suspensionLength;
|
||||
Vector3 m_hardPointWS;//raycast starting point
|
||||
Vector3 m_wheelDirectionWS; //direction in worldspace
|
||||
Vector3 m_wheelAxleWS; // axle in worldspace
|
||||
bool m_isInContact;
|
||||
PhysicsBody* m_groundObject; //could be general void* ptr
|
||||
} m_raycastInfo;
|
||||
|
||||
void _update(PhysicsDirectBodyState *s);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
VehicleWheel();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class VehicleBody : public PhysicsBody {
|
||||
|
||||
OBJ_TYPE(VehicleBody,PhysicsBody);
|
||||
|
||||
real_t mass;
|
||||
real_t friction;
|
||||
|
||||
Vector3 linear_velocity;
|
||||
Vector3 angular_velocity;
|
||||
bool ccd;
|
||||
|
||||
real_t m_pitchControl;
|
||||
real_t m_steeringValue;
|
||||
real_t m_currentVehicleSpeedKmHour;
|
||||
|
||||
Set<RID> exclude;
|
||||
|
||||
Vector<Vector3> m_forwardWS;
|
||||
Vector<Vector3> m_axle;
|
||||
Vector<real_t> m_forwardImpulse;
|
||||
Vector<real_t> m_sideImpulse;
|
||||
|
||||
struct btVehicleWheelContactPoint {
|
||||
PhysicsDirectBodyState *m_s;
|
||||
PhysicsBody* m_body1;
|
||||
Vector3 m_frictionPositionWorld;
|
||||
Vector3 m_frictionDirectionWorld;
|
||||
real_t m_jacDiagABInv;
|
||||
real_t m_maxImpulse;
|
||||
|
||||
|
||||
btVehicleWheelContactPoint(PhysicsDirectBodyState *s,PhysicsBody* body1,const Vector3& frictionPosWorld,const Vector3& frictionDirectionWorld, real_t maxImpulse);
|
||||
};
|
||||
|
||||
void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3& pos1, PhysicsBody* body2, const Vector3& pos2, const Vector3& normal, real_t& impulse);
|
||||
real_t _calc_rolling_friction(btVehicleWheelContactPoint& contactPoint);
|
||||
|
||||
void _update_friction(PhysicsDirectBodyState *s);
|
||||
void _update_suspension(PhysicsDirectBodyState *s);
|
||||
real_t _ray_cast(int p_idx,PhysicsDirectBodyState *s);
|
||||
void _update_wheel_transform(VehicleWheel& wheel ,PhysicsDirectBodyState *s);
|
||||
void _update_wheel(int p_idx,PhysicsDirectBodyState *s);
|
||||
|
||||
|
||||
|
||||
friend class VehicleWheel;
|
||||
Vector<VehicleWheel*> wheels;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
void _direct_state_changed(Object *p_state);
|
||||
public:
|
||||
|
||||
|
||||
void set_mass(real_t p_mass);
|
||||
real_t get_mass() const;
|
||||
|
||||
void set_friction(real_t p_friction);
|
||||
real_t get_friction() const;
|
||||
|
||||
|
||||
VehicleBody();
|
||||
};
|
||||
|
||||
#endif // VEHICLE_BODY_H
|
|
@ -195,6 +195,7 @@ void GeometryInstance::_notification(int p_what) {
|
|||
_find_baked_light();
|
||||
}
|
||||
|
||||
_update_visibility();
|
||||
|
||||
} else if (p_what==NOTIFICATION_EXIT_WORLD) {
|
||||
|
||||
|
@ -207,8 +208,13 @@ void GeometryInstance::_notification(int p_what) {
|
|||
_baked_light_changed();
|
||||
|
||||
}
|
||||
|
||||
} if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
|
||||
_update_visibility();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void GeometryInstance::_baked_light_changed() {
|
||||
|
@ -241,6 +247,15 @@ void GeometryInstance::_find_baked_light() {
|
|||
_baked_light_changed();
|
||||
}
|
||||
|
||||
void GeometryInstance::_update_visibility() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
_change_notify("geometry/visible");
|
||||
VS::get_singleton()->instance_geometry_set_flag(get_instance(),VS::INSTANCE_FLAG_VISIBLE,is_visible() && flags[FLAG_VISIBLE]);
|
||||
}
|
||||
|
||||
void GeometryInstance::set_flag(Flags p_flag,bool p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_flag,FLAG_MAX);
|
||||
|
@ -250,8 +265,7 @@ void GeometryInstance::set_flag(Flags p_flag,bool p_value) {
|
|||
flags[p_flag]=p_value;
|
||||
VS::get_singleton()->instance_geometry_set_flag(get_instance(),(VS::InstanceFlags)p_flag,p_value);
|
||||
if (p_flag==FLAG_VISIBLE) {
|
||||
_change_notify("geometry/visible");
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
_update_visibility();
|
||||
}
|
||||
if (p_flag==FLAG_USE_BAKED_LIGHT) {
|
||||
|
||||
|
@ -321,7 +335,7 @@ void GeometryInstance::_bind_methods() {
|
|||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/use_baked_light"), _SCS("set_flag"), _SCS("get_flag"),FLAG_USE_BAKED_LIGHT);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/baked_light_tex_id"), _SCS("set_baked_light_texture_id"), _SCS("get_baked_light_texture_id"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("visibility_changed"));
|
||||
// ADD_SIGNAL( MethodInfo("visibility_changed"));
|
||||
|
||||
BIND_CONSTANT(FLAG_VISIBLE );
|
||||
BIND_CONSTANT(FLAG_CAST_SHADOW );
|
||||
|
@ -346,6 +360,7 @@ GeometryInstance::GeometryInstance() {
|
|||
flags[FLAG_VISIBLE_IN_ALL_ROOMS]=false;
|
||||
baked_light_instance=NULL;
|
||||
baked_light_texture_id=0;
|
||||
VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ private:
|
|||
int baked_light_texture_id;
|
||||
|
||||
void _baked_light_changed();
|
||||
void _update_visibility();
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
|
|
@ -637,14 +637,15 @@ void AnimationPlayer::_animation_process(float p_delta) {
|
|||
play(queued.front()->get());
|
||||
String new_name = playback.assigned;
|
||||
queued.pop_front();
|
||||
end_notify=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name);
|
||||
} else {
|
||||
//stop();
|
||||
playing = false;
|
||||
_set_process(false);
|
||||
end_notify=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->finished);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -912,7 +913,8 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float
|
|||
c.current.speed_scale=p_custom_scale;
|
||||
c.assigned=p_name;
|
||||
|
||||
queued.clear();
|
||||
if (!end_notify)
|
||||
queued.clear();
|
||||
_set_process(true); // always process when starting an animation
|
||||
playing = true;
|
||||
|
||||
|
|
|
@ -786,6 +786,19 @@ bool Viewport::get_render_target_filter() const{
|
|||
return (render_target_texture->get_flags()&Texture::FLAG_FILTER)!=0;
|
||||
}
|
||||
|
||||
void Viewport::set_render_target_gen_mipmaps(bool p_enable) {
|
||||
|
||||
//render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0));
|
||||
render_target_gen_mipmaps=p_enable;
|
||||
|
||||
}
|
||||
|
||||
bool Viewport::get_render_target_gen_mipmaps() const{
|
||||
|
||||
//return (render_target_texture->get_flags()&Texture::FLAG_FILTER)!=0;
|
||||
return render_target_gen_mipmaps;
|
||||
}
|
||||
|
||||
|
||||
Matrix32 Viewport::_get_input_pre_xform() const {
|
||||
|
||||
|
@ -1007,6 +1020,9 @@ void Viewport::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_render_target_filter","enable"), &Viewport::set_render_target_filter);
|
||||
ObjectTypeDB::bind_method(_MD("get_render_target_filter"), &Viewport::get_render_target_filter);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_render_target_gen_mipmaps","enable"), &Viewport::set_render_target_gen_mipmaps);
|
||||
ObjectTypeDB::bind_method(_MD("get_render_target_gen_mipmaps"), &Viewport::get_render_target_gen_mipmaps);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_render_target_update_mode","mode"), &Viewport::set_render_target_update_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_render_target_update_mode"), &Viewport::get_render_target_update_mode);
|
||||
|
||||
|
@ -1038,6 +1054,7 @@ void Viewport::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/filter"), _SCS("set_render_target_filter"), _SCS("get_render_target_filter") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/gen_mipmaps"), _SCS("set_render_target_gen_mipmaps"), _SCS("get_render_target_gen_mipmaps") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") );
|
||||
|
@ -1070,6 +1087,7 @@ Viewport::Viewport() {
|
|||
size_override=false;
|
||||
size_override_stretch=false;
|
||||
size_override_size=Size2(1,1);
|
||||
render_target_gen_mipmaps=false;
|
||||
render_target=false;
|
||||
render_target_vflip=false;
|
||||
render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
|
||||
|
|
|
@ -114,6 +114,7 @@ friend class RenderTargetTexture;
|
|||
bool transparent_bg;
|
||||
bool render_target_vflip;
|
||||
bool render_target_filter;
|
||||
bool render_target_gen_mipmaps;
|
||||
|
||||
void _update_rect();
|
||||
|
||||
|
@ -214,6 +215,9 @@ public:
|
|||
void set_render_target_filter(bool p_enable);
|
||||
bool get_render_target_filter() const;
|
||||
|
||||
void set_render_target_gen_mipmaps(bool p_enable);
|
||||
bool get_render_target_gen_mipmaps() const;
|
||||
|
||||
void set_render_target_update_mode(RenderTargetUpdateMode p_mode);
|
||||
RenderTargetUpdateMode get_render_target_update_mode() const;
|
||||
Ref<RenderTargetTexture> get_render_target_texture() const;
|
||||
|
|
|
@ -185,6 +185,7 @@
|
|||
#include "scene/resources/environment.h"
|
||||
#include "scene/3d/physics_body.h"
|
||||
#include "scene/3d/car_body.h"
|
||||
#include "scene/3d/vehicle_body.h"
|
||||
#include "scene/3d/body_shape.h"
|
||||
#include "scene/3d/area.h"
|
||||
#include "scene/3d/physics_joint.h"
|
||||
|
@ -402,6 +403,8 @@ void register_scene_types() {
|
|||
ObjectTypeDB::register_type<RigidBody>();
|
||||
ObjectTypeDB::register_type<CarBody>();
|
||||
ObjectTypeDB::register_type<CarWheel>();
|
||||
ObjectTypeDB::register_type<VehicleBody>();
|
||||
ObjectTypeDB::register_type<VehicleWheel>();
|
||||
ObjectTypeDB::register_type<Area>();
|
||||
ObjectTypeDB::register_type<ProximityGroup>();
|
||||
ObjectTypeDB::register_type<CollisionShape>();
|
||||
|
|
|
@ -5,6 +5,7 @@ void BakedLight::set_mode(Mode p_mode) {
|
|||
|
||||
mode=p_mode;
|
||||
VS::get_singleton()->baked_light_set_mode(baked_light,(VS::BakedLightMode(p_mode)));
|
||||
|
||||
}
|
||||
|
||||
BakedLight::Mode BakedLight::get_mode() const{
|
||||
|
@ -123,7 +124,7 @@ void BakedLight::_set_lightmap_data(Array p_array){
|
|||
|
||||
Size2 size = p_array[i];
|
||||
Ref<Texture> tex = p_array[i+1];
|
||||
ERR_CONTINUE(tex.is_null());
|
||||
// ERR_CONTINUE(tex.is_null());
|
||||
LightMap lm;
|
||||
lm.gen_size=size;
|
||||
lm.texture=tex;
|
||||
|
@ -228,7 +229,7 @@ bool BakedLight::get_bake_flag(BakeFlags p_flags) const{
|
|||
void BakedLight::set_format(Format p_format) {
|
||||
|
||||
format=p_format;
|
||||
|
||||
VS::get_singleton()->baked_light_set_lightmap_multiplier(baked_light,format==FORMAT_HDR8?8.0:1.0);
|
||||
}
|
||||
|
||||
BakedLight::Format BakedLight::get_format() const{
|
||||
|
@ -236,6 +237,17 @@ BakedLight::Format BakedLight::get_format() const{
|
|||
return format;
|
||||
}
|
||||
|
||||
void BakedLight::set_transfer_lightmaps_only_to_uv2(bool p_enable) {
|
||||
|
||||
transfer_only_uv2=p_enable;
|
||||
}
|
||||
|
||||
bool BakedLight::get_transfer_lightmaps_only_to_uv2() const{
|
||||
|
||||
return transfer_only_uv2;
|
||||
}
|
||||
|
||||
|
||||
bool BakedLight::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String n = p_name;
|
||||
|
@ -348,6 +360,11 @@ void BakedLight::_bind_methods(){
|
|||
ObjectTypeDB::bind_method(_MD("set_format","format"),&BakedLight::set_format);
|
||||
ObjectTypeDB::bind_method(_MD("get_format"),&BakedLight::get_format);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_transfer_lightmaps_only_to_uv2","enable"),&BakedLight::set_transfer_lightmaps_only_to_uv2);
|
||||
ObjectTypeDB::bind_method(_MD("get_transfer_lightmaps_only_to_uv2"),&BakedLight::get_transfer_lightmaps_only_to_uv2);
|
||||
|
||||
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_energy_multiplier","energy_multiplier"),&BakedLight::set_energy_multiplier);
|
||||
ObjectTypeDB::bind_method(_MD("get_energy_multiplier"),&BakedLight::get_energy_multiplier);
|
||||
|
@ -371,6 +388,7 @@ void BakedLight::_bind_methods(){
|
|||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY);
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"lightmap/use_only_uv2"),_SCS("set_transfer_lightmaps_only_to_uv2"),_SCS("get_transfer_lightmaps_only_to_uv2"));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data"));
|
||||
|
@ -403,6 +421,7 @@ BakedLight::BakedLight() {
|
|||
edge_damp=0.0;
|
||||
normal_damp=0.0;
|
||||
format=FORMAT_RGB;
|
||||
transfer_only_uv2=false;
|
||||
|
||||
flags[BAKE_DIFFUSE]=true;
|
||||
flags[BAKE_SPECULAR]=false;
|
||||
|
|
|
@ -51,6 +51,7 @@ private:
|
|||
float edge_damp;
|
||||
float normal_damp;
|
||||
int bounces;
|
||||
bool transfer_only_uv2;
|
||||
Format format;
|
||||
bool flags[BAKE_MAX];
|
||||
|
||||
|
@ -104,6 +105,9 @@ public:
|
|||
void set_format(Format p_margin);
|
||||
Format get_format() const;
|
||||
|
||||
void set_transfer_lightmaps_only_to_uv2(bool p_enable);
|
||||
bool get_transfer_lightmaps_only_to_uv2() const;
|
||||
|
||||
void set_mode(Mode p_mode);
|
||||
Mode get_mode() const;
|
||||
|
||||
|
|
|
@ -227,6 +227,7 @@ bool BodyPairSW::setup(float p_step) {
|
|||
Vector3 global_A = xform_Au.xform(c.local_A);
|
||||
Vector3 global_B = xform_Bu.xform(c.local_B);
|
||||
|
||||
|
||||
real_t depth = c.normal.dot(global_A - global_B);
|
||||
|
||||
if (depth<=0) {
|
||||
|
|
|
@ -323,6 +323,7 @@ public:
|
|||
virtual Transform get_transform() const { return body->get_transform(); }
|
||||
|
||||
virtual void add_force(const Vector3& p_force, const Vector3& p_pos) { body->add_force(p_force,p_pos); }
|
||||
virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j) { body->apply_impulse(p_pos,p_j); }
|
||||
|
||||
virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
|
||||
virtual bool is_sleeping() const { return !body->is_active(); }
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -85,6 +85,7 @@ void PhysicsDirectBodyState::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("get_transform"),&PhysicsDirectBodyState::get_transform);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_force","force","pos"),&PhysicsDirectBodyState::add_force);
|
||||
ObjectTypeDB::bind_method(_MD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state);
|
||||
ObjectTypeDB::bind_method(_MD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping);
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
virtual Transform get_transform() const=0;
|
||||
|
||||
virtual void add_force(const Vector3& p_force, const Vector3& p_pos)=0;
|
||||
virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j)=0;
|
||||
|
||||
virtual void set_sleep_state(bool p_enable)=0;
|
||||
virtual bool is_sleeping() const=0;
|
||||
|
|
|
@ -507,6 +507,7 @@ public:
|
|||
float octree_lattice_size;
|
||||
float octree_lattice_divide;
|
||||
float texture_multiplier;
|
||||
float lightmap_multiplier;
|
||||
int octree_steps;
|
||||
Vector2 octree_tex_pixel_size;
|
||||
};
|
||||
|
@ -520,6 +521,7 @@ public:
|
|||
Vector<float> morph_values;
|
||||
BakedLightData *baked_light;
|
||||
Transform *baked_light_octree_xform;
|
||||
int baked_lightmap_id;
|
||||
bool mirror :8;
|
||||
bool depth_scale :8;
|
||||
bool billboard :8;
|
||||
|
|
|
@ -1005,6 +1005,11 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
|
|||
|
||||
const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={
|
||||
|
||||
{ "SRC_VERTEX", TYPE_VEC3},
|
||||
{ "SRC_NORMAL", TYPE_VEC3},
|
||||
{ "SRC_TANGENT", TYPE_VEC3},
|
||||
{ "SRC_BINORMALF", TYPE_FLOAT},
|
||||
|
||||
{ "VERTEX", TYPE_VEC3},
|
||||
{ "NORMAL", TYPE_VEC3},
|
||||
{ "TANGENT", TYPE_VEC3},
|
||||
|
@ -1023,6 +1028,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={
|
|||
{ "WORLD_MATRIX", TYPE_MAT4},
|
||||
{ "INV_CAMERA_MATRIX", TYPE_MAT4},
|
||||
{ "PROJECTION_MATRIX", TYPE_MAT4},
|
||||
{ "MODELVIEW_MATRIX", TYPE_MAT4},
|
||||
{ "INSTANCE_ID", TYPE_FLOAT},
|
||||
{ "TIME", TYPE_FLOAT},
|
||||
{ NULL, TYPE_VOID},
|
||||
|
|
|
@ -148,7 +148,7 @@ String VisualServerRaster::shader_get_fragment_code(RID p_shader) const{
|
|||
|
||||
String VisualServerRaster::shader_get_light_code(RID p_shader) const{
|
||||
|
||||
return rasterizer->shader_get_fragment_code(p_shader);
|
||||
return rasterizer->shader_get_light_code(p_shader);
|
||||
}
|
||||
|
||||
void VisualServerRaster::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
|
||||
|
@ -1038,6 +1038,7 @@ RID VisualServerRaster::baked_light_create() {
|
|||
baked_light->data.octree_lattice_size=0;
|
||||
baked_light->data.octree_lattice_divide=0;
|
||||
baked_light->data.octree_steps=1;
|
||||
baked_light->data.lightmap_multiplier=1.0;
|
||||
|
||||
return baked_light_owner.make_rid( baked_light );
|
||||
|
||||
|
@ -1063,6 +1064,26 @@ VisualServer::BakedLightMode VisualServerRaster::baked_light_get_mode(RID p_bake
|
|||
|
||||
}
|
||||
|
||||
void VisualServerRaster::baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier) {
|
||||
|
||||
VS_CHANGED;
|
||||
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
|
||||
ERR_FAIL_COND(!baked_light);
|
||||
|
||||
baked_light->data.lightmap_multiplier=p_multiplier;
|
||||
|
||||
}
|
||||
|
||||
float VisualServerRaster::baked_light_get_lightmap_multiplier(RID p_baked_light) const{
|
||||
|
||||
const BakedLight *baked_light = baked_light_owner.get(p_baked_light);
|
||||
ERR_FAIL_COND_V(!baked_light,0);
|
||||
|
||||
return baked_light->data.lightmap_multiplier;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree){
|
||||
|
||||
VS_CHANGED;
|
||||
|
@ -2568,7 +2589,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_i
|
|||
Instance *instance = instance_owner.get( p_instance );
|
||||
ERR_FAIL_COND( !instance );
|
||||
|
||||
instance->lightmap_texture_index=p_tex_id;
|
||||
instance->data.baked_lightmap_id=p_tex_id;
|
||||
|
||||
|
||||
}
|
||||
|
@ -2577,7 +2598,7 @@ int VisualServerRaster::instance_geometry_get_baked_light_texture_index(RID p_in
|
|||
const Instance *instance = instance_owner.get( p_instance );
|
||||
ERR_FAIL_COND_V( !instance,0 );
|
||||
|
||||
return instance->lightmap_texture_index;
|
||||
return instance->data.baked_lightmap_id;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class VisualServerRaster : public VisualServer {
|
|||
float draw_range_begin;
|
||||
float draw_range_end;
|
||||
float extra_margin;
|
||||
int lightmap_texture_index;
|
||||
|
||||
|
||||
|
||||
Rasterizer::InstanceData data;
|
||||
|
@ -267,6 +267,7 @@ class VisualServerRaster : public VisualServer {
|
|||
data.billboard_y=false;
|
||||
data.baked_light=NULL;
|
||||
data.baked_light_octree_xform=NULL;
|
||||
data.baked_lightmap_id=-1;
|
||||
version=1;
|
||||
room_info=NULL;
|
||||
room=NULL;
|
||||
|
@ -278,7 +279,7 @@ class VisualServerRaster : public VisualServer {
|
|||
draw_range_end=0;
|
||||
extra_margin=0;
|
||||
visible_in_all_rooms=false;
|
||||
lightmap_texture_index=-1;
|
||||
|
||||
baked_light=NULL;
|
||||
baked_light_info=NULL;
|
||||
BLE=NULL;
|
||||
|
@ -942,6 +943,9 @@ public:
|
|||
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree);
|
||||
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const;
|
||||
|
||||
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier);
|
||||
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const;
|
||||
|
||||
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id);
|
||||
virtual void baked_light_clear_lightmaps(RID p_baked_light);
|
||||
|
||||
|
|
|
@ -909,6 +909,8 @@ public:
|
|||
FUNC2(baked_light_set_octree,RID,DVector<uint8_t>);
|
||||
FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID);
|
||||
|
||||
FUNC2(baked_light_set_lightmap_multiplier,RID,float);
|
||||
FUNC1RC(float,baked_light_get_lightmap_multiplier,RID);
|
||||
|
||||
FUNC3(baked_light_add_lightmap,RID,RID,int);
|
||||
FUNC1(baked_light_clear_lightmaps,RID);
|
||||
|
|
|
@ -585,6 +585,9 @@ public:
|
|||
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0;
|
||||
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0;
|
||||
|
||||
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0;
|
||||
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0;
|
||||
|
||||
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0;
|
||||
virtual void baked_light_clear_lightmaps(RID p_baked_light)=0;
|
||||
|
||||
|
|
BIN
tools/editor/icons/icon_light_map.png
Normal file
BIN
tools/editor/icons/icon_light_map.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 441 B |
|
@ -407,6 +407,7 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
|
|||
|
||||
rim->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
|
||||
rim->set_option("flags",flags);
|
||||
print_line("GET FLAGS: "+itos(texture_options->get_flags()));
|
||||
rim->set_option("texture_flags",texture_options->get_flags());
|
||||
rim->set_option("texture_format",texture_options->get_format());
|
||||
rim->set_option("texture_quality",texture_options->get_quality());
|
||||
|
@ -640,6 +641,7 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
|
|||
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,"Materials","Set Alpha in Materials (-alpha)",true},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,"Materials","Set Vert. Color in Materials (-vcol)",true},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,"Actions","SRGB->Linear Of Diffuse Textures",false},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,"Actions","Set Material Lightmap to UV2 if Tex2Array Exists",true},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,"Create","Create Collisions (-col},-colonly)",true},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,"Create","Create Portals (-portal)",true},
|
||||
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,"Create","Create Rooms (-room)",true},
|
||||
|
@ -1036,7 +1038,7 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
|
|||
}
|
||||
|
||||
|
||||
if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR) && p_node->cast_to<MeshInstance>()) {
|
||||
if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR|SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS) && p_node->cast_to<MeshInstance>()) {
|
||||
|
||||
MeshInstance *mi = p_node->cast_to<MeshInstance>();
|
||||
|
||||
|
@ -1061,6 +1063,10 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
|
|||
mat->set_name(_fixstr(mat->get_name(),"vcol"));
|
||||
}
|
||||
|
||||
if (p_flags&SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS && m->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
|
||||
mat->set_flag(Material::FLAG_LIGHTMAP_ON_UV2,true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1224,13 +1230,13 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
|
|||
col->set_name("col");
|
||||
p_node->add_child(col);
|
||||
|
||||
|
||||
StaticBody *sb = col->cast_to<StaticBody>();
|
||||
StaticBody *sb=col->cast_to<StaticBody>();
|
||||
CollisionShape *colshape = memnew( CollisionShape);
|
||||
colshape->set_shape(sb->get_shape(0));
|
||||
colshape->set_name("shape");
|
||||
sb->add_child(colshape);
|
||||
col->add_child(colshape);
|
||||
colshape->set_owner(p_node->get_owner());
|
||||
sb->set_owner(p_node->get_owner());
|
||||
|
||||
} else if (p_flags&SCENE_FLAG_CREATE_NAVMESH &&_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
|
||||
|
||||
|
@ -1892,8 +1898,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
|||
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
|
||||
print_line("flags: "+itos(image_flags));
|
||||
uint32_t flags = image_flags;
|
||||
if (E->get())
|
||||
flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR;
|
||||
|
||||
imd->set_option("flags",flags);
|
||||
imd->set_option("format",image_format);
|
||||
imd->set_option("quality",image_quality);
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
|
||||
SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
|
||||
SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
|
||||
SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -725,6 +725,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
|
|||
bool atlas = from->get_option("atlas");
|
||||
|
||||
int flags=from->get_option("flags");
|
||||
print_line("GET FLAGS: "+itos(flags));
|
||||
uint32_t tex_flags=0;
|
||||
|
||||
if (flags&EditorTextureImportPlugin::IMAGE_FLAG_REPEAT)
|
||||
|
@ -993,6 +994,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
|
|||
|
||||
if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
|
||||
|
||||
print_line("CONVERT BECAUSE: "+itos(flags));
|
||||
image.srgb_to_linear();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>&
|
|||
}
|
||||
|
||||
|
||||
void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) {
|
||||
void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture) {
|
||||
|
||||
|
||||
for(int i=0;i<p_mesh->get_surface_count();i++) {
|
||||
|
@ -55,6 +55,7 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
|
|||
Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i);
|
||||
|
||||
MeshMaterial *matptr=NULL;
|
||||
int baked_tex=p_baked_texture;
|
||||
|
||||
if (mat.is_valid()) {
|
||||
|
||||
|
@ -112,6 +113,8 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
|
|||
DVector<Vector3>::Read vr=vertices.read();
|
||||
DVector<Vector2> uv;
|
||||
DVector<Vector2>::Read uvr;
|
||||
DVector<Vector2> uv2;
|
||||
DVector<Vector2>::Read uv2r;
|
||||
DVector<Vector3> normal;
|
||||
DVector<Vector3>::Read normalr;
|
||||
bool read_uv=false;
|
||||
|
@ -122,6 +125,18 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
|
|||
uv=a[Mesh::ARRAY_TEX_UV];
|
||||
uvr=uv.read();
|
||||
read_uv=true;
|
||||
|
||||
if (mat.is_valid() && mat->get_flag(Material::FLAG_LIGHTMAP_ON_UV2) && p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
|
||||
|
||||
uv2=a[Mesh::ARRAY_TEX_UV2];
|
||||
uv2r=uv2.read();
|
||||
|
||||
} else {
|
||||
uv2r=uv.read();
|
||||
if (baked_light->get_transfer_lightmaps_only_to_uv2()) {
|
||||
baked_tex=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_NORMAL) {
|
||||
|
@ -145,11 +160,16 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
|
|||
t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]);
|
||||
t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]);
|
||||
t.material=matptr;
|
||||
t.baked_texture=baked_tex;
|
||||
if (read_uv) {
|
||||
|
||||
t.uvs[0]=uvr[ ir[i*3+0] ];
|
||||
t.uvs[1]=uvr[ ir[i*3+1] ];
|
||||
t.uvs[2]=uvr[ ir[i*3+2] ];
|
||||
|
||||
t.bake_uvs[0]=uv2r[ ir[i*3+0] ];
|
||||
t.bake_uvs[1]=uv2r[ ir[i*3+1] ];
|
||||
t.bake_uvs[2]=uv2r[ ir[i*3+2] ];
|
||||
}
|
||||
if (read_normal) {
|
||||
|
||||
|
@ -167,11 +187,17 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
|
|||
t.vertices[1]=p_xform.xform(vr[ i*3+1 ]);
|
||||
t.vertices[2]=p_xform.xform(vr[ i*3+2 ]);
|
||||
t.material=matptr;
|
||||
t.baked_texture=baked_tex;
|
||||
if (read_uv) {
|
||||
|
||||
t.uvs[0]=uvr[ i*3+0 ];
|
||||
t.uvs[1]=uvr[ i*3+1 ];
|
||||
t.uvs[2]=uvr[ i*3+2 ];
|
||||
|
||||
t.bake_uvs[0]=uv2r[ i*3+0 ];
|
||||
t.bake_uvs[1]=uv2r[ i*3+1 ];
|
||||
t.bake_uvs[2]=uv2r[ i*3+2 ];
|
||||
|
||||
}
|
||||
if (read_normal) {
|
||||
|
||||
|
@ -193,7 +219,7 @@ void BakedLightBaker::_parse_geometry(Node* p_node) {
|
|||
MeshInstance *meshi=p_node->cast_to<MeshInstance>();
|
||||
Ref<Mesh> mesh=meshi->get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
_add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform());
|
||||
_add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform(),meshi->get_baked_light_texture_id());
|
||||
}
|
||||
} else if (p_node->cast_to<Light>()) {
|
||||
|
||||
|
@ -214,9 +240,11 @@ void BakedLightBaker::_parse_geometry(Node* p_node) {
|
|||
dirl.spot_angle=dl->get_parameter(DirectionalLight::PARAM_SPOT_ANGLE);
|
||||
dirl.spot_attenuation=dl->get_parameter(DirectionalLight::PARAM_SPOT_ATTENUATION);
|
||||
dirl.attenuation=dl->get_parameter(DirectionalLight::PARAM_ATTENUATION);
|
||||
dirl.darkening=dl->get_parameter(DirectionalLight::PARAM_SHADOW_DARKENING);
|
||||
dirl.radius=dl->get_parameter(DirectionalLight::PARAM_RADIUS);
|
||||
dirl.bake_direct=dl->get_bake_mode()==Light::BAKE_MODE_FULL;
|
||||
dirl.rays_thrown=0;
|
||||
dirl.bake_shadow=dl->get_bake_mode()==Light::BAKE_MODE_INDIRECT_AND_SHADOWS;
|
||||
lights.push_back(dirl);
|
||||
}
|
||||
|
||||
|
@ -720,7 +748,7 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos,
|
|||
float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
|
||||
float damp = Math::abs(p_plane.normal.dot(Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2])));
|
||||
intensity*=pow(damp,edge_damp);
|
||||
intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size);
|
||||
//intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size);
|
||||
octant.light[p_light_index].accum[i][0]+=p_light.r*intensity;
|
||||
octant.light[p_light_index].accum[i][1]+=p_light.g*intensity;
|
||||
octant.light[p_light_index].accum[i][2]+=p_light.b*intensity;
|
||||
|
@ -1310,7 +1338,7 @@ double BakedLightBaker::get_normalization(int p_light_idx) const {
|
|||
nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel
|
||||
nrg*=dl.constant;
|
||||
//nrg*=5;
|
||||
print_line("CS: "+rtos(cell_size));
|
||||
|
||||
|
||||
return nrg;
|
||||
}
|
||||
|
@ -1460,6 +1488,13 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
|
|||
normal_damp=baked_light->get_normal_damp();
|
||||
octree_extra_margin=baked_light->get_cell_extra_margin();
|
||||
|
||||
baked_textures.clear();
|
||||
for(int i=0;i<baked_light->get_lightmaps_count();i++) {
|
||||
BakeTexture bt;
|
||||
bt.width=baked_light->get_lightmap_gen_size(i).x;
|
||||
bt.height=baked_light->get_lightmap_gen_size(i).y;
|
||||
baked_textures.push_back(bt);
|
||||
}
|
||||
|
||||
|
||||
ep.step("Parsing Geometry",0);
|
||||
|
@ -1690,6 +1725,484 @@ void BakedLightBaker::_stop_thread() {
|
|||
thread=NULL;
|
||||
}
|
||||
|
||||
void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) {
|
||||
|
||||
|
||||
uint8_t *ptr = &image[(y*width+x)*4];
|
||||
int lc = lights.size();
|
||||
|
||||
|
||||
Color color;
|
||||
|
||||
Octant *octants=octant_pool.ptr();
|
||||
|
||||
|
||||
int octant_idx=0;
|
||||
|
||||
|
||||
while(true) {
|
||||
|
||||
Octant &octant=octants[octant_idx];
|
||||
|
||||
if (octant.leaf) {
|
||||
|
||||
Vector3 lpos = p_pos-octant.aabb.pos;
|
||||
lpos/=octant.aabb.size;
|
||||
|
||||
Vector3 cols[8];
|
||||
|
||||
for(int i=0;i<8;i++) {
|
||||
|
||||
for(int j=0;j<lc;j++) {
|
||||
cols[i].x+=octant.light[j].accum[i][0]*p_norm_ptr[j];
|
||||
cols[i].y+=octant.light[j].accum[i][1]*p_norm_ptr[j];
|
||||
cols[i].z+=octant.light[j].accum[i][2]*p_norm_ptr[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Vector3 final = (cols[0] + (cols[1] - cols[0]) * lpos.y);
|
||||
final = final + ((cols[2] + (cols[3] - cols[2]) * lpos.y) - final)*lpos.x;
|
||||
|
||||
Vector3 final2 = (cols[4+0] + (cols[4+1] - cols[4+0]) * lpos.y);
|
||||
final2 = final2 + ((cols[4+2] + (cols[4+3] - cols[4+2]) * lpos.y) - final2)*lpos.x;*/
|
||||
|
||||
Vector3 finala = cols[0].linear_interpolate(cols[1],lpos.x);
|
||||
Vector3 finalb = cols[2].linear_interpolate(cols[3],lpos.x);
|
||||
Vector3 final = finala.linear_interpolate(finalb,lpos.y);
|
||||
|
||||
Vector3 final2a = cols[4+0].linear_interpolate(cols[4+1],lpos.x);
|
||||
Vector3 final2b = cols[4+2].linear_interpolate(cols[4+3],lpos.x);
|
||||
Vector3 final2 = final2a.linear_interpolate(final2b,lpos.y);
|
||||
|
||||
final = final.linear_interpolate(final2,lpos.z);
|
||||
if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
|
||||
final*=8.0;
|
||||
|
||||
|
||||
color.r=pow(final.x*mult,gamma);
|
||||
color.g=pow(final.y*mult,gamma);
|
||||
color.b=pow(final.z*mult,gamma);
|
||||
color.a=1.0;
|
||||
|
||||
int lc = lights.size();
|
||||
LightData *lv = lights.ptr();
|
||||
for(int i=0;i<lc;i++) {
|
||||
//shadow baking
|
||||
if (!lv[i].bake_shadow)
|
||||
continue;
|
||||
Vector3 from = p_pos+p_normal*0.01;
|
||||
Vector3 to;
|
||||
float att=0;
|
||||
switch(lv[i].type) {
|
||||
case VS::LIGHT_DIRECTIONAL: {
|
||||
to=from-lv[i].dir*lv[i].length;
|
||||
} break;
|
||||
case VS::LIGHT_OMNI: {
|
||||
to=lv[i].pos;
|
||||
float d = MIN(lv[i].radius,to.distance_to(from))/lv[i].radius;
|
||||
att=d;//1.0-d;
|
||||
} break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
uint32_t* stack = ray_stack;
|
||||
BVH **bstack = bvh_stack;
|
||||
|
||||
enum {
|
||||
TEST_RAY_BIT=0,
|
||||
VISIT_LEFT_BIT=1,
|
||||
VISIT_RIGHT_BIT=2,
|
||||
VISIT_DONE_BIT=3,
|
||||
|
||||
|
||||
};
|
||||
|
||||
bool intersected=false;
|
||||
|
||||
int level=0;
|
||||
|
||||
Vector3 n = (to-from);
|
||||
float len=n.length();
|
||||
if (len==0)
|
||||
continue;
|
||||
n/=len;
|
||||
|
||||
const BVH *bvhptr = bvh;
|
||||
|
||||
bstack[0]=bvh;
|
||||
stack[0]=TEST_RAY_BIT;
|
||||
|
||||
|
||||
while(!intersected) {
|
||||
|
||||
uint32_t mode = stack[level];
|
||||
const BVH &b = *bstack[level];
|
||||
bool done=false;
|
||||
|
||||
switch(mode) {
|
||||
case TEST_RAY_BIT: {
|
||||
|
||||
if (b.leaf) {
|
||||
|
||||
|
||||
Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
|
||||
|
||||
|
||||
Vector3 res;
|
||||
|
||||
if (f3.intersects_segment(from,to)) {
|
||||
intersected=true;
|
||||
done=true;
|
||||
}
|
||||
|
||||
stack[level]=VISIT_DONE_BIT;
|
||||
} else {
|
||||
|
||||
|
||||
bool valid = b.aabb.smits_intersect_ray(from,n,0,len);
|
||||
//bool valid = b.aabb.intersects_segment(p_begin,p_end);
|
||||
// bool valid = b.aabb.intersects(ray_aabb);
|
||||
|
||||
if (!valid) {
|
||||
|
||||
stack[level]=VISIT_DONE_BIT;
|
||||
|
||||
} else {
|
||||
|
||||
stack[level]=VISIT_LEFT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
} continue;
|
||||
case VISIT_LEFT_BIT: {
|
||||
|
||||
stack[level]=VISIT_RIGHT_BIT;
|
||||
bstack[level+1]=b.children[0];
|
||||
stack[level+1]=TEST_RAY_BIT;
|
||||
level++;
|
||||
|
||||
} continue;
|
||||
case VISIT_RIGHT_BIT: {
|
||||
|
||||
stack[level]=VISIT_DONE_BIT;
|
||||
bstack[level+1]=b.children[1];
|
||||
stack[level+1]=TEST_RAY_BIT;
|
||||
level++;
|
||||
} continue;
|
||||
case VISIT_DONE_BIT: {
|
||||
|
||||
if (level==0) {
|
||||
done=true;
|
||||
break;
|
||||
} else
|
||||
level--;
|
||||
|
||||
} continue;
|
||||
}
|
||||
|
||||
|
||||
if (done)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (intersected) {
|
||||
|
||||
color.a=Math::lerp(MAX(0.01,lv[i].darkening),1.0,att);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
|
||||
Vector3 lpos = p_pos - octant.aabb.pos;
|
||||
Vector3 half = octant.aabb.size * 0.5;
|
||||
|
||||
int ofs=0;
|
||||
|
||||
if (lpos.x >= half.x)
|
||||
ofs|=1;
|
||||
if (lpos.y >= half.y)
|
||||
ofs|=2;
|
||||
if (lpos.z >= half.z)
|
||||
ofs|=4;
|
||||
|
||||
octant_idx = octant.children[ofs];
|
||||
|
||||
if (octant_idx==0)
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ptr[0]=CLAMP(color.r*255.0,0,255);
|
||||
ptr[1]=CLAMP(color.g*255.0,0,255);
|
||||
ptr[2]=CLAMP(color.b*255.0,0,255);
|
||||
ptr[3]=CLAMP(color.a*255.0,0,255);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Error BakedLightBaker::transfer_to_lightmaps() {
|
||||
|
||||
if (!triangles.size() || baked_textures.size()==0)
|
||||
return ERR_UNCONFIGURED;
|
||||
|
||||
EditorProgress ep("transfer_to_lightmaps","Transfer to Lightmaps:",baked_textures.size()*2+triangles.size());
|
||||
|
||||
for(int i=0;i<baked_textures.size();i++) {
|
||||
|
||||
ERR_FAIL_COND_V( baked_textures[i].width<=0 || baked_textures[i].height<=0,ERR_UNCONFIGURED );
|
||||
|
||||
baked_textures[i].data.resize( baked_textures[i].width*baked_textures[i].height*4 );
|
||||
zeromem(baked_textures[i].data.ptr(),baked_textures[i].data.size());
|
||||
ep.step("Allocating Texture #"+itos(i+1),i);
|
||||
}
|
||||
|
||||
Vector<double> norm_arr;
|
||||
norm_arr.resize(lights.size());
|
||||
|
||||
for(int i=0;i<lights.size();i++) {
|
||||
norm_arr[i] = 1.0/get_normalization(i);
|
||||
}
|
||||
float gamma = baked_light->get_gamma_adjust();
|
||||
float mult = baked_light->get_energy_multiplier();
|
||||
|
||||
|
||||
const double *normptr=norm_arr.ptr();
|
||||
for(int i=0;i<triangles.size();i++) {
|
||||
|
||||
if (i%200==0) {
|
||||
ep.step("Baking Triangle #"+itos(i),i+baked_textures.size());
|
||||
}
|
||||
Triangle &t=triangles[i];
|
||||
if (t.baked_texture<0 || t.baked_texture>=baked_textures.size())
|
||||
continue;
|
||||
|
||||
BakeTexture &bt=baked_textures[t.baked_texture];
|
||||
Vector3 normal = Plane(t.vertices[0],t.vertices[1],t.vertices[2]).normal;
|
||||
|
||||
|
||||
int x[3];
|
||||
int y[3];
|
||||
|
||||
Vector3 vertices[3]={
|
||||
t.vertices[0],
|
||||
t.vertices[1],
|
||||
t.vertices[2]
|
||||
};
|
||||
|
||||
for(int j=0;j<3;j++) {
|
||||
|
||||
x[j]=t.bake_uvs[j].x*bt.width;
|
||||
y[j]=t.bake_uvs[j].y*bt.height;
|
||||
x[j]=CLAMP(x[j],0,bt.width-1);
|
||||
y[j]=CLAMP(y[j],0,bt.height-1);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
|
||||
// sort the points vertically
|
||||
if (y[1] > y[2]) {
|
||||
SWAP(x[1], x[2]);
|
||||
SWAP(y[1], y[2]);
|
||||
SWAP(vertices[1],vertices[2]);
|
||||
}
|
||||
if (y[0] > y[1]) {
|
||||
SWAP(x[0], x[1]);
|
||||
SWAP(y[0], y[1]);
|
||||
SWAP(vertices[0],vertices[1]);
|
||||
}
|
||||
if (y[1] > y[2]) {
|
||||
SWAP(x[1], x[2]);
|
||||
SWAP(y[1], y[2]);
|
||||
SWAP(vertices[1],vertices[2]);
|
||||
}
|
||||
|
||||
double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
|
||||
double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
|
||||
double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
|
||||
double xf = x[0];
|
||||
double xt = x[0] + dx_upper; // if y[0] == y[1], special case
|
||||
for (int yi = y[0]; yi <= (y[2] > bt.height-1 ? bt.height-1 : y[2]); yi++)
|
||||
{
|
||||
if (yi >= 0) {
|
||||
for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < bt.width ? xt : bt.width-1) ; xi++) {
|
||||
//pixels[int(x + y * width)] = color;
|
||||
|
||||
Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
|
||||
Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
|
||||
//vertices[2] - vertices[0];
|
||||
Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
|
||||
float d00 = v0.dot( v0);
|
||||
float d01 = v0.dot( v1);
|
||||
float d11 = v1.dot( v1);
|
||||
float d20 = v2.dot( v0);
|
||||
float d21 = v2.dot( v1);
|
||||
float denom = (d00 * d11 - d01 * d01);
|
||||
Vector3 pos;
|
||||
if (denom==0) {
|
||||
pos=t.vertices[0];
|
||||
} else {
|
||||
float v = (d11 * d20 - d01 * d21) / denom;
|
||||
float w = (d00 * d21 - d01 * d20) / denom;
|
||||
float u = 1.0f - v - w;
|
||||
pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
|
||||
}
|
||||
_plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
|
||||
|
||||
}
|
||||
|
||||
for (int xi = (xf < bt.width ? int(xf) : bt.width-1); xi >= (xt > 0 ? xt : 0); xi--) {
|
||||
//pixels[int(x + y * width)] = color;
|
||||
Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
|
||||
Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
|
||||
//vertices[2] - vertices[0];
|
||||
Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
|
||||
float d00 = v0.dot( v0);
|
||||
float d01 = v0.dot( v1);
|
||||
float d11 = v1.dot( v1);
|
||||
float d20 = v2.dot( v0);
|
||||
float d21 = v2.dot( v1);
|
||||
float denom = (d00 * d11 - d01 * d01);
|
||||
Vector3 pos;
|
||||
if (denom==0) {
|
||||
pos=t.vertices[0];
|
||||
} else {
|
||||
float v = (d11 * d20 - d01 * d21) / denom;
|
||||
float w = (d00 * d21 - d01 * d20) / denom;
|
||||
float u = 1.0f - v - w;
|
||||
pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
|
||||
}
|
||||
|
||||
_plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
|
||||
|
||||
}
|
||||
}
|
||||
xf += dx_far;
|
||||
if (yi < y[1])
|
||||
xt += dx_upper;
|
||||
else
|
||||
xt += dx_low;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(int i=0;i<baked_textures.size();i++) {
|
||||
|
||||
|
||||
{
|
||||
|
||||
ep.step("Post-Processing Texture #"+itos(i),i+baked_textures.size()+triangles.size());
|
||||
|
||||
BakeTexture &bt=baked_textures[i];
|
||||
|
||||
Vector<uint8_t> copy_data=bt.data;
|
||||
uint8_t *data=bt.data.ptr();
|
||||
uint8_t *src_data=copy_data.ptr();
|
||||
const int max_radius=8;
|
||||
const int shadow_radius=2;
|
||||
const int max_dist=0x7FFFFFFF;
|
||||
|
||||
for(int x=0;x<bt.width;x++) {
|
||||
|
||||
for(int y=0;y<bt.height;y++) {
|
||||
|
||||
|
||||
uint8_t a = copy_data[(y*bt.width+x)*4+3];
|
||||
|
||||
if (a>0) {
|
||||
//blur shadow
|
||||
|
||||
int from_x = MAX(0,x-shadow_radius);
|
||||
int to_x = MIN(bt.width-1,x+shadow_radius);
|
||||
int from_y = MAX(0,y-shadow_radius);
|
||||
int to_y = MIN(bt.height-1,y+shadow_radius);
|
||||
|
||||
int sum=0;
|
||||
int sumc=0;
|
||||
|
||||
for(int k=from_y;k<=to_y;k++) {
|
||||
for(int l=from_x;l<=to_x;l++) {
|
||||
|
||||
const uint8_t * rp = ©_data[(k*bt.width+l)<<2];
|
||||
|
||||
sum+=rp[3];
|
||||
sumc++;
|
||||
}
|
||||
}
|
||||
|
||||
sum/=sumc;
|
||||
data[(y*bt.width+x)*4+3]=sum;
|
||||
|
||||
} else {
|
||||
|
||||
int closest_dist=max_dist;
|
||||
uint8_t closest_color[4];
|
||||
|
||||
int from_x = MAX(0,x-max_radius);
|
||||
int to_x = MIN(bt.width-1,x+max_radius);
|
||||
int from_y = MAX(0,y-max_radius);
|
||||
int to_y = MIN(bt.height-1,y+max_radius);
|
||||
|
||||
for(int k=from_y;k<=to_y;k++) {
|
||||
for(int l=from_x;l<=to_x;l++) {
|
||||
|
||||
int dy = y-k;
|
||||
int dx = x-l;
|
||||
int dist = dy*dy+dx*dx;
|
||||
if (dist>=closest_dist)
|
||||
continue;
|
||||
|
||||
const uint8_t * rp = ©_data[(k*bt.width+l)<<2];
|
||||
|
||||
if (rp[3]==0)
|
||||
continue;
|
||||
|
||||
closest_dist=dist;
|
||||
closest_color[0]=rp[0];
|
||||
closest_color[1]=rp[1];
|
||||
closest_color[2]=rp[2];
|
||||
closest_color[3]=rp[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (closest_dist!=max_dist) {
|
||||
|
||||
data[(y*bt.width+x)*4+0]=closest_color[0];
|
||||
data[(y*bt.width+x)*4+1]=closest_color[1];
|
||||
data[(y*bt.width+x)*4+2]=closest_color[2];
|
||||
data[(y*bt.width+x)*4+3]=closest_color[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DVector<uint8_t> dv;
|
||||
dv.resize(baked_textures[i].data.size());
|
||||
{
|
||||
DVector<uint8_t>::Write w = dv.write();
|
||||
copymem(w.ptr(),baked_textures[i].data.ptr(),baked_textures[i].data.size());
|
||||
}
|
||||
|
||||
Image img(baked_textures[i].width,baked_textures[i].height,0,Image::FORMAT_RGBA,dv);
|
||||
Ref<ImageTexture> tex = memnew( ImageTexture );
|
||||
tex->create_from_image(img);
|
||||
baked_light->set_lightmap_texture(i,tex);
|
||||
}
|
||||
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void BakedLightBaker::clear() {
|
||||
|
||||
|
||||
|
@ -1711,7 +2224,14 @@ void BakedLightBaker::clear() {
|
|||
for(int i=0;i<octant_pool.size();i++) {
|
||||
if (octant_pool[i].leaf) {
|
||||
memdelete_arr( octant_pool[i].light );
|
||||
} Vector<double> norm_arr;
|
||||
norm_arr.resize(lights.size());
|
||||
|
||||
for(int i=0;i<lights.size();i++) {
|
||||
norm_arr[i] = 1.0/get_normalization(i);
|
||||
}
|
||||
|
||||
const double *normptr=norm_arr.ptr();
|
||||
}
|
||||
octant_pool.clear();
|
||||
octant_pool_size=0;
|
||||
|
|
|
@ -94,11 +94,13 @@ public:
|
|||
|
||||
struct Triangle {
|
||||
|
||||
AABB aabb;
|
||||
AABB aabb;
|
||||
Vector3 vertices[3];
|
||||
Vector2 uvs[3];
|
||||
Vector2 bake_uvs[3];
|
||||
Vector3 normals[3];
|
||||
MeshMaterial *material;
|
||||
int baked_texture;
|
||||
|
||||
_FORCE_INLINE_ Vector2 get_uv(const Vector3& p_pos) {
|
||||
|
||||
|
@ -180,6 +182,12 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct BakeTexture {
|
||||
|
||||
Vector<uint8_t> data;
|
||||
int width,height;
|
||||
};
|
||||
|
||||
|
||||
struct LightData {
|
||||
|
||||
|
@ -194,10 +202,12 @@ public:
|
|||
float energy;
|
||||
float length;
|
||||
int rays_thrown;
|
||||
bool bake_shadow;
|
||||
|
||||
float radius;
|
||||
float attenuation;
|
||||
float spot_angle;
|
||||
float darkening;
|
||||
float spot_attenuation;
|
||||
float area;
|
||||
|
||||
|
@ -220,6 +230,7 @@ public:
|
|||
int octant_pool_size;
|
||||
BVH*bvh;
|
||||
Vector<Triangle> triangles;
|
||||
Vector<BakeTexture> baked_textures;
|
||||
Transform base_inv;
|
||||
int leaf_list;
|
||||
int octree_depth;
|
||||
|
@ -255,13 +266,14 @@ public:
|
|||
|
||||
|
||||
MeshTexture* _get_mat_tex(const Ref<Texture>& p_tex);
|
||||
void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform);
|
||||
void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture=-1);
|
||||
void _parse_geometry(Node* p_node);
|
||||
BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth);
|
||||
void _make_bvh();
|
||||
void _make_octree();
|
||||
void _make_octree_texture();
|
||||
void _octree_insert(int p_octant, Triangle* p_triangle, int p_depth);
|
||||
_FORCE_INLINE_ void _plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma);
|
||||
|
||||
|
||||
void _free_bvh(BVH* p_bvh);
|
||||
|
@ -302,6 +314,8 @@ public:
|
|||
bool is_paused();
|
||||
int get_rays_sec() { return rays_sec; }
|
||||
|
||||
Error transfer_to_lightmaps();
|
||||
|
||||
void update_octree_image(DVector<uint8_t> &p_image);
|
||||
|
||||
Ref<BakedLight> get_baked_light() { return baked_light; }
|
||||
|
|
|
@ -38,6 +38,7 @@ void BakedLightEditor::_notification(int p_option) {
|
|||
|
||||
button_bake->set_icon(get_icon("Bake","EditorIcons"));
|
||||
button_reset->set_icon(get_icon("Reload","EditorIcons"));
|
||||
button_make_lightmaps->set_icon(get_icon("LightMap","EditorIcons"));
|
||||
}
|
||||
|
||||
if (p_option==NOTIFICATION_PROCESS) {
|
||||
|
@ -148,7 +149,7 @@ void BakedLightEditor::_menu_option(int p_option) {
|
|||
ERR_FAIL_COND(!node);
|
||||
ERR_FAIL_COND(node->get_baked_light().is_null());
|
||||
baker->bake(node->get_baked_light(),node);
|
||||
|
||||
node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE);
|
||||
update_timeout=0;
|
||||
set_process(true);
|
||||
|
||||
|
@ -180,14 +181,19 @@ void BakedLightEditor::_bake_pressed() {
|
|||
|
||||
set_process(false);
|
||||
bake_info->set_text("");
|
||||
button_reset->show();
|
||||
button_make_lightmaps->show();
|
||||
|
||||
} else {
|
||||
|
||||
update_timeout=0;
|
||||
set_process(true);
|
||||
button_make_lightmaps->hide();
|
||||
button_reset->hide();
|
||||
}
|
||||
|
||||
} else {
|
||||
baker->bake(node->get_baked_light(),node);
|
||||
node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE);
|
||||
update_timeout=0;
|
||||
set_process(true);
|
||||
}
|
||||
|
@ -216,13 +222,27 @@ void BakedLightEditor::edit(BakedLightInstance *p_baked_light) {
|
|||
|
||||
}
|
||||
|
||||
void BakedLightEditor::_bake_lightmaps() {
|
||||
|
||||
Error err = baker->transfer_to_lightmaps();
|
||||
if (err) {
|
||||
|
||||
err_dialog->set_text("Error baking to lightmaps!\nMake sure that a bake has just\n happened and that lightmaps are\n configured. ");
|
||||
err_dialog->popup_centered(Size2(350,70));
|
||||
return;
|
||||
}
|
||||
|
||||
node->get_baked_light()->set_mode(BakedLight::MODE_LIGHTMAPS);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void BakedLightEditor::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_menu_option",&BakedLightEditor::_menu_option);
|
||||
ObjectTypeDB::bind_method("_bake_pressed",&BakedLightEditor::_bake_pressed);
|
||||
ObjectTypeDB::bind_method("_clear_pressed",&BakedLightEditor::_clear_pressed);
|
||||
ObjectTypeDB::bind_method("_bake_lightmaps",&BakedLightEditor::_bake_lightmaps);
|
||||
}
|
||||
|
||||
BakedLightEditor::BakedLightEditor() {
|
||||
|
@ -233,6 +253,11 @@ BakedLightEditor::BakedLightEditor() {
|
|||
button_bake->set_text("Bake!");
|
||||
button_bake->set_toggle_mode(true);
|
||||
button_reset = memnew( Button );
|
||||
button_make_lightmaps = memnew( Button );
|
||||
button_bake->set_tooltip("Start/Unpause the baking process.\nThis bakes lighting into the lightmap octree.");
|
||||
button_make_lightmaps ->set_tooltip("Convert the lightmap octree to lightmap textures\n(must have set up UV/Lightmaps properly before!).");
|
||||
|
||||
|
||||
bake_info = memnew( Label );
|
||||
bake_hbox->add_child( button_bake );
|
||||
bake_hbox->add_child( button_reset );
|
||||
|
@ -243,8 +268,15 @@ BakedLightEditor::BakedLightEditor() {
|
|||
node=NULL;
|
||||
baker = memnew( BakedLightBaker );
|
||||
|
||||
bake_hbox->add_child(button_make_lightmaps);
|
||||
button_make_lightmaps->hide();
|
||||
|
||||
button_bake->connect("pressed",this,"_bake_pressed");
|
||||
button_reset->connect("pressed",this,"_clear_pressed");
|
||||
button_make_lightmaps->connect("pressed",this,"_bake_lightmaps");
|
||||
button_reset->hide();
|
||||
button_reset->set_tooltip("Reset the lightmap octree baking process (start over).");
|
||||
|
||||
|
||||
update_timeout=0;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class BakedLightEditor : public Control {
|
|||
HBoxContainer *bake_hbox;
|
||||
Button *button_bake;
|
||||
Button *button_reset;
|
||||
Button *button_make_lightmaps;
|
||||
Label *bake_info;
|
||||
|
||||
|
||||
|
@ -41,6 +42,8 @@ class BakedLightEditor : public Control {
|
|||
MENU_OPTION_CLEAR
|
||||
};
|
||||
|
||||
void _bake_lightmaps();
|
||||
|
||||
void _bake_pressed();
|
||||
void _clear_pressed();
|
||||
|
||||
|
|
|
@ -436,8 +436,10 @@ void ShaderEditor::save_external_data() {
|
|||
void ShaderEditor::apply_shaders() {
|
||||
|
||||
|
||||
if (shader.is_valid())
|
||||
if (shader.is_valid()) {
|
||||
shader->set_code(vertex_editor->get_text_edit()->get_text(),fragment_editor->get_text_edit()->get_text(),light_editor->get_text_edit()->get_text(),0,0);
|
||||
shader->set_edited(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderEditor::_close_callback() {
|
||||
|
|
|
@ -66,11 +66,19 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id)
|
|||
} else if (p_id==BUTTON_VISIBILITY) {
|
||||
|
||||
|
||||
if (n->is_type("GeometryInstance")) {
|
||||
bool v = n->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
|
||||
undo_redo->create_action("Toggle Geometry Visible");
|
||||
undo_redo->add_do_method(n,"set_flag",VS::INSTANCE_FLAG_VISIBLE,!v);
|
||||
undo_redo->add_undo_method(n,"set_flag",VS::INSTANCE_FLAG_VISIBLE,v);
|
||||
if (n->is_type("Spatial")) {
|
||||
|
||||
Spatial *ci = n->cast_to<Spatial>();
|
||||
if (!ci->is_visible() && ci->get_parent_spatial() && !ci->get_parent_spatial()->is_visible()) {
|
||||
error->set_text("This item cannot be made visible because the parent is hidden. Unhide the parent first.");
|
||||
error->popup_centered_minsize(Size2(400,80));
|
||||
return;
|
||||
}
|
||||
|
||||
bool v = !bool(n->call("is_hidden"));
|
||||
undo_redo->create_action("Toggle Spatial Visible");
|
||||
undo_redo->add_do_method(n,"_set_visible_",!v);
|
||||
undo_redo->add_undo_method(n,"_set_visible_",v);
|
||||
undo_redo->commit_action();
|
||||
} else if (n->is_type("CanvasItem")) {
|
||||
|
||||
|
@ -189,9 +197,9 @@ void SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
|
|||
if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
|
||||
p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
|
||||
|
||||
} else if (p_node->is_type("GeometryInstance")) {
|
||||
} else if (p_node->is_type("Spatial")) {
|
||||
|
||||
bool h = !p_node->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
|
||||
bool h = p_node->call("is_hidden");
|
||||
if (h)
|
||||
item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
|
||||
else
|
||||
|
@ -226,7 +234,16 @@ void SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
|
|||
|
||||
void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
|
||||
|
||||
|
||||
if (p_node!=get_scene_node() && !p_node->get_owner()) {
|
||||
|
||||
return;
|
||||
}
|
||||
TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
|
||||
if (!item) {
|
||||
|
||||
return;
|
||||
}
|
||||
int idx=item->get_button_by_id(0,BUTTON_VISIBILITY);
|
||||
ERR_FAIL_COND(idx==-1);
|
||||
|
||||
|
@ -234,11 +251,10 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
|
|||
|
||||
if (p_node->is_type("CanvasItem")) {
|
||||
visible = !p_node->call("is_hidden");
|
||||
} else if (p_node->is_type("GeometryInstance")) {
|
||||
visible = p_node->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
|
||||
} else if (p_node->is_type("Spatial")) {
|
||||
visible = !p_node->call("is_hidden");
|
||||
}
|
||||
|
||||
|
||||
if (!visible)
|
||||
item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
|
||||
else
|
||||
|
@ -274,7 +290,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) {
|
|||
if (p_node->is_connected("script_changed",this,"_node_script_changed"))
|
||||
p_node->disconnect("script_changed",this,"_node_script_changed");
|
||||
|
||||
if (p_node->is_type("GeometryInstance") || p_node->is_type("CanvasItem")) {
|
||||
if (p_node->is_type("Spatial") || p_node->is_type("CanvasItem")) {
|
||||
if (p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
|
||||
p_node->disconnect("visibility_changed",this,"_node_visibility_changed");
|
||||
}
|
||||
|
|
|
@ -292,6 +292,9 @@ class DaeExporter:
|
|||
self.writel(S_FX,7,'<texture texture="'+normal_tex+'" texcoord="CHANNEL1"/>')
|
||||
self.writel(S_FX,6,'</bump>')
|
||||
|
||||
self.writel(S_FX,5,'</technique>')
|
||||
self.writel(S_FX,5,'<technique profile="GOOGLEEARTH">')
|
||||
self.writel(S_FX,6,'<double_sided>'+["0","1"][double_sided_hint]+"</double_sided>")
|
||||
self.writel(S_FX,5,'</technique>')
|
||||
self.writel(S_FX,4,'</extra>')
|
||||
|
||||
|
@ -359,7 +362,7 @@ class DaeExporter:
|
|||
mat= None
|
||||
|
||||
if (mat!=None):
|
||||
materials[f.material_index]=self.export_material( mat )
|
||||
materials[f.material_index]=self.export_material( mat,mesh.show_double_sided )
|
||||
else:
|
||||
materials[f.material_index]=None #weird, has no material?
|
||||
|
||||
|
@ -730,7 +733,7 @@ class DaeExporter:
|
|||
self.writel(S_LAMPS,2,'<optics>')
|
||||
self.writel(S_LAMPS,3,'<technique_common>')
|
||||
|
||||
if (light.type=="POINT" or light.type=="HEMI"):
|
||||
if (light.type=="POINT"):
|
||||
self.writel(S_LAMPS,4,'<point>')
|
||||
self.writel(S_LAMPS,5,'<color>'+strarr(light.color)+'</color>')
|
||||
att_by_distance = 2.0 / light.distance # convert to linear attenuation
|
||||
|
|
Loading…
Reference in a new issue