diff options
36 files changed, 1557 insertions, 272 deletions
diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic.c b/extern/curve_fit_nd/intern/curve_fit_cubic.c index 9b4f1869c02..0a32f1e796a 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic.c @@ -255,7 +255,7 @@ static void cubic_list_clear(CubicList *clist) /** \name Cubic Evaluation * \{ */ -static void cubic_evaluate( +static void cubic_calc_point( const Cubic *cubic, const double t, const uint dims, double r_v[]) { @@ -271,18 +271,6 @@ static void cubic_evaluate( } } -static void cubic_calc_point( - const Cubic *cubic, const double t, const uint dims, - double r_v[]) -{ - CUBIC_VARS_CONST(cubic, dims, p0, p1, p2, p3); - const double s = 1.0 - t; - for (uint j = 0; j < dims; j++) { - r_v[j] = p0[j] * s * s * s + - 3.0 * t * s * (s * p1[j] + t * p2[j]) + t * t * t * p3[j]; - } -} - static void cubic_calc_speed( const Cubic *cubic, const double t, const uint dims, double r_v[]) @@ -332,7 +320,7 @@ static double cubic_calc_error( #endif for (uint i = 1; i < points_offset_len - 1; i++, pt_real += dims) { - cubic_evaluate(cubic, u[i], dims, pt_eval); + cubic_calc_point(cubic, u[i], dims, pt_eval); const double err_sq = len_squared_vnvn(pt_real, pt_eval, dims); if (err_sq >= error_max_sq) { @@ -368,7 +356,7 @@ static double cubic_calc_error_simple( #endif for (uint i = 1; i < points_offset_len - 1; i++, pt_real += dims) { - cubic_evaluate(cubic, u[i], dims, pt_eval); + cubic_calc_point(cubic, u[i], dims, pt_eval); const double err_sq = len_squared_vnvn(pt_real, pt_eval, dims); if (err_sq >= error_threshold_sq) { @@ -501,7 +489,7 @@ static double points_calc_circle_tangent_factor( return (1.0 / 3.0) * 0.75; } else if (tan_dot < -1.0 + eps) { - /* parallele tangents (half-circle) */ + /* parallel tangents (half-circle) */ return (1.0 / 2.0); } else { @@ -623,8 +611,8 @@ static void cubic_from_points_offset_fallback( } } - double alpha_l = (dists[0] / 0.75) / dot_vnvn(tan_l, a[0], dims); - double alpha_r = (dists[1] / 0.75) / -dot_vnvn(tan_r, a[1], dims); + double alpha_l = (dists[0] / 0.75) / fabs(dot_vnvn(tan_l, a[0], dims)); + double alpha_r = (dists[1] / 0.75) / fabs(dot_vnvn(tan_r, a[1], dims)); if (!(alpha_l > 0.0)) { alpha_l = dir_dist / 3.0; @@ -677,13 +665,11 @@ static void cubic_from_points( double alpha_l, alpha_r; #ifdef USE_VLA double a[2][dims]; - double tmp[dims]; #else double *a[2] = { alloca(sizeof(double) * dims), alloca(sizeof(double) * dims), }; - double *tmp = alloca(sizeof(double) * dims); #endif { @@ -694,22 +680,22 @@ static void cubic_from_points( mul_vnvn_fl(a[0], tan_l, B1(u_prime[i]), dims); mul_vnvn_fl(a[1], tan_r, B2(u_prime[i]), dims); - c[0][0] += dot_vnvn(a[0], a[0], dims); - c[0][1] += dot_vnvn(a[0], a[1], dims); - c[1][1] += dot_vnvn(a[1], a[1], dims); + const double b0_plus_b1 = B0plusB1(u_prime[i]); + const double b2_plus_b3 = B2plusB3(u_prime[i]); - c[1][0] = c[0][1]; + /* inline dot product */ + for (uint j = 0; j < dims; j++) { + const double tmp = (pt[j] - (p0[j] * b0_plus_b1)) + (p3[j] * b2_plus_b3); - { - const double b0_plus_b1 = B0plusB1(u_prime[i]); - const double b2_plus_b3 = B2plusB3(u_prime[i]); - for (uint j = 0; j < dims; j++) { - tmp[j] = (pt[j] - (p0[j] * b0_plus_b1)) + (p3[j] * b2_plus_b3); - } + x[0] += a[0][j] * tmp; + x[1] += a[1][j] * tmp; - x[0] += dot_vnvn(a[0], tmp, dims); - x[1] += dot_vnvn(a[1], tmp, dims); + c[0][0] += a[0][j] * a[0][j]; + c[0][1] += a[0][j] * a[1][j]; + c[1][1] += a[1][j] * a[1][j]; } + + c[1][0] = c[0][1]; } double det_C0_C1 = c[0][0] * c[1][1] - c[0][1] * c[1][0]; diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c index d22d042bff5..bf1ab99995f 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c @@ -463,7 +463,7 @@ static uint curve_incremental_simplify( rstate_pool_create(&epool, 0); #endif - Heap *heap = HEAP_new(knots_len); + Heap *heap = HEAP_new(knots_len_remaining); struct KnotRemove_Params params = { .pd = pd, @@ -698,7 +698,7 @@ static uint curve_incremental_simplify_refit( refit_pool_create(&epool, 0); #endif - Heap *heap = HEAP_new(knots_len); + Heap *heap = HEAP_new(knots_len_remaining); struct KnotRefit_Params params = { .pd = pd, @@ -890,7 +890,7 @@ static void knot_corner_error_recalculate( static uint curve_incremental_simplify_corners( const struct PointData *pd, struct Knot *knots, const uint knots_len, uint knots_len_remaining, - const double error_sq_max, const double error_sq_2x_max, + const double error_sq_max, const double error_sq_collapse_max, const double corner_angle, const uint dims, uint *r_corner_index_len) @@ -954,12 +954,12 @@ static uint curve_incremental_simplify_corners( project_vn_vnvn_normalized(k_proj_ref, co_prev, k_prev->tan[1], dims); project_vn_vnvn_normalized(k_proj_split, co_split, k_prev->tan[1], dims); - if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) { + if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_collapse_max) { project_vn_vnvn_normalized(k_proj_ref, co_next, k_next->tan[0], dims); project_vn_vnvn_normalized(k_proj_split, co_split, k_next->tan[0], dims); - if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) { + if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_collapse_max) { struct Knot *k_split = &knots[split_index]; @@ -1260,9 +1260,12 @@ int curve_fit_cubic_to_points_refit_db( #ifdef USE_CORNER_DETECT if (use_corner) { + +#ifdef DEBUG for (uint i = 0; i < knots_len; i++) { assert(knots[i].heap_node == NULL); } +#endif knots_len_remaining = curve_incremental_simplify_corners( &pd, knots, knots_len, knots_len_remaining, diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index c4f8d9e16e0..ef257358b22 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -51,7 +51,7 @@ public: Device *device; foreach(DeviceInfo& subinfo, info.multi_devices) { - device = Device::create(subinfo, stats, background); + device = Device::create(subinfo, sub_stats_, background); devices.push_back(SubDevice(device)); } @@ -107,6 +107,7 @@ public: } mem.device_pointer = unique_ptr++; + stats.mem_alloc(mem.device_size); } void mem_copy_to(device_memory& mem) @@ -161,6 +162,7 @@ public: } mem.device_pointer = 0; + stats.mem_free(mem.device_size); } void const_copy_to(const char *name, void *host, size_t size) @@ -186,6 +188,7 @@ public: } mem.device_pointer = unique_ptr++; + stats.mem_alloc(mem.device_size); } void tex_free(device_memory& mem) @@ -199,6 +202,7 @@ public: } mem.device_pointer = 0; + stats.mem_free(mem.device_size); } void pixels_alloc(device_memory& mem) @@ -336,6 +340,9 @@ public: foreach(SubDevice& sub, devices) sub.device->task_cancel(); } + +protected: + Stats sub_stats_; }; Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index df848c3d179..0a6dd4dcbdf 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -373,6 +373,11 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *s ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; + + if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) { + return make_float3(0.0f, 0.0f, 0.0f); + } + bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y); float3 X, Y, Z; Z = bsdf->N; @@ -394,9 +399,18 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state) { const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; - bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y); + float3 X, Y, Z; Z = bsdf->N; + + if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) { + *omega_in = 2*dot(Z, I)*Z - I; + *pdf = 1e6f; + *eval = make_float3(1e6f, 1e6f, 1e6f); + return LABEL_REFLECT|LABEL_SINGULAR; + } + + bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y); if(is_aniso) make_orthonormals_tangent(Z, bsdf->T, &X, &Y); else @@ -438,6 +452,11 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf) ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; + + if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) { + return make_float3(0.0f, 0.0f, 0.0f); + } + float3 X, Y, Z; Z = bsdf->N; make_orthonormals(Z, &X, &Y); @@ -451,6 +470,11 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClos ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; + + if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) { + return make_float3(0.0f, 0.0f, 0.0f); + } + float3 X, Y, Z; Z = bsdf->N; make_orthonormals(Z, &X, &Y); @@ -465,8 +489,42 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state) { const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; + float3 X, Y, Z; Z = bsdf->N; + + if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) { + float3 R, T; +#ifdef __RAY_DIFFERENTIALS__ + float3 dRdx, dRdy, dTdx, dTdy; +#endif + bool inside; + float fresnel = fresnel_dielectric(bsdf->ior, Z, I, &R, &T, +#ifdef __RAY_DIFFERENTIALS__ + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, +#endif + &inside); + + *pdf = 1e6f; + *eval = make_float3(1e6f, 1e6f, 1e6f); + if(randu < fresnel) { + *omega_in = R; +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = dRdx; + *domega_in_dy = dRdy; +#endif + return LABEL_REFLECT|LABEL_SINGULAR; + } + else { + *omega_in = T; +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = dTdx; + *domega_in_dy = dTdy; +#endif + return LABEL_TRANSMIT|LABEL_SINGULAR; + } + } + make_orthonormals(Z, &X, &Y); float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z)); diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 27acf8166b3..45f0f1cbfaa 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -46,15 +46,17 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); - if(kernel_data.integrator.pdf_triangles != 0.0f) - num_samples_inv *= 0.5f; - for(int j = 0; j < num_samples; j++) { float light_u, light_v; path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; if(lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls)) { + /* The sampling probability returned by lamp_light_sample assumes that all lights were sampled. + * However, this code only samples lamps, so if the scene also had mesh lights, the real probability is twice as high. */ + if(kernel_data.integrator.pdf_triangles != 0.0f) + ls.pdf *= 2.0f; + if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) { /* trace shadow ray */ float3 shadow; @@ -73,9 +75,6 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal int num_samples = ceil_to_int(num_samples_adjust*kernel_data.integrator.mesh_light_samples); float num_samples_inv = num_samples_adjust/num_samples; - if(kernel_data.integrator.num_all_lights) - num_samples_inv *= 0.5f; - for(int j = 0; j < num_samples; j++) { float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT); float light_u, light_v; @@ -87,6 +86,10 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal LightSample ls; if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) { + /* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */ + if(kernel_data.integrator.num_all_lights) + ls.pdf *= 2.0f; + if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) { /* trace shadow ray */ float3 shadow; diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index 0bb8f1c517f..5ee1912c913 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -136,9 +136,6 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); - if(kernel_data.integrator.pdf_triangles != 0.0f) - num_samples_inv *= 0.5f; - for(int j = 0; j < num_samples; j++) { /* sample random position on given light */ float light_u, light_v; @@ -161,6 +158,9 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG /* todo: split up light_sample so we don't have to call it again with new position */ if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) { + if(kernel_data.integrator.pdf_triangles != 0.0f) + ls.pdf *= 2.0f; + if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) { /* trace shadow ray */ float3 shadow; @@ -179,9 +179,6 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG int num_samples = kernel_data.integrator.mesh_light_samples; float num_samples_inv = 1.0f/num_samples; - if(kernel_data.integrator.num_all_lights) - num_samples_inv *= 0.5f; - for(int j = 0; j < num_samples; j++) { /* sample random position on random triangle */ float light_t = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_LIGHT); @@ -209,6 +206,9 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG /* todo: split up light_sample so we don't have to call it again with new position */ if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(kernel_data.integrator.num_all_lights) + ls.pdf *= 2.0f; + if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) { /* trace shadow ray */ float3 shadow; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 3eff35bae9e..039bb49d82f 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -471,16 +471,12 @@ void Mesh::add_face_normals() /* compute face normals */ size_t triangles_size = num_triangles(); - bool flip = transform_negative_scaled; if(triangles_size) { float3 *verts_ptr = verts.data(); for(size_t i = 0; i < triangles_size; i++) { fN[i] = compute_face_normal(get_triangle(i), verts_ptr); - - if(flip) - fN[i] = -fN[i]; } } diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py index 8e6fc45af73..9d9dd529322 100644 --- a/release/scripts/startup/bl_ui/properties_physics_smoke.py +++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py @@ -330,5 +330,54 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel): domain = context.smoke.domain_settings effector_weights_ui(self, context, domain.effector_weights, 'SMOKE') + +class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel): + bl_label = "Smoke Display Settings" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.smoke + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) + + def draw(self, context): + domain = context.smoke.domain_settings + layout = self.layout + + layout.prop(domain, "display_thickness") + + layout.separator() + layout.label(text="Slicing:") + layout.prop(domain, "slice_method") + + slice_method = domain.slice_method + axis_slice_method = domain.axis_slice_method + + do_axis_slicing = (slice_method == 'AXIS_ALIGNED') + do_full_slicing = (axis_slice_method == 'FULL') + + row = layout.row(); + row.enabled = do_axis_slicing + row.prop(domain, "axis_slice_method") + + col = layout.column(); + col.enabled = not do_full_slicing and do_axis_slicing + col.prop(domain, "slice_axis") + col.prop(domain, "slice_depth") + + row = layout.row(); + row.enabled = do_full_slicing or not do_axis_slicing + row.prop(domain, "slice_per_voxel") + + layout.separator() + layout.label(text="Debug:") + layout.prop(domain, "draw_velocity") + col = layout.column(); + col.enabled = domain.draw_velocity + col.prop(domain, "vector_draw_type") + col.prop(domain, "vector_scale") + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index db41d5e837c..5e66d6c2dc7 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -86,10 +86,10 @@ ExportSettings::ExportSettings() , export_child_hairs(true) , export_ogawa(true) , pack_uv(false) - , do_convert_axis(false) , triangulate(false) , quad_method(0) , ngon_method(0) + , do_convert_axis(false) {} static bool object_is_smoke_sim(Object *ob) diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 5977a072ccd..22a4c0ff7f8 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -146,19 +146,6 @@ static void get_topology(DerivedMesh *dm, } } -static void get_material_indices(DerivedMesh *dm, std::vector<int32_t> &indices) -{ - indices.clear(); - indices.reserve(dm->getNumTessFaces(dm)); - - MPoly *mpolys = dm->getPolyArray(dm); - - for (int i = 1, e = dm->getNumPolys(dm); i < e; ++i) { - MPoly *mpoly = &mpolys[i]; - indices.push_back(mpoly->mat_nr); - } -} - static void get_creases(DerivedMesh *dm, std::vector<int32_t> &indices, std::vector<int32_t> &lengths, @@ -309,7 +296,6 @@ AbcMeshWriter::AbcMeshWriter(Scene *scene, { m_is_animated = isAnimated(); m_subsurf_mod = NULL; - m_has_per_face_materials = false; m_is_subd = false; /* If the object is static, use the default static time sampling. */ @@ -406,8 +392,8 @@ void AbcMeshWriter::writeMesh(DerivedMesh *dm) get_vertices(dm, points); get_topology(dm, poly_verts, loop_counts, smooth_normal); - if (m_first_frame) { - writeCommonData(dm, m_mesh_schema); + if (m_first_frame && m_settings.export_face_sets) { + writeFaceSets(dm, m_mesh_schema); } m_mesh_sample = OPolyMeshSchema::Sample(V3fArraySample(points), @@ -475,9 +461,8 @@ void AbcMeshWriter::writeSubD(DerivedMesh *dm) get_topology(dm, poly_verts, loop_counts, smooth_normal); get_creases(dm, crease_indices, crease_lengths, crease_sharpness); - if (m_first_frame) { - /* create materials' face_sets */ - writeCommonData(dm, m_subdiv_schema); + if (m_first_frame && m_settings.export_face_sets) { + writeFaceSets(dm, m_subdiv_schema); } m_subdiv_sample = OSubDSchema::Sample(V3fArraySample(points), @@ -514,7 +499,7 @@ void AbcMeshWriter::writeSubD(DerivedMesh *dm) } template <typename Schema> -void AbcMeshWriter::writeCommonData(DerivedMesh *dm, Schema &schema) +void AbcMeshWriter::writeFaceSets(DerivedMesh *dm, Schema &schema) { std::map< std::string, std::vector<int32_t> > geo_groups; getGeoGroups(dm, geo_groups); @@ -588,18 +573,6 @@ void AbcMeshWriter::writeArbGeoParams(DerivedMesh *dm) write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL); } } - - if (m_first_frame && m_has_per_face_materials) { - std::vector<int32_t> material_indices; - - if (m_settings.export_face_sets) { - get_material_indices(dm, material_indices); - - OFaceSetSchema::Sample samp; - samp.setFaces(Int32ArraySample(material_indices)); - m_face_set.getSchema().set(samp); - } - } } void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels) @@ -873,7 +846,10 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) const P3fArraySamplePtr &positions = mesh_data.positions; const N3fArraySamplePtr &normals = mesh_data.vertex_normals; - if (config.weight != 0.0f && mesh_data.ceil_positions) { + if ( config.weight != 0.0f + && mesh_data.ceil_positions != NULL + && mesh_data.ceil_positions->size() == positions->size()) + { read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight); return; } diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 9dc222e5206..41abe78f75f 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -39,8 +39,6 @@ class AbcMeshWriter : public AbcObjectWriter { Alembic::AbcGeom::OSubDSchema m_subdiv_schema; Alembic::AbcGeom::OSubDSchema::Sample m_subdiv_sample; - bool m_has_per_face_materials; - Alembic::AbcGeom::OFaceSet m_face_set; Alembic::Abc::OArrayProperty m_mat_indices; bool m_is_animated; @@ -87,7 +85,7 @@ private: void getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels); template <typename Schema> - void writeCommonData(DerivedMesh *dm, Schema &schema); + void writeFaceSets(DerivedMesh *dm, Schema &schema); }; /* ************************************************************************** */ diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index e8b37a36b56..2993540bb4f 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -31,8 +31,9 @@ * \ingroup bke */ -struct bSensor; +struct Main; struct Object; +struct bSensor; struct bController; struct bActuator; @@ -68,6 +69,9 @@ void clear_sca_new_poins(void); void set_sca_new_poins_ob(struct Object *ob); void set_sca_new_poins(void); +void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new); +void BKE_sca_logic_copy(struct Object *ob_new, struct Object *ob); + void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up); void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up); diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 69b52c92c3f..b7f7f2c19cc 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -98,6 +98,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" +#include "BKE_sca.h" #include "BKE_speaker.h" #include "BKE_sound.h" #include "BKE_screen.h" @@ -447,6 +448,10 @@ ATTR_NONNULL(1) static void libblock_remap_data( } } + if (old_id && GS(old_id->name) == ID_OB) { + BKE_sca_logic_links_remap(bmain, (Object *)old_id, (Object *)new_id); + } + /* XXX We may not want to always 'transfer' fakeuser from old to new id... Think for now it's desired behavior * though, we can always add an option (flag) to control this later if needed. */ if (old_id && (old_id->flag & LIB_FAKEUSER)) { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 7714c71681a..1cc8d8c381c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2368,8 +2368,12 @@ Mesh *BKE_mesh_new_from_object( if (tmpcu->mat) { for (i = tmpcu->totcol; i-- > 0; ) { /* are we an object material or data based? */ - - tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i]; + if (ob->matbits[i] && i >= ob->totcol) { + tmpmesh->mat[i] = NULL; + } + else { + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i]; + } if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); @@ -2388,7 +2392,12 @@ Mesh *BKE_mesh_new_from_object( if (tmpmb->mat) { for (i = tmpmb->totcol; i-- > 0; ) { /* are we an object material or data based? */ - tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpmb->mat[i]; + if (ob->matbits[i] && i >= ob->totcol) { + tmpmesh->mat[i] = NULL; + } + else { + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpmb->mat[i]; + } if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); @@ -2408,7 +2417,12 @@ Mesh *BKE_mesh_new_from_object( if (origmesh->mat) { for (i = origmesh->totcol; i-- > 0; ) { /* are we an object material or data based? */ - tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i]; + if (ob->matbits[i] && i >= ob->totcol) { + tmpmesh->mat[i] = NULL; + } + else { + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i]; + } if (do_mat_id_us && tmpmesh->mat[i]) { id_us_plus(&tmpmesh->mat[i]->id); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0b15d28ec17..16e15e78185 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -957,11 +957,9 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) BLI_listbase_clear(&obn->prop); BKE_bproperty_copy_list(&obn->prop, &ob->prop); - - copy_sensors(&obn->sensors, &ob->sensors); - copy_controllers(&obn->controllers, &ob->controllers); - copy_actuators(&obn->actuators, &ob->actuators); - + + BKE_sca_logic_copy(obn, ob); + if (ob->pose) { copy_object_pose(obn, ob); /* backwards compat... non-armatures can get poses in older files? */ diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index a468420f87d..61aa8c7589f 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -44,7 +44,9 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" + #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" @@ -653,6 +655,161 @@ void set_sca_new_poins(void) } } +/** + * Try to remap logic links to new object... Very, *very* weak. + */ +/* XXX Logick bricks... I don't have words to say what I think about this behavior. + * They have silent hidden ugly inter-objects dependencies (a sensor can link into any other + * object's controllers, and same between controllers and actuators, without *any* explicit reference + * to data-block involved). + * This is bad, bad, bad!!! + * ...and forces us to add yet another very ugly hack to get remapping with logic bricks working. */ +void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new) +{ + if (ob_new == NULL || (ob_old->controllers.first == NULL && ob_old->actuators.first == NULL)) { + /* Nothing to do here... */ + return; + } + + GHash *controllers_map = ob_old->controllers.first ? + BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->controllers)) : NULL; + GHash *actuators_map = ob_old->actuators.first ? + BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->actuators)) : NULL; + + /* We try to remap old controllers/actuators to new ones - in a very basic way. */ + for (bController *cont_old = ob_old->controllers.first, *cont_new = ob_new->controllers.first; + cont_old; + cont_old = cont_old->next) + { + bController *cont_new2 = cont_new; + + if (cont_old->mynew != NULL) { + cont_new2 = cont_old->mynew; + if (!(cont_new2 == cont_new || BLI_findindex(&ob_new->controllers, cont_new2) >= 0)) { + cont_new2 = NULL; + } + } + else if (cont_new && cont_old->type != cont_new->type) { + cont_new2 = NULL; + } + + BLI_ghash_insert(controllers_map, cont_old, cont_new2); + + if (cont_new) { + cont_new = cont_new->next; + } + } + + for (bActuator *act_old = ob_old->actuators.first, *act_new = ob_new->actuators.first; + act_old; + act_old = act_old->next) + { + bActuator *act_new2 = act_new; + + if (act_old->mynew != NULL) { + act_new2 = act_old->mynew; + if (!(act_new2 == act_new || BLI_findindex(&ob_new->actuators, act_new2) >= 0)) { + act_new2 = NULL; + } + } + else if (act_new && act_old->type != act_new->type) { + act_new2 = NULL; + } + + BLI_ghash_insert(actuators_map, act_old, act_new2); + + if (act_new) { + act_new = act_new->next; + } + } + + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + if (controllers_map != NULL) { + for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) { + for (int a = 0; a < sens->totlinks; a++) { + if (sens->links[a]) { + bController *old_link = sens->links[a]; + bController **new_link_p = (bController **)BLI_ghash_lookup_p(controllers_map, old_link); + + if (new_link_p == NULL) { + /* old_link is *not* in map's keys (i.e. not to any ob_old->controllers), + * which means we ignore it totally here. */ + } + else if (*new_link_p == NULL) { + unlink_logicbricks((void **)&old_link, (void ***)&(sens->links), &sens->totlinks); + a--; + } + else { + sens->links[a] = *new_link_p; + } + } + } + } + } + + if (actuators_map != NULL) { + for (bController *cont = ob->controllers.first; cont; cont = cont->next) { + for (int a = 0; a < cont->totlinks; a++) { + if (cont->links[a]) { + bActuator *old_link = cont->links[a]; + bActuator **new_link_p = (bActuator **)BLI_ghash_lookup_p(actuators_map, old_link); + + if (new_link_p == NULL) { + /* old_link is *not* in map's keys (i.e. not to any ob_old->actuators), + * which means we ignore it totally here. */ + } + else if (*new_link_p == NULL) { + unlink_logicbricks((void **)&old_link, (void ***)&(cont->links), &cont->totlinks); + a--; + } + else { + cont->links[a] = *new_link_p; + } + } + } + } + } + } + + if (controllers_map) { + BLI_ghash_free(controllers_map, NULL, NULL); + } + if (actuators_map) { + BLI_ghash_free(actuators_map, NULL, NULL); + } +} + +/** + * Handle the copying of logic data into a new object, including internal logic links update. + * External links (links between logic bricks of different objects) must be handled separately. + */ +void BKE_sca_logic_copy(Object *ob_new, Object *ob) +{ + copy_sensors(&ob_new->sensors, &ob->sensors); + copy_controllers(&ob_new->controllers, &ob->controllers); + copy_actuators(&ob_new->actuators, &ob->actuators); + + for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) { + if (sens->flag & SENS_NEW) { + for (int a = 0; a < sens->totlinks; a++) { + if (sens->links[a] && sens->links[a]->mynew) { + sens->links[a] = sens->links[a]->mynew; + } + } + } + } + + for (bController *cont = ob->controllers.first; cont; cont = cont->next) { + if (cont->flag & CONT_NEW) { + for (int a = 0; a < cont->totlinks; a++) { + if (cont->links[a] && cont->links[a]->mynew) { + cont->links[a] = cont->links[a]->mynew; + } + } + } + } +} + /* ******************** INTERFACE ******************* */ void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5454e1f7568..aca0c833aea 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -799,6 +799,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name) Scene *sce; sce = BKE_libblock_alloc(bmain, ID_SCE, name); + id_us_min(&sce->id); + id_us_ensure_real(&sce->id); BKE_scene_init(sce); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 4a8629e40a3..05356123727 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -523,6 +523,14 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->openvdb_comp = VDB_COMPRESSION_ZIP; #endif smd->domain->data_depth = 0; + + smd->domain->display_thickness = 1.0f; + smd->domain->slice_method = MOD_SMOKE_SLICE_VIEW_ALIGNED; + smd->domain->axis_slice_method = AXIS_SLICE_FULL; + smd->domain->slice_per_voxel = 5.0f; + smd->domain->slice_depth = 0.5f; + smd->domain->slice_axis = 0; + smd->domain->vector_scale = 1.0f; } else if (smd->type & MOD_SMOKE_TYPE_FLOW) { @@ -614,6 +622,15 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData tsmd->domain->openvdb_comp = smd->domain->openvdb_comp; tsmd->domain->data_depth = smd->domain->data_depth; tsmd->domain->cache_file_format = smd->domain->cache_file_format; + + tsmd->domain->slice_method = smd->domain->slice_method; + tsmd->domain->axis_slice_method = smd->domain->axis_slice_method; + tsmd->domain->slice_per_voxel = smd->domain->slice_per_voxel; + tsmd->domain->slice_depth = smd->domain->slice_depth; + tsmd->domain->slice_axis = smd->domain->slice_axis; + tsmd->domain->draw_velocity = smd->domain->draw_velocity; + tsmd->domain->vector_draw_type = smd->domain->vector_draw_type; + tsmd->domain->vector_scale = smd->domain->vector_scale; } else if (tsmd->flow) { tsmd->flow->noise_texture = smd->flow->noise_texture; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 39fe914e53c..eb398923589 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -51,6 +51,7 @@ #include "DNA_linestyle_types.h" #include "DNA_actuator_types.h" #include "DNA_view3d_types.h" +#include "DNA_smoke_types.h" #include "DNA_genfile.h" @@ -1317,5 +1318,23 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) scene->r.ffcodecdata.constant_rate_factor = FFM_CRF_NONE; } } + + if (!DNA_struct_elem_find(fd->filesdna, "SmokeModifierData", "float", "slice_per_voxel")) { + Object *ob; + ModifierData *md; + + for (ob = main->object.first; ob; ob = ob->id.next) { + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if (smd->domain) { + smd->domain->slice_per_voxel = 5.0f; + smd->domain->slice_depth = 0.5f; + smd->domain->display_thickness = 1.0f; + } + } + } + } + } } } diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 79c2f80d6aa..0d0fdda2c4c 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1635,7 +1635,8 @@ static BMOpDefine bmo_create_icosphere_def = { static BMOpDefine bmo_create_monkey_def = { "create_monkey", /* slots_in */ - {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index d2b9fa9efa3..7b32921f8cf 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -78,6 +78,31 @@ static const short icoface[20][3] = { {10, 9, 11} }; +static const float icouvs[60][2] = +{ + {0.818181f, 0.000000f}, {0.727272f, 0.157461f}, {0.909090f, 0.157461f}, + {0.727272f, 0.157461f}, {0.636363f, 0.000000f}, {0.545454f, 0.157461f}, + {0.090909f, 0.000000f}, {0.000000f, 0.157461f}, {0.181818f, 0.157461f}, + {0.272727f, 0.000000f}, {0.181818f, 0.157461f}, {0.363636f, 0.157461f}, + {0.454545f, 0.000000f}, {0.363636f, 0.157461f}, {0.545454f, 0.157461f}, + {0.727272f, 0.157461f}, {0.545454f, 0.157461f}, {0.636363f, 0.314921f}, + {0.909090f, 0.157461f}, {0.727272f, 0.157461f}, {0.818181f, 0.314921f}, + {0.181818f, 0.157461f}, {0.000000f, 0.157461f}, {0.090909f, 0.314921f}, + {0.363636f, 0.157461f}, {0.181818f, 0.157461f}, {0.272727f, 0.314921f}, + {0.545454f, 0.157461f}, {0.363636f, 0.157461f}, {0.454545f, 0.314921f}, + {0.727272f, 0.157461f}, {0.636363f, 0.314921f}, {0.818181f, 0.314921f}, + {0.909090f, 0.157461f}, {0.818181f, 0.314921f}, {1.000000f, 0.314921f}, + {0.181818f, 0.157461f}, {0.090909f, 0.314921f}, {0.272727f, 0.314921f}, + {0.363636f, 0.157461f}, {0.272727f, 0.314921f}, {0.454545f, 0.314921f}, + {0.545454f, 0.157461f}, {0.454545f, 0.314921f}, {0.636363f, 0.314921f}, + {0.818181f, 0.314921f}, {0.636363f, 0.314921f}, {0.727272f, 0.472382f}, + {1.000000f, 0.314921f}, {0.818181f, 0.314921f}, {0.909090f, 0.472382f}, + {0.272727f, 0.314921f}, {0.090909f, 0.314921f}, {0.181818f, 0.472382f}, + {0.454545f, 0.314921f}, {0.272727f, 0.314921f}, {0.363636f, 0.472382f}, + {0.636363f, 0.314921f}, {0.454545f, 0.314921f}, {0.545454f, 0.472382f} +}; + + static const int monkeyo = 4; static const int monkeynv = 271; static const int monkeynf = 250; @@ -218,6 +243,510 @@ static signed char monkeyf[250][4] = { {-68, -67, 24, -33}, }; +static const float monkeyuvs[] = +{ + 0.890955f, 0.590063f, 0.870622f, 0.589649f, 0.860081f, 0.560115f, 0.904571f, 0.559404f, + 0.856226f, 0.850547f, 0.868067f, 0.821510f, 0.888398f, 0.821999f, 0.900640f, 0.853232f, + 0.904571f, 0.559404f, 0.860081f, 0.560115f, 0.853018f, 0.521562f, 0.920166f, 0.524546f, + 0.847458f, 0.888748f, 0.856226f, 0.850547f, 0.900640f, 0.853232f, 0.914672f, 0.888748f, + 0.860081f, 0.560115f, 0.828900f, 0.590771f, 0.798481f, 0.569535f, 0.853018f, 0.521562f, + 0.795104f, 0.838402f, 0.826436f, 0.818537f, 0.856226f, 0.850547f, 0.847458f, 0.888748f, + 0.870622f, 0.589649f, 0.854402f, 0.604754f, 0.828900f, 0.590771f, 0.860081f, 0.560115f, + 0.826436f, 0.818537f, 0.852534f, 0.805700f, 0.868067f, 0.821510f, 0.856226f, 0.850547f, + 0.854402f, 0.604754f, 0.854107f, 0.625459f, 0.828171f, 0.633354f, 0.828900f, 0.590771f, + 0.827598f, 0.775964f, 0.853157f, 0.785002f, 0.852534f, 0.805700f, 0.826436f, 0.818537f, + 0.828900f, 0.590771f, 0.828171f, 0.633354f, 0.791018f, 0.645443f, 0.798481f, 0.569535f, + 0.791018f, 0.762238f, 0.827598f, 0.775964f, 0.826436f, 0.818537f, 0.795104f, 0.838402f, + 0.828171f, 0.633354f, 0.855181f, 0.668527f, 0.842358f, 0.702491f, 0.791018f, 0.645443f, + 0.844839f, 0.707525f, 0.856142f, 0.742025f, 0.827598f, 0.775964f, 0.791018f, 0.762238f, + 0.854107f, 0.625459f, 0.867508f, 0.642291f, 0.855181f, 0.668527f, 0.828171f, 0.633354f, + 0.856142f, 0.742025f, 0.867293f, 0.768782f, 0.853157f, 0.785002f, 0.827598f, 0.775964f, + 0.867508f, 0.642291f, 0.890474f, 0.641909f, 0.900375f, 0.666964f, 0.855181f, 0.668527f, + 0.901223f, 0.745592f, 0.890219f, 0.770183f, 0.867293f, 0.768782f, 0.856142f, 0.742025f, + 0.855181f, 0.668527f, 0.900375f, 0.666964f, 0.918898f, 0.699697f, 0.842358f, 0.702491f, + 0.921180f, 0.713713f, 0.901223f, 0.745592f, 0.856142f, 0.742025f, 0.844839f, 0.707525f, + 0.900375f, 0.666964f, 0.931889f, 0.636832f, 0.968392f, 0.645333f, 0.918898f, 0.699697f, + 0.968213f, 0.770220f, 0.931368f, 0.777093f, 0.901223f, 0.745592f, 0.921180f, 0.713713f, + 0.890474f, 0.641909f, 0.905882f, 0.627902f, 0.931889f, 0.636832f, 0.900375f, 0.666964f, + 0.931368f, 0.777093f, 0.904990f, 0.784860f, 0.890219f, 0.770183f, 0.901223f, 0.745592f, + 0.905882f, 0.627902f, 0.906232f, 0.605742f, 0.933717f, 0.593037f, 0.931889f, 0.636832f, + 0.931250f, 0.820926f, 0.904357f, 0.807013f, 0.904990f, 0.784860f, 0.931368f, 0.777093f, + 0.931889f, 0.636832f, 0.933717f, 0.593037f, 0.968392f, 0.573812f, 0.968392f, 0.645333f, + 0.965038f, 0.841671f, 0.931250f, 0.820926f, 0.931368f, 0.777093f, 0.968213f, 0.770220f, + 0.933717f, 0.593037f, 0.904571f, 0.559404f, 0.920166f, 0.524546f, 0.968392f, 0.573812f, + 0.914672f, 0.888748f, 0.900640f, 0.853232f, 0.931250f, 0.820926f, 0.965038f, 0.841671f, + 0.906232f, 0.605742f, 0.890955f, 0.590063f, 0.904571f, 0.559404f, 0.933717f, 0.593037f, + 0.900640f, 0.853232f, 0.888398f, 0.821999f, 0.904357f, 0.807013f, 0.931250f, 0.820926f, + 0.890955f, 0.590063f, 0.906232f, 0.605742f, 0.902359f, 0.607909f, 0.889591f, 0.593275f, + 0.900583f, 0.804677f, 0.904357f, 0.807013f, 0.888398f, 0.821999f, 0.887178f, 0.818729f, + 0.906232f, 0.605742f, 0.905882f, 0.627902f, 0.899781f, 0.626257f, 0.902359f, 0.607909f, + 0.898822f, 0.786233f, 0.904990f, 0.784860f, 0.904357f, 0.807013f, 0.900583f, 0.804677f, + 0.905882f, 0.627902f, 0.890474f, 0.641909f, 0.887842f, 0.636527f, 0.899781f, 0.626257f, + 0.887351f, 0.775442f, 0.890219f, 0.770183f, 0.904990f, 0.784860f, 0.898822f, 0.786233f, + 0.890474f, 0.641909f, 0.867508f, 0.642291f, 0.870908f, 0.635245f, 0.887842f, 0.636527f, + 0.870376f, 0.775972f, 0.867293f, 0.768782f, 0.890219f, 0.770183f, 0.887351f, 0.775442f, + 0.867508f, 0.642291f, 0.854107f, 0.625459f, 0.859881f, 0.623942f, 0.870908f, 0.635245f, + 0.858859f, 0.786774f, 0.853157f, 0.785002f, 0.867293f, 0.768782f, 0.870376f, 0.775972f, + 0.854107f, 0.625459f, 0.854402f, 0.604754f, 0.859664f, 0.608186f, 0.859881f, 0.623942f, + 0.857942f, 0.802505f, 0.852534f, 0.805700f, 0.853157f, 0.785002f, 0.858859f, 0.786774f, + 0.854402f, 0.604754f, 0.870622f, 0.589649f, 0.871664f, 0.593961f, 0.859664f, 0.608186f, + 0.869299f, 0.817249f, 0.868067f, 0.821510f, 0.852534f, 0.805700f, 0.857942f, 0.802505f, + 0.870622f, 0.589649f, 0.890955f, 0.590063f, 0.889591f, 0.593275f, 0.871664f, 0.593961f, + 0.887178f, 0.818729f, 0.888398f, 0.821999f, 0.868067f, 0.821510f, 0.869299f, 0.817249f, + 0.879400f, 0.616512f, 0.871664f, 0.593961f, 0.889591f, 0.593275f, + 0.887178f, 0.818729f, 0.869299f, 0.817249f, 0.878029f, 0.795063f, + 0.859664f, 0.608186f, 0.871664f, 0.593961f, 0.879400f, 0.616512f, + 0.878029f, 0.795063f, 0.869299f, 0.817249f, 0.857942f, 0.802505f, + 0.879400f, 0.616512f, 0.859881f, 0.623942f, 0.859664f, 0.608186f, + 0.857942f, 0.802505f, 0.858859f, 0.786774f, 0.878029f, 0.795063f, + 0.879400f, 0.616512f, 0.870908f, 0.635245f, 0.859881f, 0.623942f, + 0.858859f, 0.786774f, 0.870376f, 0.775972f, 0.878029f, 0.795063f, + 0.879400f, 0.616512f, 0.887842f, 0.636527f, 0.870908f, 0.635245f, + 0.870376f, 0.775972f, 0.887351f, 0.775442f, 0.878029f, 0.795063f, + 0.879400f, 0.616512f, 0.899781f, 0.626257f, 0.887842f, 0.636527f, + 0.887351f, 0.775442f, 0.898822f, 0.786233f, 0.878029f, 0.795063f, + 0.879400f, 0.616512f, 0.902359f, 0.607909f, 0.899781f, 0.626257f, + 0.898822f, 0.786233f, 0.900583f, 0.804677f, 0.878029f, 0.795063f, + 0.879400f, 0.616512f, 0.889591f, 0.593275f, 0.902359f, 0.607909f, + 0.900583f, 0.804677f, 0.887178f, 0.818729f, 0.878029f, 0.795063f, + 0.540260f, 0.053805f, 0.536419f, 0.062072f, 0.518925f, 0.059681f, 0.518916f, 0.050294f, + 0.518925f, 0.059681f, 0.501452f, 0.062043f, 0.497626f, 0.053770f, 0.518916f, 0.050294f, + 0.551930f, 0.058338f, 0.542788f, 0.064089f, 0.536419f, 0.062072f, 0.540260f, 0.053805f, + 0.501452f, 0.062043f, 0.495083f, 0.064047f, 0.485955f, 0.058273f, 0.497626f, 0.053770f, + 0.555073f, 0.061900f, 0.546290f, 0.072669f, 0.542788f, 0.064089f, 0.551930f, 0.058338f, + 0.495083f, 0.064047f, 0.491565f, 0.072625f, 0.482805f, 0.061829f, 0.485955f, 0.058273f, + 0.563812f, 0.076586f, 0.548333f, 0.084893f, 0.546290f, 0.072669f, 0.555073f, 0.061900f, + 0.491565f, 0.072625f, 0.489507f, 0.084858f, 0.474014f, 0.076511f, 0.482805f, 0.061829f, + 0.583135f, 0.108495f, 0.555621f, 0.121749f, 0.548333f, 0.084893f, 0.563812f, 0.076586f, + 0.489507f, 0.084858f, 0.482177f, 0.121781f, 0.454527f, 0.108481f, 0.474014f, 0.076511f, + 0.605512f, 0.165134f, 0.647395f, 0.200502f, 0.621513f, 0.227818f, 0.553118f, 0.209599f, + 0.416514f, 0.229490f, 0.389677f, 0.201890f, 0.432024f, 0.165644f, 0.485339f, 0.210053f, + 0.647395f, 0.200502f, 0.676379f, 0.233241f, 0.664761f, 0.253225f, 0.621513f, 0.227818f, + 0.372747f, 0.256357f, 0.360308f, 0.235899f, 0.389677f, 0.201890f, 0.416514f, 0.229490f, + 0.676379f, 0.233241f, 0.715342f, 0.265392f, 0.683908f, 0.279995f, 0.664761f, 0.253225f, + 0.353696f, 0.284606f, 0.320452f, 0.270303f, 0.360308f, 0.235899f, 0.372747f, 0.256357f, + 0.715342f, 0.265392f, 0.707254f, 0.310054f, 0.687515f, 0.311539f, 0.683908f, 0.279995f, + 0.351187f, 0.317440f, 0.330721f, 0.316853f, 0.320452f, 0.270303f, 0.353696f, 0.284606f, + 0.707254f, 0.310054f, 0.697446f, 0.332673f, 0.676824f, 0.323937f, 0.687515f, 0.311539f, + 0.362723f, 0.329722f, 0.341964f, 0.339667f, 0.330721f, 0.316853f, 0.351187f, 0.317440f, + 0.697446f, 0.332673f, 0.662817f, 0.372521f, 0.639050f, 0.357330f, 0.676824f, 0.323937f, + 0.402772f, 0.362131f, 0.379297f, 0.378686f, 0.341964f, 0.339667f, 0.362723f, 0.329722f, + 0.662817f, 0.372521f, 0.626842f, 0.395792f, 0.618316f, 0.375151f, 0.639050f, 0.357330f, + 0.424583f, 0.379267f, 0.416915f, 0.400552f, 0.379297f, 0.378686f, 0.402772f, 0.362131f, + 0.626842f, 0.395792f, 0.604826f, 0.397804f, 0.600808f, 0.377857f, 0.618316f, 0.375151f, + 0.442396f, 0.381222f, 0.439252f, 0.401540f, 0.416915f, 0.400552f, 0.424583f, 0.379267f, + 0.604826f, 0.397804f, 0.553095f, 0.390512f, 0.559674f, 0.357011f, 0.600808f, 0.377857f, + 0.482938f, 0.358497f, 0.490934f, 0.391862f, 0.439252f, 0.401540f, 0.442396f, 0.381222f, + 0.553095f, 0.390512f, 0.521923f, 0.386009f, 0.521086f, 0.343868f, 0.559674f, 0.357011f, + 0.521086f, 0.343868f, 0.521923f, 0.386009f, 0.490934f, 0.391862f, 0.482938f, 0.358497f, + 0.577279f, 0.340156f, 0.599845f, 0.344815f, 0.600808f, 0.377857f, 0.559674f, 0.357011f, + 0.442396f, 0.381222f, 0.441977f, 0.347815f, 0.464579f, 0.342230f, 0.482938f, 0.358497f, + 0.599845f, 0.344815f, 0.615546f, 0.342005f, 0.618316f, 0.375151f, 0.600808f, 0.377857f, + 0.424583f, 0.379267f, 0.425972f, 0.345582f, 0.441977f, 0.347815f, 0.442396f, 0.381222f, + 0.634472f, 0.332311f, 0.639050f, 0.357330f, 0.618316f, 0.375151f, 0.615546f, 0.342005f, + 0.424583f, 0.379267f, 0.402772f, 0.362131f, 0.406362f, 0.336480f, 0.425972f, 0.345582f, + 0.662406f, 0.312804f, 0.676824f, 0.323937f, 0.639050f, 0.357330f, 0.634472f, 0.332311f, + 0.402772f, 0.362131f, 0.362723f, 0.329722f, 0.377061f, 0.317685f, 0.406362f, 0.336480f, + 0.668440f, 0.297958f, 0.687515f, 0.311539f, 0.676824f, 0.323937f, 0.662406f, 0.312804f, + 0.362723f, 0.329722f, 0.351187f, 0.317440f, 0.370304f, 0.302644f, 0.377061f, 0.317685f, + 0.664101f, 0.277872f, 0.683908f, 0.279995f, 0.687515f, 0.311539f, 0.668440f, 0.297958f, + 0.351187f, 0.317440f, 0.353696f, 0.284606f, 0.374100f, 0.281778f, 0.370304f, 0.302644f, + 0.639236f, 0.253047f, 0.664761f, 0.253225f, 0.683908f, 0.279995f, 0.664101f, 0.277872f, + 0.353696f, 0.284606f, 0.372747f, 0.256357f, 0.398938f, 0.255633f, 0.374100f, 0.281778f, + 0.613992f, 0.242662f, 0.621513f, 0.227818f, 0.664761f, 0.253225f, 0.639236f, 0.253047f, + 0.372747f, 0.256357f, 0.416514f, 0.229490f, 0.424464f, 0.244473f, 0.398938f, 0.255633f, + 0.572941f, 0.258564f, 0.553118f, 0.209599f, 0.621513f, 0.227818f, 0.613992f, 0.242662f, + 0.416514f, 0.229490f, 0.485339f, 0.210053f, 0.466409f, 0.259709f, 0.424464f, 0.244473f, + 0.572941f, 0.258564f, 0.563905f, 0.272007f, 0.519760f, 0.248864f, 0.553118f, 0.209599f, + 0.519760f, 0.248864f, 0.475886f, 0.273078f, 0.466409f, 0.259709f, 0.485339f, 0.210053f, + 0.577279f, 0.340156f, 0.559674f, 0.357011f, 0.521086f, 0.343868f, 0.558527f, 0.316594f, + 0.521086f, 0.343868f, 0.482938f, 0.358497f, 0.464579f, 0.342230f, 0.482619f, 0.317843f, + 0.558527f, 0.316594f, 0.521086f, 0.343868f, 0.520277f, 0.294764f, 0.556923f, 0.291214f, + 0.520277f, 0.294764f, 0.521086f, 0.343868f, 0.482619f, 0.317843f, 0.483433f, 0.292249f, + 0.519760f, 0.248864f, 0.563905f, 0.272007f, 0.556923f, 0.291214f, 0.520277f, 0.294764f, + 0.483433f, 0.292249f, 0.475886f, 0.273078f, 0.519760f, 0.248864f, 0.520277f, 0.294764f, + 0.525483f, 0.068967f, 0.518928f, 0.067899f, 0.518925f, 0.059681f, 0.536419f, 0.062072f, + 0.518925f, 0.059681f, 0.518928f, 0.067899f, 0.512375f, 0.068956f, 0.501452f, 0.062043f, + 0.531231f, 0.073829f, 0.525483f, 0.068967f, 0.536419f, 0.062072f, 0.542788f, 0.064089f, + 0.501452f, 0.062043f, 0.512375f, 0.068956f, 0.506626f, 0.073811f, 0.495083f, 0.064047f, + 0.531019f, 0.087431f, 0.531231f, 0.073829f, 0.542788f, 0.064089f, 0.546290f, 0.072669f, + 0.495083f, 0.064047f, 0.506626f, 0.073811f, 0.506827f, 0.087416f, 0.491565f, 0.072625f, + 0.555621f, 0.121749f, 0.532042f, 0.127713f, 0.532669f, 0.090920f, 0.548333f, 0.084893f, + 0.505177f, 0.090908f, 0.505828f, 0.127728f, 0.482177f, 0.121781f, 0.489507f, 0.084858f, + 0.531019f, 0.087431f, 0.546290f, 0.072669f, 0.548333f, 0.084893f, 0.532669f, 0.090920f, + 0.489507f, 0.084858f, 0.491565f, 0.072625f, 0.506827f, 0.087416f, 0.505177f, 0.090908f, + 0.538112f, 0.158382f, 0.518981f, 0.151749f, 0.518941f, 0.128358f, 0.532042f, 0.127713f, + 0.518941f, 0.128358f, 0.518981f, 0.151749f, 0.499851f, 0.158434f, 0.505828f, 0.127728f, + 0.532669f, 0.090920f, 0.532042f, 0.127713f, 0.518941f, 0.128358f, 0.518925f, 0.093952f, + 0.518941f, 0.128358f, 0.505828f, 0.127728f, 0.505177f, 0.090908f, 0.518925f, 0.093952f, + 0.518927f, 0.085180f, 0.531019f, 0.087431f, 0.532669f, 0.090920f, 0.518925f, 0.093952f, + 0.505177f, 0.090908f, 0.506827f, 0.087416f, 0.518927f, 0.085180f, 0.518925f, 0.093952f, + 0.548362f, 0.173560f, 0.537959f, 0.175966f, 0.535214f, 0.166808f, 0.538112f, 0.158382f, + 0.502799f, 0.166857f, 0.500100f, 0.176033f, 0.489683f, 0.173693f, 0.499851f, 0.158434f, + 0.544281f, 0.193366f, 0.537248f, 0.187577f, 0.537959f, 0.175966f, 0.548362f, 0.173560f, + 0.500100f, 0.176033f, 0.500890f, 0.187571f, 0.493996f, 0.193428f, 0.489683f, 0.173693f, + 0.519841f, 0.200843f, 0.528757f, 0.191785f, 0.537248f, 0.187577f, 0.544281f, 0.193366f, + 0.500890f, 0.187571f, 0.509219f, 0.191626f, 0.519841f, 0.200843f, 0.493996f, 0.193428f, + 0.517577f, 0.190607f, 0.519132f, 0.185382f, 0.528757f, 0.191785f, 0.519841f, 0.200843f, + 0.509219f, 0.191626f, 0.519132f, 0.185382f, 0.517577f, 0.190607f, 0.519841f, 0.200843f, + 0.518981f, 0.151749f, 0.538112f, 0.158382f, 0.535214f, 0.166808f, 0.518998f, 0.159028f, + 0.502799f, 0.166857f, 0.499851f, 0.158434f, 0.518981f, 0.151749f, 0.518998f, 0.159028f, + 0.518998f, 0.159028f, 0.535214f, 0.166808f, 0.531131f, 0.171631f, 0.519016f, 0.165599f, + 0.506910f, 0.171667f, 0.502799f, 0.166857f, 0.518998f, 0.159028f, 0.519016f, 0.165599f, + 0.519132f, 0.185382f, 0.519099f, 0.179457f, 0.528222f, 0.186316f, 0.528757f, 0.191785f, + 0.509787f, 0.186260f, 0.519099f, 0.179457f, 0.519132f, 0.185382f, 0.509219f, 0.191626f, + 0.528757f, 0.191785f, 0.528222f, 0.186316f, 0.533528f, 0.184215f, 0.537248f, 0.187577f, + 0.504547f, 0.184206f, 0.509787f, 0.186260f, 0.509219f, 0.191626f, 0.500890f, 0.187571f, + 0.537248f, 0.187577f, 0.533528f, 0.184215f, 0.533449f, 0.176739f, 0.537959f, 0.175966f, + 0.504604f, 0.176791f, 0.504547f, 0.184206f, 0.500890f, 0.187571f, 0.500100f, 0.176033f, + 0.537959f, 0.175966f, 0.533449f, 0.176739f, 0.531131f, 0.171631f, 0.535214f, 0.166808f, + 0.506910f, 0.171667f, 0.504604f, 0.176791f, 0.500100f, 0.176033f, 0.502799f, 0.166857f, + 0.519099f, 0.179457f, 0.533449f, 0.176739f, 0.533528f, 0.184215f, 0.528222f, 0.186316f, + 0.504547f, 0.184206f, 0.504604f, 0.176791f, 0.519099f, 0.179457f, 0.509787f, 0.186260f, + 0.519099f, 0.179457f, 0.519016f, 0.165599f, 0.531131f, 0.171631f, 0.533449f, 0.176739f, + 0.506910f, 0.171667f, 0.519016f, 0.165599f, 0.519099f, 0.179457f, 0.504604f, 0.176791f, + 0.519841f, 0.200843f, 0.544281f, 0.193366f, 0.553118f, 0.209599f, 0.519760f, 0.248864f, + 0.485339f, 0.210053f, 0.493996f, 0.193428f, 0.519841f, 0.200843f, 0.519760f, 0.248864f, + 0.544281f, 0.193366f, 0.548362f, 0.173560f, 0.561572f, 0.167779f, 0.553118f, 0.209599f, + 0.476363f, 0.167996f, 0.489683f, 0.173693f, 0.493996f, 0.193428f, 0.485339f, 0.210053f, + 0.548362f, 0.173560f, 0.538112f, 0.158382f, 0.559475f, 0.149319f, 0.561572f, 0.167779f, + 0.478371f, 0.149447f, 0.499851f, 0.158434f, 0.489683f, 0.173693f, 0.476363f, 0.167996f, + 0.538112f, 0.158382f, 0.532042f, 0.127713f, 0.555621f, 0.121749f, 0.559475f, 0.149319f, + 0.482177f, 0.121781f, 0.505828f, 0.127728f, 0.499851f, 0.158434f, 0.478371f, 0.149447f, + 0.583135f, 0.108495f, 0.596138f, 0.133426f, 0.559475f, 0.149319f, 0.555621f, 0.121749f, + 0.478371f, 0.149447f, 0.441395f, 0.133592f, 0.454527f, 0.108481f, 0.482177f, 0.121781f, + 0.596138f, 0.133426f, 0.601169f, 0.147885f, 0.561572f, 0.167779f, 0.559475f, 0.149319f, + 0.476363f, 0.167996f, 0.436337f, 0.148194f, 0.441395f, 0.133592f, 0.478371f, 0.149447f, + 0.605512f, 0.165134f, 0.553118f, 0.209599f, 0.561572f, 0.167779f, 0.601169f, 0.147885f, + 0.476363f, 0.167996f, 0.485339f, 0.210053f, 0.432024f, 0.165644f, 0.436337f, 0.148194f, + 0.531019f, 0.087431f, 0.518927f, 0.085180f, 0.518925f, 0.083865f, 0.528933f, 0.084957f, + 0.518925f, 0.083865f, 0.518927f, 0.085180f, 0.506827f, 0.087416f, 0.508915f, 0.084945f, + 0.531231f, 0.073829f, 0.531019f, 0.087431f, 0.528933f, 0.084957f, 0.529036f, 0.075429f, + 0.508915f, 0.084945f, 0.506827f, 0.087416f, 0.506626f, 0.073811f, 0.508820f, 0.075415f, + 0.525483f, 0.068967f, 0.531231f, 0.073829f, 0.529036f, 0.075429f, 0.523751f, 0.070508f, + 0.508820f, 0.075415f, 0.506626f, 0.073811f, 0.512375f, 0.068956f, 0.514106f, 0.070501f, + 0.518928f, 0.067899f, 0.525483f, 0.068967f, 0.523751f, 0.070508f, 0.518929f, 0.069468f, + 0.514106f, 0.070501f, 0.512375f, 0.068956f, 0.518928f, 0.067899f, 0.518929f, 0.069468f, + 0.518929f, 0.069468f, 0.523751f, 0.070508f, 0.521560f, 0.074970f, 0.518928f, 0.074259f, + 0.516297f, 0.074966f, 0.514106f, 0.070501f, 0.518929f, 0.069468f, 0.518928f, 0.074259f, + 0.523751f, 0.070508f, 0.529036f, 0.075429f, 0.524236f, 0.076691f, 0.521560f, 0.074970f, + 0.513619f, 0.076684f, 0.508820f, 0.075415f, 0.514106f, 0.070501f, 0.516297f, 0.074966f, + 0.529036f, 0.075429f, 0.528933f, 0.084957f, 0.524601f, 0.079886f, 0.524236f, 0.076691f, + 0.513252f, 0.079879f, 0.508915f, 0.084945f, 0.508820f, 0.075415f, 0.513619f, 0.076684f, + 0.528933f, 0.084957f, 0.518925f, 0.083865f, 0.518926f, 0.079331f, 0.524601f, 0.079886f, + 0.518926f, 0.079331f, 0.518925f, 0.083865f, 0.508915f, 0.084945f, 0.513252f, 0.079879f, + 0.518926f, 0.079331f, 0.518928f, 0.074259f, 0.521560f, 0.074970f, 0.524601f, 0.079886f, + 0.516297f, 0.074966f, 0.518928f, 0.074259f, 0.518926f, 0.079331f, 0.513252f, 0.079879f, + 0.524601f, 0.079886f, 0.521560f, 0.074970f, 0.524236f, 0.076691f, + 0.513619f, 0.076684f, 0.516297f, 0.074966f, 0.513252f, 0.079879f, + 0.556923f, 0.291214f, 0.563905f, 0.272007f, 0.571787f, 0.277295f, 0.568351f, 0.292904f, + 0.468070f, 0.278617f, 0.475886f, 0.273078f, 0.483433f, 0.292249f, 0.471978f, 0.294282f, + 0.558527f, 0.316594f, 0.556923f, 0.291214f, 0.568351f, 0.292904f, 0.573085f, 0.311386f, + 0.471978f, 0.294282f, 0.483433f, 0.292249f, 0.482619f, 0.317843f, 0.467790f, 0.313081f, + 0.577279f, 0.340156f, 0.558527f, 0.316594f, 0.573085f, 0.311386f, 0.584855f, 0.327708f, + 0.467790f, 0.313081f, 0.482619f, 0.317843f, 0.464579f, 0.342230f, 0.456477f, 0.329961f, + 0.563905f, 0.272007f, 0.572941f, 0.258564f, 0.580734f, 0.266620f, 0.571787f, 0.277295f, + 0.458737f, 0.268049f, 0.466409f, 0.259709f, 0.475886f, 0.273078f, 0.468070f, 0.278617f, + 0.572941f, 0.258564f, 0.613992f, 0.242662f, 0.611720f, 0.255725f, 0.580734f, 0.266620f, + 0.427062f, 0.257728f, 0.424464f, 0.244473f, 0.466409f, 0.259709f, 0.458737f, 0.268049f, + 0.613992f, 0.242662f, 0.639236f, 0.253047f, 0.632494f, 0.262853f, 0.611720f, 0.255725f, + 0.406068f, 0.265508f, 0.398938f, 0.255633f, 0.424464f, 0.244473f, 0.427062f, 0.257728f, + 0.639236f, 0.253047f, 0.664101f, 0.277872f, 0.653658f, 0.279971f, 0.632494f, 0.262853f, + 0.384904f, 0.283634f, 0.374100f, 0.281778f, 0.398938f, 0.255633f, 0.406068f, 0.265508f, + 0.664101f, 0.277872f, 0.668440f, 0.297958f, 0.656064f, 0.297636f, 0.653658f, 0.279971f, + 0.383015f, 0.301864f, 0.370304f, 0.302644f, 0.374100f, 0.281778f, 0.384904f, 0.283634f, + 0.668440f, 0.297958f, 0.662406f, 0.312804f, 0.652752f, 0.310186f, 0.656064f, 0.297636f, + 0.386858f, 0.314615f, 0.377061f, 0.317685f, 0.370304f, 0.302644f, 0.383015f, 0.301864f, + 0.662406f, 0.312804f, 0.634472f, 0.332311f, 0.629040f, 0.323864f, 0.652752f, 0.310186f, + 0.411556f, 0.327673f, 0.406362f, 0.336480f, 0.377061f, 0.317685f, 0.386858f, 0.314615f, + 0.634472f, 0.332311f, 0.615546f, 0.342005f, 0.614408f, 0.331972f, 0.629040f, 0.323864f, + 0.426727f, 0.335361f, 0.425972f, 0.345582f, 0.406362f, 0.336480f, 0.411556f, 0.327673f, + 0.615546f, 0.342005f, 0.599845f, 0.344815f, 0.601033f, 0.333624f, 0.614408f, 0.331972f, + 0.440344f, 0.336537f, 0.441977f, 0.347815f, 0.425972f, 0.345582f, 0.426727f, 0.335361f, + 0.599845f, 0.344815f, 0.577279f, 0.340156f, 0.584855f, 0.327708f, 0.601033f, 0.333624f, + 0.456477f, 0.329961f, 0.464579f, 0.342230f, 0.441977f, 0.347815f, 0.440344f, 0.336537f, + 0.601033f, 0.333624f, 0.584855f, 0.327708f, 0.590644f, 0.321516f, 0.601799f, 0.328453f, + 0.450408f, 0.323919f, 0.456477f, 0.329961f, 0.440344f, 0.336537f, 0.439372f, 0.331331f, + 0.614408f, 0.331972f, 0.601033f, 0.333624f, 0.601799f, 0.328453f, 0.613335f, 0.327083f, + 0.439372f, 0.331331f, 0.440344f, 0.336537f, 0.426727f, 0.335361f, 0.427623f, 0.330358f, + 0.629040f, 0.323864f, 0.614408f, 0.331972f, 0.613335f, 0.327083f, 0.626851f, 0.320513f, + 0.427623f, 0.330358f, 0.426727f, 0.335361f, 0.411556f, 0.327673f, 0.413648f, 0.324175f, + 0.652752f, 0.310186f, 0.629040f, 0.323864f, 0.626851f, 0.320513f, 0.646248f, 0.306421f, + 0.413648f, 0.324175f, 0.411556f, 0.327673f, 0.386858f, 0.314615f, 0.393381f, 0.310510f, + 0.656064f, 0.297636f, 0.652752f, 0.310186f, 0.646248f, 0.306421f, 0.649541f, 0.296225f, + 0.393381f, 0.310510f, 0.386858f, 0.314615f, 0.383015f, 0.301864f, 0.389662f, 0.300183f, + 0.653658f, 0.279971f, 0.656064f, 0.297636f, 0.649541f, 0.296225f, 0.647785f, 0.283486f, + 0.389662f, 0.300183f, 0.383015f, 0.301864f, 0.384904f, 0.283634f, 0.391040f, 0.287071f, + 0.632494f, 0.262853f, 0.653658f, 0.279971f, 0.647785f, 0.283486f, 0.629829f, 0.267263f, + 0.391040f, 0.287071f, 0.384904f, 0.283634f, 0.406068f, 0.265508f, 0.408893f, 0.269959f, + 0.611720f, 0.255725f, 0.632494f, 0.262853f, 0.629829f, 0.267263f, 0.612641f, 0.261560f, + 0.408893f, 0.269959f, 0.406068f, 0.265508f, 0.427062f, 0.257728f, 0.426254f, 0.263693f, + 0.580734f, 0.266620f, 0.611720f, 0.255725f, 0.612641f, 0.261560f, 0.585166f, 0.270991f, + 0.426254f, 0.263693f, 0.427062f, 0.257728f, 0.458737f, 0.268049f, 0.454369f, 0.272583f, + 0.571787f, 0.277295f, 0.580734f, 0.266620f, 0.585166f, 0.270991f, 0.578124f, 0.281900f, + 0.454369f, 0.272583f, 0.458737f, 0.268049f, 0.468070f, 0.278617f, 0.461798f, 0.283441f, + 0.584855f, 0.327708f, 0.573085f, 0.311386f, 0.579548f, 0.309340f, 0.590644f, 0.321516f, + 0.461204f, 0.311233f, 0.467790f, 0.313081f, 0.456477f, 0.329961f, 0.450408f, 0.323919f, + 0.573085f, 0.311386f, 0.568351f, 0.292904f, 0.577524f, 0.293776f, 0.579548f, 0.309340f, + 0.462754f, 0.295432f, 0.471978f, 0.294282f, 0.467790f, 0.313081f, 0.461204f, 0.311233f, + 0.568351f, 0.292904f, 0.571787f, 0.277295f, 0.578124f, 0.281900f, 0.577524f, 0.293776f, + 0.461798f, 0.283441f, 0.468070f, 0.278617f, 0.471978f, 0.294282f, 0.462754f, 0.295432f, + 0.521923f, 0.386009f, 0.553095f, 0.390512f, 0.553209f, 0.433063f, 0.523031f, 0.433628f, + 0.492809f, 0.434538f, 0.490934f, 0.391862f, 0.521923f, 0.386009f, 0.523031f, 0.433628f, + 0.553095f, 0.390512f, 0.604826f, 0.397804f, 0.609819f, 0.431516f, 0.553209f, 0.433063f, + 0.435860f, 0.435740f, 0.439252f, 0.401540f, 0.490934f, 0.391862f, 0.492809f, 0.434538f, + 0.604826f, 0.397804f, 0.626842f, 0.395792f, 0.648174f, 0.419316f, 0.609819f, 0.431516f, + 0.396518f, 0.425416f, 0.416915f, 0.400552f, 0.439252f, 0.401540f, 0.435860f, 0.435740f, + 0.626842f, 0.395792f, 0.662817f, 0.372521f, 0.692106f, 0.388274f, 0.648174f, 0.419316f, + 0.350292f, 0.396229f, 0.379297f, 0.378686f, 0.416915f, 0.400552f, 0.396518f, 0.425416f, + 0.662817f, 0.372521f, 0.697446f, 0.332673f, 0.726332f, 0.341754f, 0.692106f, 0.388274f, + 0.312756f, 0.350588f, 0.341964f, 0.339667f, 0.379297f, 0.378686f, 0.350292f, 0.396229f, + 0.697446f, 0.332673f, 0.707254f, 0.310054f, 0.735879f, 0.312112f, 0.726332f, 0.341754f, + 0.301067f, 0.320593f, 0.330721f, 0.316853f, 0.341964f, 0.339667f, 0.312756f, 0.350588f, + 0.707254f, 0.310054f, 0.715342f, 0.265392f, 0.729900f, 0.256393f, 0.735879f, 0.312112f, + 0.304876f, 0.261087f, 0.320452f, 0.270303f, 0.330721f, 0.316853f, 0.301067f, 0.320593f, + 0.715342f, 0.265392f, 0.676379f, 0.233241f, 0.698172f, 0.216906f, 0.729900f, 0.256393f, + 0.337414f, 0.219179f, 0.360308f, 0.235899f, 0.320452f, 0.270303f, 0.304876f, 0.261087f, + 0.676379f, 0.233241f, 0.647395f, 0.200502f, 0.663103f, 0.190671f, 0.698172f, 0.216906f, + 0.373474f, 0.191872f, 0.389677f, 0.201890f, 0.360308f, 0.235899f, 0.337414f, 0.219179f, + 0.626908f, 0.015608f, 0.649444f, 0.022378f, 0.660451f, 0.076084f, 0.621440f, 0.048089f, + 0.376796f, 0.075296f, 0.388827f, 0.021586f, 0.411318f, 0.015131f, 0.416419f, 0.047631f, + 0.567460f, 0.000144f, 0.626908f, 0.015608f, 0.621440f, 0.048089f, 0.577206f, 0.032801f, + 0.416419f, 0.047631f, 0.411318f, 0.015131f, 0.470636f, 0.000144f, 0.460782f, 0.032656f, + 0.518922f, 0.024886f, 0.567460f, 0.000144f, 0.577206f, 0.032801f, 0.547413f, 0.041724f, + 0.460782f, 0.032656f, 0.470636f, 0.000144f, 0.518922f, 0.024886f, 0.490511f, 0.041669f, + 0.540260f, 0.053805f, 0.518916f, 0.050294f, 0.518922f, 0.024886f, 0.547413f, 0.041724f, + 0.518922f, 0.024886f, 0.518916f, 0.050294f, 0.497626f, 0.053770f, 0.490511f, 0.041669f, + 0.551930f, 0.058338f, 0.540260f, 0.053805f, 0.547413f, 0.041724f, 0.558059f, 0.053871f, + 0.490511f, 0.041669f, 0.497626f, 0.053770f, 0.485955f, 0.058273f, 0.479842f, 0.053785f, + 0.555073f, 0.061900f, 0.551930f, 0.058338f, 0.558059f, 0.053871f, 0.576951f, 0.057998f, + 0.479842f, 0.053785f, 0.485955f, 0.058273f, 0.482805f, 0.061829f, 0.460920f, 0.057845f, + 0.563812f, 0.076586f, 0.555073f, 0.061900f, 0.576951f, 0.057998f, 0.611687f, 0.078268f, + 0.460920f, 0.057845f, 0.482805f, 0.061829f, 0.474014f, 0.076511f, 0.425932f, 0.077985f, + 0.576951f, 0.057998f, 0.577206f, 0.032801f, 0.621440f, 0.048089f, 0.611687f, 0.078268f, + 0.416419f, 0.047631f, 0.460782f, 0.032656f, 0.460920f, 0.057845f, 0.425932f, 0.077985f, + 0.576951f, 0.057998f, 0.558059f, 0.053871f, 0.547413f, 0.041724f, 0.577206f, 0.032801f, + 0.490511f, 0.041669f, 0.479842f, 0.053785f, 0.460920f, 0.057845f, 0.460782f, 0.032656f, + 0.626663f, 0.111357f, 0.611687f, 0.078268f, 0.621440f, 0.048089f, 0.660451f, 0.076084f, + 0.416419f, 0.047631f, 0.425932f, 0.077985f, 0.410618f, 0.111244f, 0.376796f, 0.075296f, + 0.583135f, 0.108495f, 0.563812f, 0.076586f, 0.611687f, 0.078268f, 0.626663f, 0.111357f, + 0.425932f, 0.077985f, 0.474014f, 0.076511f, 0.454527f, 0.108481f, 0.410618f, 0.111244f, + 0.596138f, 0.133426f, 0.629482f, 0.130456f, 0.623495f, 0.146796f, 0.601169f, 0.147885f, + 0.413741f, 0.147158f, 0.407648f, 0.130594f, 0.441395f, 0.133592f, 0.436337f, 0.148194f, + 0.583135f, 0.108495f, 0.626663f, 0.111357f, 0.629482f, 0.130456f, 0.596138f, 0.133426f, + 0.407648f, 0.130594f, 0.410618f, 0.111244f, 0.454527f, 0.108481f, 0.441395f, 0.133592f, + 0.605512f, 0.165134f, 0.601169f, 0.147885f, 0.623495f, 0.146796f, 0.619303f, 0.159841f, + 0.413741f, 0.147158f, 0.436337f, 0.148194f, 0.432024f, 0.165644f, 0.418035f, 0.160361f, + 0.605512f, 0.165134f, 0.619303f, 0.159841f, 0.663103f, 0.190671f, 0.647395f, 0.200502f, + 0.373474f, 0.191872f, 0.418035f, 0.160361f, 0.432024f, 0.165644f, 0.389677f, 0.201890f, + 0.945900f, 0.079569f, 0.886245f, 0.121777f, 0.849114f, 0.099732f, 0.891780f, 0.036916f, + 0.183115f, 0.092127f, 0.141314f, 0.112482f, 0.078961f, 0.060719f, 0.142277f, 0.021467f, + 0.891780f, 0.036916f, 0.849114f, 0.099732f, 0.788458f, 0.080826f, 0.805584f, 0.010786f, + 0.246353f, 0.076510f, 0.183115f, 0.092127f, 0.142277f, 0.021467f, 0.232648f, 0.003484f, + 0.805584f, 0.010786f, 0.788458f, 0.080826f, 0.687018f, 0.077204f, 0.672384f, 0.022201f, + 0.349875f, 0.075955f, 0.246353f, 0.076510f, 0.232648f, 0.003484f, 0.365979f, 0.020991f, + 0.672384f, 0.022201f, 0.687018f, 0.077204f, 0.660451f, 0.076084f, 0.649444f, 0.022378f, + 0.376796f, 0.075296f, 0.349875f, 0.075955f, 0.365979f, 0.020991f, 0.388827f, 0.021586f, + 0.626663f, 0.111357f, 0.660451f, 0.076084f, 0.687018f, 0.077204f, 0.629482f, 0.130456f, + 0.349875f, 0.075955f, 0.376796f, 0.075296f, 0.410618f, 0.111244f, 0.407648f, 0.130594f, + 0.729900f, 0.256393f, 0.698172f, 0.216906f, 0.760215f, 0.193244f, 0.789046f, 0.233323f, + 0.271553f, 0.193871f, 0.337414f, 0.219179f, 0.304876f, 0.261087f, 0.241255f, 0.236977f, + 0.994525f, 0.167705f, 0.909112f, 0.183261f, 0.886245f, 0.121777f, 0.945900f, 0.079569f, + 0.141314f, 0.112482f, 0.107928f, 0.179083f, 0.011829f, 0.155367f, 0.078961f, 0.060719f, + 0.911671f, 0.402429f, 0.862868f, 0.338556f, 0.894128f, 0.301884f, 0.962901f, 0.344752f, + 0.123776f, 0.315519f, 0.160557f, 0.356821f, 0.106400f, 0.432652f, 0.043968f, 0.367038f, + 0.962901f, 0.344752f, 0.894128f, 0.301884f, 0.915360f, 0.259804f, 0.999856f, 0.254640f, + 0.098965f, 0.266968f, 0.123776f, 0.315519f, 0.043968f, 0.367038f, 0.000144f, 0.259113f, + 0.999856f, 0.254640f, 0.915360f, 0.259804f, 0.909112f, 0.183261f, 0.994525f, 0.167705f, + 0.107928f, 0.179083f, 0.098965f, 0.266968f, 0.000144f, 0.259113f, 0.011829f, 0.155367f, + 0.749542f, 0.334683f, 0.735879f, 0.312112f, 0.766337f, 0.300809f, 0.789162f, 0.313727f, + 0.267408f, 0.310142f, 0.301067f, 0.320593f, 0.288183f, 0.346496f, 0.242992f, 0.325552f, + 0.789162f, 0.313727f, 0.766337f, 0.300809f, 0.815314f, 0.276388f, 0.846174f, 0.293397f, + 0.213065f, 0.285164f, 0.267408f, 0.310142f, 0.242992f, 0.325552f, 0.178537f, 0.304983f, + 0.846174f, 0.293397f, 0.815314f, 0.276388f, 0.845007f, 0.256352f, 0.873517f, 0.265922f, + 0.179662f, 0.263312f, 0.213065f, 0.285164f, 0.178537f, 0.304983f, 0.147089f, 0.274284f, + 0.873517f, 0.265922f, 0.845007f, 0.256352f, 0.859075f, 0.228168f, 0.886999f, 0.233769f, + 0.162803f, 0.231720f, 0.179662f, 0.263312f, 0.147089f, 0.274284f, 0.131514f, 0.237587f, + 0.842355f, 0.195160f, 0.875030f, 0.184705f, 0.886999f, 0.233769f, 0.859075f, 0.228168f, + 0.131514f, 0.237587f, 0.145224f, 0.182749f, 0.176788f, 0.196179f, 0.162803f, 0.231720f, + 0.909112f, 0.183261f, 0.915360f, 0.259804f, 0.886999f, 0.233769f, 0.875030f, 0.184705f, + 0.131514f, 0.237587f, 0.098965f, 0.266968f, 0.107928f, 0.179083f, 0.145224f, 0.182749f, + 0.915360f, 0.259804f, 0.894128f, 0.301884f, 0.873517f, 0.265922f, 0.886999f, 0.233769f, + 0.147089f, 0.274284f, 0.123776f, 0.315519f, 0.098965f, 0.266968f, 0.131514f, 0.237587f, + 0.894128f, 0.301884f, 0.862868f, 0.338556f, 0.846174f, 0.293397f, 0.873517f, 0.265922f, + 0.178537f, 0.304983f, 0.160557f, 0.356821f, 0.123776f, 0.315519f, 0.147089f, 0.274284f, + 0.862868f, 0.338556f, 0.794286f, 0.364062f, 0.789162f, 0.313727f, 0.846174f, 0.293397f, + 0.242992f, 0.325552f, 0.239776f, 0.382592f, 0.160557f, 0.356821f, 0.178537f, 0.304983f, + 0.770185f, 0.379538f, 0.749542f, 0.334683f, 0.789162f, 0.313727f, 0.794286f, 0.364062f, + 0.242992f, 0.325552f, 0.288183f, 0.346496f, 0.268122f, 0.398737f, 0.239776f, 0.382592f, + 0.845499f, 0.449967f, 0.794286f, 0.364062f, 0.862868f, 0.338556f, 0.911671f, 0.402429f, + 0.160557f, 0.356821f, 0.239776f, 0.382592f, 0.185281f, 0.484099f, 0.106400f, 0.432652f, + 0.815858f, 0.445381f, 0.770572f, 0.444261f, 0.755700f, 0.418603f, 0.770185f, 0.379538f, + 0.287033f, 0.442912f, 0.271364f, 0.473316f, 0.219260f, 0.477186f, 0.268122f, 0.398737f, + 0.815858f, 0.445381f, 0.770185f, 0.379538f, 0.794286f, 0.364062f, 0.845499f, 0.449967f, + 0.239776f, 0.382592f, 0.268122f, 0.398737f, 0.219260f, 0.477186f, 0.185281f, 0.484099f, + 0.819845f, 0.468071f, 0.815858f, 0.445381f, 0.845499f, 0.449967f, + 0.185281f, 0.484099f, 0.219260f, 0.477186f, 0.215894f, 0.503605f, + 0.735879f, 0.312112f, 0.729900f, 0.256393f, 0.789046f, 0.233323f, 0.766337f, 0.300809f, + 0.241255f, 0.236977f, 0.304876f, 0.261087f, 0.301067f, 0.320593f, 0.267408f, 0.310142f, + 0.789046f, 0.233323f, 0.809631f, 0.233887f, 0.815314f, 0.276388f, 0.766337f, 0.300809f, + 0.213065f, 0.285164f, 0.219168f, 0.237388f, 0.241255f, 0.236977f, 0.267408f, 0.310142f, + 0.809631f, 0.233887f, 0.829287f, 0.219562f, 0.845007f, 0.256352f, 0.815314f, 0.276388f, + 0.179662f, 0.263312f, 0.199067f, 0.222464f, 0.219168f, 0.237388f, 0.213065f, 0.285164f, + 0.842355f, 0.195160f, 0.859075f, 0.228168f, 0.845007f, 0.256352f, 0.829287f, 0.219562f, + 0.179662f, 0.263312f, 0.162803f, 0.231720f, 0.176788f, 0.196179f, 0.199067f, 0.222464f, + 0.687018f, 0.077204f, 0.788458f, 0.080826f, 0.786480f, 0.117591f, 0.715482f, 0.139727f, + 0.246666f, 0.114850f, 0.246353f, 0.076510f, 0.349875f, 0.075955f, 0.319538f, 0.139409f, + 0.760215f, 0.193244f, 0.715482f, 0.139727f, 0.786480f, 0.117591f, 0.785486f, 0.152330f, + 0.246666f, 0.114850f, 0.319538f, 0.139409f, 0.271553f, 0.193871f, 0.245969f, 0.151002f, + 0.698172f, 0.216906f, 0.663103f, 0.190671f, 0.715482f, 0.139727f, 0.760215f, 0.193244f, + 0.319538f, 0.139409f, 0.373474f, 0.191872f, 0.337414f, 0.219179f, 0.271553f, 0.193871f, + 0.663103f, 0.190671f, 0.623495f, 0.146796f, 0.629482f, 0.130456f, 0.715482f, 0.139727f, + 0.407648f, 0.130594f, 0.413741f, 0.147158f, 0.373474f, 0.191872f, 0.319538f, 0.139409f, + 0.629482f, 0.130456f, 0.687018f, 0.077204f, 0.715482f, 0.139727f, + 0.319538f, 0.139409f, 0.349875f, 0.075955f, 0.407648f, 0.130594f, + 0.663103f, 0.190671f, 0.619303f, 0.159841f, 0.623495f, 0.146796f, + 0.413741f, 0.147158f, 0.418035f, 0.160361f, 0.373474f, 0.191872f, + 0.842355f, 0.195160f, 0.837382f, 0.156361f, 0.858171f, 0.137775f, 0.875030f, 0.184705f, + 0.171653f, 0.132294f, 0.196622f, 0.155241f, 0.176788f, 0.196179f, 0.145224f, 0.182749f, + 0.909112f, 0.183261f, 0.875030f, 0.184705f, 0.858171f, 0.137775f, 0.886245f, 0.121777f, + 0.171653f, 0.132294f, 0.145224f, 0.182749f, 0.107928f, 0.179083f, 0.141314f, 0.112482f, + 0.785486f, 0.152330f, 0.786480f, 0.117591f, 0.858171f, 0.137775f, 0.837382f, 0.156361f, + 0.171653f, 0.132294f, 0.246666f, 0.114850f, 0.245969f, 0.151002f, 0.196622f, 0.155241f, + 0.788458f, 0.080826f, 0.849114f, 0.099732f, 0.858171f, 0.137775f, 0.786480f, 0.117591f, + 0.171653f, 0.132294f, 0.183115f, 0.092127f, 0.246353f, 0.076510f, 0.246666f, 0.114850f, + 0.886245f, 0.121777f, 0.858171f, 0.137775f, 0.849114f, 0.099732f, + 0.183115f, 0.092127f, 0.171653f, 0.132294f, 0.141314f, 0.112482f, + 0.506166f, 0.904851f, 0.432388f, 0.894943f, 0.438797f, 0.870229f, 0.491058f, 0.881714f, + 0.315867f, 0.868209f, 0.321637f, 0.893225f, 0.247207f, 0.901159f, 0.263032f, 0.878321f, + 0.506166f, 0.904851f, 0.491058f, 0.881714f, 0.572792f, 0.860484f, 0.604825f, 0.879946f, + 0.181486f, 0.854693f, 0.263032f, 0.878321f, 0.247207f, 0.901159f, 0.148729f, 0.873349f, + 0.604825f, 0.879946f, 0.572792f, 0.860484f, 0.586396f, 0.793977f, 0.619962f, 0.791615f, + 0.169745f, 0.787474f, 0.181486f, 0.854693f, 0.148729f, 0.873349f, 0.136063f, 0.784093f, + 0.619962f, 0.791615f, 0.586396f, 0.793977f, 0.549027f, 0.746412f, 0.563786f, 0.739211f, + 0.208656f, 0.740879f, 0.169745f, 0.787474f, 0.136063f, 0.784093f, 0.194086f, 0.733241f, + 0.563786f, 0.739211f, 0.549027f, 0.746412f, 0.500314f, 0.711729f, 0.508270f, 0.697693f, + 0.258399f, 0.707497f, 0.208656f, 0.740879f, 0.194086f, 0.733241f, 0.250811f, 0.693249f, + 0.508270f, 0.697693f, 0.500314f, 0.711729f, 0.438641f, 0.680683f, 0.434803f, 0.658882f, + 0.320962f, 0.677959f, 0.258399f, 0.707497f, 0.250811f, 0.693249f, 0.325318f, 0.656224f, + 0.500314f, 0.711729f, 0.505666f, 0.730944f, 0.452955f, 0.700023f, 0.438641f, 0.680683f, + 0.306136f, 0.696976f, 0.252524f, 0.726592f, 0.258399f, 0.707497f, 0.320962f, 0.677959f, + 0.549027f, 0.746412f, 0.542850f, 0.755753f, 0.505666f, 0.730944f, 0.500314f, 0.711729f, + 0.252524f, 0.726592f, 0.214575f, 0.750414f, 0.208656f, 0.740879f, 0.258399f, 0.707497f, + 0.586396f, 0.793977f, 0.568148f, 0.787367f, 0.542850f, 0.755753f, 0.549027f, 0.746412f, + 0.214575f, 0.750414f, 0.188269f, 0.781375f, 0.169745f, 0.787474f, 0.208656f, 0.740879f, + 0.572792f, 0.860484f, 0.555495f, 0.826352f, 0.568148f, 0.787367f, 0.586396f, 0.793977f, + 0.188269f, 0.781375f, 0.199850f, 0.820889f, 0.181486f, 0.854693f, 0.169745f, 0.787474f, + 0.491058f, 0.881714f, 0.501231f, 0.844356f, 0.555495f, 0.826352f, 0.572792f, 0.860484f, + 0.199850f, 0.820889f, 0.253846f, 0.840502f, 0.263032f, 0.878321f, 0.181486f, 0.854693f, + 0.491058f, 0.881714f, 0.438797f, 0.870229f, 0.457832f, 0.840040f, 0.501231f, 0.844356f, + 0.297562f, 0.837358f, 0.315867f, 0.868209f, 0.263032f, 0.878321f, 0.253846f, 0.840502f, + 0.760215f, 0.193244f, 0.785486f, 0.152330f, 0.796021f, 0.176969f, 0.783193f, 0.187449f, + 0.233625f, 0.175620f, 0.245969f, 0.151002f, 0.271553f, 0.193871f, 0.246955f, 0.187075f, + 0.391039f, 0.611891f, 0.434803f, 0.658882f, 0.438641f, 0.680683f, 0.394766f, 0.686125f, + 0.320962f, 0.677959f, 0.325318f, 0.656224f, 0.369913f, 0.610196f, 0.364838f, 0.684445f, + 0.789046f, 0.233323f, 0.760215f, 0.193244f, 0.783193f, 0.187449f, 0.809631f, 0.233887f, + 0.246955f, 0.187075f, 0.271553f, 0.193871f, 0.241255f, 0.236977f, 0.219168f, 0.237388f, + 0.391747f, 0.862097f, 0.401605f, 0.841460f, 0.438797f, 0.870229f, 0.432388f, 0.894943f, + 0.315867f, 0.868209f, 0.354026f, 0.840297f, 0.363377f, 0.861308f, 0.321637f, 0.893225f, + 0.438641f, 0.680683f, 0.452955f, 0.700023f, 0.435018f, 0.718280f, 0.394766f, 0.686125f, + 0.323658f, 0.715731f, 0.306136f, 0.696976f, 0.320962f, 0.677959f, 0.364838f, 0.684445f, + 0.433669f, 0.729661f, 0.384658f, 0.710299f, 0.394766f, 0.686125f, 0.435018f, 0.718280f, + 0.364838f, 0.684445f, 0.374400f, 0.708969f, 0.324726f, 0.727177f, 0.323658f, 0.715731f, + 0.410995f, 0.747662f, 0.384658f, 0.710299f, 0.433669f, 0.729661f, 0.427812f, 0.742828f, + 0.324726f, 0.727177f, 0.374400f, 0.708969f, 0.347028f, 0.745816f, 0.330270f, 0.740536f, + 0.418086f, 0.784946f, 0.384657f, 0.795423f, 0.384658f, 0.710299f, 0.410995f, 0.747662f, + 0.374400f, 0.708969f, 0.372270f, 0.794472f, 0.338952f, 0.783073f, 0.347028f, 0.745816f, + 0.401605f, 0.841460f, 0.384657f, 0.795423f, 0.418086f, 0.784946f, 0.431333f, 0.817535f, + 0.338952f, 0.783073f, 0.372270f, 0.794472f, 0.354026f, 0.840297f, 0.324790f, 0.815460f, + 0.438797f, 0.870229f, 0.401605f, 0.841460f, 0.431333f, 0.817535f, 0.457832f, 0.840040f, + 0.324790f, 0.815460f, 0.354026f, 0.840297f, 0.315867f, 0.868209f, 0.297562f, 0.837358f, + 0.809631f, 0.233887f, 0.816266f, 0.203086f, 0.825107f, 0.209762f, 0.829287f, 0.219562f, + 0.199767f, 0.214827f, 0.209828f, 0.206161f, 0.219168f, 0.237388f, 0.199067f, 0.222464f, + 0.809631f, 0.233887f, 0.783193f, 0.187449f, 0.802192f, 0.184609f, 0.816266f, 0.203086f, + 0.226485f, 0.183086f, 0.246955f, 0.187075f, 0.219168f, 0.237388f, 0.209828f, 0.206161f, + 0.783193f, 0.187449f, 0.796021f, 0.176969f, 0.802192f, 0.184609f, + 0.226485f, 0.183086f, 0.233625f, 0.175620f, 0.246955f, 0.187075f, + 0.457832f, 0.840040f, 0.431333f, 0.817535f, 0.448505f, 0.804621f, 0.473386f, 0.824700f, + 0.307886f, 0.802031f, 0.324790f, 0.815460f, 0.297562f, 0.837358f, 0.282357f, 0.821525f, + 0.431333f, 0.817535f, 0.418086f, 0.784946f, 0.435868f, 0.779569f, 0.448505f, 0.804621f, + 0.321237f, 0.777208f, 0.338952f, 0.783073f, 0.324790f, 0.815460f, 0.307886f, 0.802031f, + 0.418086f, 0.784946f, 0.410995f, 0.747662f, 0.423718f, 0.754191f, 0.435868f, 0.779569f, + 0.334089f, 0.752045f, 0.347028f, 0.745816f, 0.338952f, 0.783073f, 0.321237f, 0.777208f, + 0.410995f, 0.747662f, 0.427812f, 0.742828f, 0.437950f, 0.749777f, 0.423718f, 0.754191f, + 0.319919f, 0.747250f, 0.330270f, 0.740536f, 0.347028f, 0.745816f, 0.334089f, 0.752045f, + 0.427812f, 0.742828f, 0.433669f, 0.729661f, 0.445392f, 0.731997f, 0.437950f, 0.749777f, + 0.312907f, 0.729222f, 0.324726f, 0.727177f, 0.330270f, 0.740536f, 0.319919f, 0.747250f, + 0.433669f, 0.729661f, 0.435018f, 0.718280f, 0.440995f, 0.724383f, 0.445392f, 0.731997f, + 0.317510f, 0.721697f, 0.323658f, 0.715731f, 0.324726f, 0.727177f, 0.312907f, 0.729222f, + 0.435018f, 0.718280f, 0.452955f, 0.700023f, 0.455277f, 0.713731f, 0.440995f, 0.724383f, + 0.303460f, 0.710657f, 0.306136f, 0.696976f, 0.323658f, 0.715731f, 0.317510f, 0.721697f, + 0.501231f, 0.844356f, 0.457832f, 0.840040f, 0.473386f, 0.824700f, 0.512485f, 0.828811f, + 0.282357f, 0.821525f, 0.297562f, 0.837358f, 0.253846f, 0.840502f, 0.242975f, 0.824574f, + 0.555495f, 0.826352f, 0.501231f, 0.844356f, 0.512485f, 0.828811f, 0.550942f, 0.811814f, + 0.242975f, 0.824574f, 0.253846f, 0.840502f, 0.199850f, 0.820889f, 0.204839f, 0.806417f, + 0.568148f, 0.787367f, 0.555495f, 0.826352f, 0.550942f, 0.811814f, 0.552139f, 0.787682f, + 0.204839f, 0.806417f, 0.199850f, 0.820889f, 0.188269f, 0.781375f, 0.204331f, 0.782156f, + 0.542850f, 0.755753f, 0.568148f, 0.787367f, 0.552139f, 0.787682f, 0.539407f, 0.764539f, + 0.204331f, 0.782156f, 0.188269f, 0.781375f, 0.214575f, 0.750414f, 0.217774f, 0.759319f, + 0.505666f, 0.730944f, 0.542850f, 0.755753f, 0.539407f, 0.764539f, 0.508439f, 0.743135f, + 0.217774f, 0.759319f, 0.214575f, 0.750414f, 0.252524f, 0.726592f, 0.249419f, 0.738732f, + 0.452955f, 0.700023f, 0.505666f, 0.730944f, 0.508439f, 0.743135f, 0.455277f, 0.713731f, + 0.249419f, 0.738732f, 0.252524f, 0.726592f, 0.306136f, 0.696976f, 0.303460f, 0.710657f, + 0.437950f, 0.749777f, 0.445392f, 0.731997f, 0.470841f, 0.748408f, 0.454776f, 0.761665f, + 0.286960f, 0.745020f, 0.312907f, 0.729222f, 0.319919f, 0.747250f, 0.302729f, 0.758742f, + 0.454776f, 0.761665f, 0.470841f, 0.748408f, 0.488870f, 0.770464f, 0.475403f, 0.783904f, + 0.268291f, 0.766661f, 0.286960f, 0.745020f, 0.302729f, 0.758742f, 0.281439f, 0.780511f, + 0.475403f, 0.783904f, 0.488870f, 0.770464f, 0.503673f, 0.787562f, 0.494476f, 0.802470f, + 0.252972f, 0.783410f, 0.268291f, 0.766661f, 0.281439f, 0.780511f, 0.261790f, 0.798626f, + 0.494476f, 0.802470f, 0.503673f, 0.787562f, 0.518562f, 0.791602f, 0.516802f, 0.807339f, + 0.237920f, 0.787045f, 0.252972f, 0.783410f, 0.261790f, 0.798626f, 0.239243f, 0.802891f, + 0.512485f, 0.828811f, 0.473386f, 0.824700f, 0.494476f, 0.802470f, 0.516802f, 0.807339f, + 0.261790f, 0.798626f, 0.282357f, 0.821525f, 0.242975f, 0.824574f, 0.239243f, 0.802891f, + 0.448505f, 0.804621f, 0.475403f, 0.783904f, 0.494476f, 0.802470f, 0.473386f, 0.824700f, + 0.261790f, 0.798626f, 0.281439f, 0.780511f, 0.307886f, 0.802031f, 0.282357f, 0.821525f, + 0.448505f, 0.804621f, 0.435868f, 0.779569f, 0.454776f, 0.761665f, 0.475403f, 0.783904f, + 0.302729f, 0.758742f, 0.321237f, 0.777208f, 0.307886f, 0.802031f, 0.281439f, 0.780511f, + 0.437950f, 0.749777f, 0.454776f, 0.761665f, 0.435868f, 0.779569f, 0.423718f, 0.754191f, + 0.321237f, 0.777208f, 0.302729f, 0.758742f, 0.319919f, 0.747250f, 0.334089f, 0.752045f, + 0.440995f, 0.724383f, 0.455277f, 0.713731f, 0.470841f, 0.748408f, 0.445392f, 0.731997f, + 0.286960f, 0.745020f, 0.303460f, 0.710657f, 0.317510f, 0.721697f, 0.312907f, 0.729222f, + 0.508439f, 0.743135f, 0.488870f, 0.770464f, 0.470841f, 0.748408f, 0.455277f, 0.713731f, + 0.286960f, 0.745020f, 0.268291f, 0.766661f, 0.249419f, 0.738732f, 0.303460f, 0.710657f, + 0.539407f, 0.764539f, 0.503673f, 0.787562f, 0.488870f, 0.770464f, 0.508439f, 0.743135f, + 0.268291f, 0.766661f, 0.252972f, 0.783410f, 0.217774f, 0.759319f, 0.249419f, 0.738732f, + 0.552139f, 0.787682f, 0.518562f, 0.791602f, 0.503673f, 0.787562f, 0.539407f, 0.764539f, + 0.252972f, 0.783410f, 0.237920f, 0.787045f, 0.204331f, 0.782156f, 0.217774f, 0.759319f, + 0.550942f, 0.811814f, 0.516802f, 0.807339f, 0.518562f, 0.791602f, 0.552139f, 0.787682f, + 0.237920f, 0.787045f, 0.239243f, 0.802891f, 0.204839f, 0.806417f, 0.204331f, 0.782156f, + 0.512485f, 0.828811f, 0.516802f, 0.807339f, 0.550942f, 0.811814f, + 0.204839f, 0.806417f, 0.239243f, 0.802891f, 0.242975f, 0.824574f, + 0.508270f, 0.697693f, 0.434803f, 0.658882f, 0.484068f, 0.628776f, 0.543385f, 0.683538f, + 0.276936f, 0.625067f, 0.325318f, 0.656224f, 0.250811f, 0.693249f, 0.216123f, 0.678120f, + 0.563786f, 0.739211f, 0.508270f, 0.697693f, 0.543385f, 0.683538f, 0.581052f, 0.726933f, + 0.216123f, 0.678120f, 0.250811f, 0.693249f, 0.194086f, 0.733241f, 0.177176f, 0.720426f, + 0.619962f, 0.791615f, 0.563786f, 0.739211f, 0.581052f, 0.726933f, 0.616701f, 0.759965f, + 0.177176f, 0.720426f, 0.194086f, 0.733241f, 0.136063f, 0.784093f, 0.140379f, 0.752377f, + 0.707492f, 0.759884f, 0.619962f, 0.791615f, 0.616701f, 0.759965f, 0.660647f, 0.741167f, + 0.140379f, 0.752377f, 0.136063f, 0.784093f, 0.049526f, 0.748824f, 0.097038f, 0.732052f, + 0.745511f, 0.652100f, 0.707492f, 0.759884f, 0.660647f, 0.741167f, 0.677256f, 0.670436f, + 0.097038f, 0.732052f, 0.049526f, 0.748824f, 0.019409f, 0.639749f, 0.083564f, 0.662038f, + 0.740843f, 0.572428f, 0.745511f, 0.652100f, 0.677256f, 0.670436f, 0.671403f, 0.592656f, + 0.083564f, 0.662038f, 0.019409f, 0.639749f, 0.033664f, 0.564403f, 0.092820f, 0.589862f, + 0.677256f, 0.670436f, 0.543385f, 0.683538f, 0.484068f, 0.628776f, 0.671403f, 0.592656f, + 0.276936f, 0.625067f, 0.216123f, 0.678120f, 0.083564f, 0.662038f, 0.092820f, 0.589862f, + 0.677256f, 0.670436f, 0.660647f, 0.741167f, 0.581052f, 0.726933f, 0.543385f, 0.683538f, + 0.177176f, 0.720426f, 0.097038f, 0.732052f, 0.083564f, 0.662038f, 0.216123f, 0.678120f, + 0.660647f, 0.741167f, 0.616701f, 0.759965f, 0.581052f, 0.726933f, + 0.177176f, 0.720426f, 0.140379f, 0.752377f, 0.097038f, 0.732052f, + 0.842355f, 0.195160f, 0.829287f, 0.219562f, 0.834578f, 0.206879f, 0.834705f, 0.206959f, + 0.033664f, 0.564403f, 0.051216f, 0.522659f, 0.145041f, 0.562595f, 0.092820f, 0.589862f, + 0.620420f, 0.565675f, 0.671403f, 0.592656f, 0.484068f, 0.628776f, 0.498072f, 0.552315f, + 0.276936f, 0.625067f, 0.092820f, 0.589862f, 0.145041f, 0.562595f, 0.264218f, 0.550140f, + 0.391039f, 0.611891f, 0.498072f, 0.552315f, 0.484068f, 0.628776f, 0.434803f, 0.658882f, + 0.276936f, 0.625067f, 0.264218f, 0.550140f, 0.369913f, 0.610196f, 0.325318f, 0.656224f +}; + #define VERT_MARK 1 #define EDGE_ORIG 1 @@ -496,21 +1025,33 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_vert_flag_enable(bm, eva[a], VERT_MARK); } + int uvi = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); for (a = 0; a < 20; a++) { - BMFace *eftemp; + BMFace *f; BMVert *v1, *v2, *v3; v1 = eva[icoface[a][0]]; v2 = eva[icoface[a][1]]; v3 = eva[icoface[a][2]]; - eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP); + f = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP); - BM_ITER_ELEM (l, &liter, eftemp, BM_LOOPS_OF_FACE) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_edge_flag_enable(bm, l->e, EDGE_MARK); } - BMO_face_flag_enable(bm, eftemp, FACE_MARK); + /* Set the UVs here, the iteration order of the faces is not guaranteed, + * so it's best to set the UVs right after the face is created. */ + if (calc_uvs) { + int loop_index; + BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] = icouvs[uvi][0]; + luv->uv[1] = icouvs[uvi][1]; + uvi++; + } + } } if (subdiv > 1) { @@ -530,29 +1071,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &bmop); } - if (calc_uvs) { - BMFace *f; - BMIter fiter; - - /* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices - * being tagged. */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - bool valid = true; - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (!BMO_vert_flag_test(bm, l->v, VERT_MARK)) { - valid = false; - break; - } - } - if (valid) { - BMO_face_flag_enable(bm, f, FACE_MARK); - } - } - - BM_mesh_calc_uvs_sphere(bm, FACE_MARK); - } /* must transform after because of sphere subdivision */ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { @@ -564,7 +1083,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } -static void bm_mesh_calc_uvs_sphere_face(BMFace *f, float mat_rot[3][3], const int cd_loop_uv_offset) +static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset) { float *uvs[4]; BMLoop *l; @@ -574,12 +1093,42 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, float mat_rot[3][3], const i BLI_assert(f->len <= 4); + /* If face has 3 vertices, it's a polar face, in which case we need to + * compute a nearbye to determine its latitude. */ + float avgx = 0.0f, avgy = 0.0f; + BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) { + if (f->len == 3) { + avgx += l->v->co[0]; + avgy += l->v->co[1]; + } + } + avgx /= 3.0f; + avgy /= 3.0f; + BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - float vco[3]; + float x = l->v->co[0]; + float y = l->v->co[1]; + float z = l->v->co[2]; + float len = len_v3(l->v->co); + + /* Use neigboring point to compute angle for poles. */ + float theta; + if (f->len == 3 && fabsf(x) < 0.0001f && fabsf(y) < 0.0001f) { + theta = atan2f(avgy, avgx); + } + else { + theta = atan2f(y, x); + } + + /* Shift borderline coordinates to the left. */ + if (fabsf(theta - M_PI) < 0.0001f) { + theta = -M_PI; + } - mul_v3_m3v3(vco, mat_rot, l->v->co); - map_to_sphere(&luv->uv[0], &luv->uv[1], vco[0], vco[1], vco[2]); + float phi = saacos(z / len); + luv->uv[0] = 0.5f + theta / ((float)M_PI * 2); + luv->uv[1] = 1.0f - phi / (float)M_PI; uvs[loop_index] = luv->uv; } @@ -615,21 +1164,38 @@ void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - /* We apply a 'magic' rotationto vcos before mapping them to sphere, - * those values seem to give best results for both ico and uv sphere projections. */ - float mat_rot[3][3]; - const float axis[3] = {0.806f, 0.329f, 0.491f}; - const float angle = DEG2RADF(120.0f); + BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */ - axis_angle_to_mat3(mat_rot, axis, angle); + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (!BMO_face_flag_test(bm, f, oflag)) + continue; - BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */ + bm_mesh_calc_uvs_sphere_face(f, cd_loop_uv_offset); + } + + BMIter iter2; + BMLoop* l; + int loop_index; + float minx = 1.0f; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) continue; + BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->uv[0] < minx) { + minx = luv->uv[0]; + } + } + } - bm_mesh_calc_uvs_sphere_face(f, mat_rot, cd_loop_uv_offset); + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (!BMO_face_flag_test(bm, f, oflag)) + continue; + BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] -= minx; + } } } @@ -640,6 +1206,7 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) int i; BMO_slot_mat4_get(op->slots_in, "matrix", mat); + const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); for (i = 0; i < monkeynv; i++) { float v[3]; @@ -666,20 +1233,43 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) mul_m4_v3(mat, tv[i]->co); } + int uvi = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); for (i = 0; i < monkeynf; i++) { - BM_face_create_quad_tri(bm, + BMFace* temp1 = BM_face_create_quad_tri(bm, tv[monkeyf[i][0] + i - monkeyo], tv[monkeyf[i][1] + i - monkeyo], tv[monkeyf[i][2] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL, NULL, BM_CREATE_NOP); - BM_face_create_quad_tri(bm, + BMFace* temp2 = BM_face_create_quad_tri(bm, tv[monkeynv + monkeyf[i][2] + i - monkeyo], tv[monkeynv + monkeyf[i][1] + i - monkeyo], tv[monkeynv + monkeyf[i][0] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL, NULL, BM_CREATE_NOP); + + /* Set the UVs here, the iteration order of the faces is not guaranteed, + * so it's best to set the UVs right after the face is created. */ + if(calc_uvs) { + BMLoop* l; + BMIter liter; + int loop_index; + BM_ITER_ELEM_INDEX (l, &liter, temp1, BM_LOOPS_OF_FACE, loop_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] = monkeyuvs[uvi*2 + 0]; + luv->uv[1] = monkeyuvs[uvi*2 + 1]; + uvi++; + } + BM_ITER_ELEM_INDEX (l, &liter, temp2, BM_LOOPS_OF_FACE, loop_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] = monkeyuvs[uvi*2 + 0]; + luv->uv[1] = monkeyuvs[uvi*2 + 1]; + uvi++; + } + + } } MEM_freeN(tv); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index d97fb55af9c..ae43c0a69d2 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -52,23 +52,14 @@ static const char *bc_get_joint_name(T *node) ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) : - import_settings(import_settings), + TransformReader(conv), + scene(sce), unit_converter(conv), - TransformReader(conv), - scene(sce), + import_settings(import_settings), empty(NULL), mesh_importer(mesh) { } -void ArmatureImporter::clear_extended_boneset() -{ - for (std::map<std::string, BoneExtended *>::iterator it = extended_bones.begin(); it != extended_bones.end(); ++it) { - if (it->second != NULL) - delete it->second; - } - extended_bones.clear(); -} - ArmatureImporter::~ArmatureImporter() { // free skin controller data if we forget to do this earlier @@ -76,7 +67,6 @@ ArmatureImporter::~ArmatureImporter() for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { it->second.free(); } - clear_extended_boneset(); } #if 0 @@ -156,8 +146,8 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon if (parent) bone->parent = parent; float loc[3], size[3], rot[3][3]; - - BoneExtended &be = add_bone_extended(bone, node, totchild, layer_labels); + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(arm); + BoneExtended &be = add_bone_extended(bone, node, totchild, layer_labels, extended_bones); int layer = be.get_bone_layers(); if (layer) bone->layer = layer; arm->layer |= layer; // ensure that all populated bone layers are visible after import @@ -205,7 +195,6 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon chain_length = cl; } - bone->length = len_v3v3(bone->head, bone->tail); joint_by_uid[node->getUniqueId()] = node; finished_joints.push_back(node); @@ -221,43 +210,49 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon * tail locations for the affected bones (nodes which don't have any connected child) * Hint: The extended_bones set gets populated in ArmatureImporter::create_bone **/ -void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone, bool fix_orientation) +void ArmatureImporter::fix_leaf_bone_hierarchy(bArmature *armature, Bone *bone, bool fix_orientation) { if (bone == NULL) return; if (bc_is_leaf_bone(bone)) { - + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); BoneExtended *be = extended_bones[bone->name]; - if (be == NULL || !be->has_tail()) { + EditBone *ebone = bc_get_edit_bone(armature, bone->name); + fix_leaf_bone(armature, ebone, be, fix_orientation); + } - /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ - float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + fix_leaf_bone_hierarchy(armature, child, fix_orientation); + } +} - EditBone *ebone = bc_get_edit_bone(armature, bone->name); - float vec[3]; +void ArmatureImporter::fix_leaf_bone(bArmature *armature, EditBone *ebone, BoneExtended *be , bool fix_orientation) +{ + if (be == NULL || !be->has_tail()) { - if (ebone->parent != NULL && fix_orientation) { - EditBone *parent = ebone->parent; - sub_v3_v3v3(vec, ebone->head, parent->head); - if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) - { - sub_v3_v3v3(vec, parent->tail, parent->head); - } - } - else { - vec[2] = 0.1f; - sub_v3_v3v3(vec, ebone->tail, ebone->head); - } + /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ + float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; - normalize_v3_v3(vec, vec); - mul_v3_fl(vec, leaf_length); - add_v3_v3v3(ebone->tail, ebone->head, vec); + + float vec[3]; + + if (fix_orientation && ebone->parent != NULL) { + EditBone *parent = ebone->parent; + sub_v3_v3v3(vec, ebone->head, parent->head); + if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) + { + sub_v3_v3v3(vec, parent->tail, parent->head); + } + } + else { + vec[2] = 0.1f; + sub_v3_v3v3(vec, ebone->tail, ebone->head); } - } - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - fix_leaf_bones(armature, child, fix_orientation); + normalize_v3_v3(vec, vec); + mul_v3_fl(vec, leaf_length); + add_v3_v3v3(ebone->tail, ebone->head, vec); } } @@ -280,6 +275,7 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); BoneExtended *dominant_child = NULL; int maxlen = 0; Bone *child; @@ -445,11 +441,10 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm) return armature_joints.back(); } #endif -Object *ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms) +void ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms) { std::vector<COLLADAFW::Node *>::iterator ri; std::vector<std::string> layer_labels; - Object *ob_arm = NULL; //if there is an armature created for root_joint next root_joint for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { @@ -470,15 +465,23 @@ Object *ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms) continue; } - clear_extended_boneset(); - ED_armature_to_edit(armature); armature->layer = 0; // layer is set according to imported bone set in create_bone() create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels); + if (this->import_settings->find_chains) { + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + } /* exit armature edit mode to populate the Armature object */ + ED_armature_from_edit(armature); + ED_armature_edit_free(armature); + + ED_armature_to_edit(armature); + + fix_leaf_bone_hierarchy(armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; + ED_armature_from_edit(armature); ED_armature_edit_free(armature); @@ -489,7 +492,6 @@ Object *ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms) DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA); } - return ob_arm; } Object *ArmatureImporter::create_armature_bones(SkinInfo& skin) @@ -584,8 +586,6 @@ Object *ArmatureImporter::create_armature_bones(SkinInfo& skin) bArmature * armature = (bArmature *)ob_arm->data; ED_armature_to_edit(armature); - clear_extended_boneset(); - totbone = 0; // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row @@ -615,6 +615,14 @@ Object *ArmatureImporter::create_armature_bones(SkinInfo& skin) ED_armature_from_edit(armature); ED_armature_edit_free(armature); + ED_armature_to_edit(armature); + if (this->import_settings->find_chains) { + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + } + fix_leaf_bone_hierarchy(armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); + ED_armature_from_edit(armature); + ED_armature_edit_free(armature); + DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA); return ob_arm; @@ -756,11 +764,6 @@ void ArmatureImporter::make_armatures(bContext *C, std::vector<Object *> &object /* and step back to edit mode to fix the leaf nodes */ ED_armature_to_edit(armature); - if (this->import_settings->find_chains) - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - - fix_leaf_bones(armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); - fix_parent_connect(armature, (Bone *)armature->bonebase.first); ED_armature_from_edit(armature); @@ -952,7 +955,7 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint) return found; } -BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, int sibcount, std::vector<std::string> &layer_labels) +BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, int sibcount, std::vector<std::string> &layer_labels, BoneExtensionMap &extended_bones) { BoneExtended *be = new BoneExtended(bone); extended_bones[bone->name] = be; diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index 524c524c9c9..17173f157e5 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -68,8 +68,7 @@ private: // std::map<int, JointData> joint_index_to_joint_info_map; // std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map; - - std::map<std::string, BoneExtended *> extended_bones; + BoneExtensionManager bone_extension_manager; // int bone_direction_row; // XXX not used float leaf_bone_length; int totbone; @@ -108,16 +107,15 @@ private: int create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild, float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels); - BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, int sibcount, std::vector<std::string> &layer_labels); - void clear_extended_boneset(); + BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, int sibcount, std::vector<std::string> &layer_labels, BoneExtensionMap &extended_bones); - void fix_leaf_bones(bArmature *armature, Bone *bone, bool fix_orientation); + void fix_leaf_bone_hierarchy(bArmature *armature, Bone *bone, bool fix_orientation); + void fix_leaf_bone(bArmature *armature, EditBone *ebone, BoneExtended *be, bool fix_orientation); void fix_parent_connect(bArmature *armature, Bone *bone); void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length); void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]); - #if 0 void set_leaf_bone_shapes(Object *ob_arm); void set_euler_rotmode(); @@ -132,7 +130,7 @@ private: #endif Object *create_armature_bones(SkinInfo& skin); - Object *create_armature_bones(std::vector<Object *> &arm_objs); + void create_armature_bones(std::vector<Object *> &arm_objs); /** TagsMap typedef for uid_tags_map. */ typedef std::map<std::string, ExtraTags*> TagsMap; diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index abe5130b9c1..2efa8b21d81 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -412,6 +412,38 @@ int bc_set_layer(int bitfield, int layer, bool enable) return bitfield; } +/* + | This method creates a new extension map when needed. + | Note: The ~BoneExtensionManager destructor takes care + | to delete the created maps when the manager is removed. +*/ +BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature) +{ + std::string key = armature->id.name; + BoneExtensionMap *result = extended_bone_maps[key]; + if (result == NULL) + { + result = new BoneExtensionMap(); + extended_bone_maps[key] = result; + } + return *result; +} + +BoneExtensionManager::~BoneExtensionManager() +{ + std::map<std::string, BoneExtensionMap *>::iterator map_it; + for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) + { + BoneExtensionMap *extended_bones = map_it->second; + for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) { + if (ext_it->second != NULL) + delete ext_it->second; + } + extended_bones->clear(); + delete extended_bones; + } +} + /** * BoneExtended is a helper class needed for the Bone chain finder * See ArmatureImporter::fix_leaf_bones() diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index ee371f7959e..7fdbef3b6cb 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -153,5 +153,24 @@ public: int get_use_connect(); }; +/* a map to store bone extension maps +| std:string : an armature name +| BoneExtended * : a map that contains extra data for bones +*/ +typedef std::map<std::string, BoneExtended *> BoneExtensionMap; + +/* +| A class to organise bone extendion data for multiple Armatures. +| this is needed for the case where a Collada file contains 2 or more +| separate armatures. +*/ +class BoneExtensionManager { +private: + std::map<std::string, BoneExtensionMap *> extended_bone_maps; + +public: + BoneExtensionMap &getExtensionMap(bArmature *armature); + ~BoneExtensionManager(); +}; #endif diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 2a9f9c830f4..3725590c188 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -461,6 +461,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) bool enter_editmode; unsigned int layer; bool was_editmode; + const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs"); WM_operator_view3d_unit_defaults(C, op); ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &layer, NULL); @@ -471,9 +472,13 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) em = BKE_editmesh_from_object(obedit); + if (calc_uvs) { + ED_mesh_uv_texture_ensure(obedit->data, NULL); + } + if (!EDBM_op_call_and_selectf( em, op, "verts.out", false, - "create_monkey matrix=%m4", mat)) + "create_monkey matrix=%m4 calc_uvs=%b", mat, calc_uvs)) { return OPERATOR_CANCELLED; } @@ -498,6 +503,8 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot) ED_object_add_unit_props(ot); ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* props */ + ED_object_add_mesh_props(ot); ED_object_add_generic_props(ot, true); } diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 357259731d2..d0cb7fd12a9 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -91,3 +91,6 @@ void ED_operatortypes_physics(void) void ED_keymap_physics(wmKeyConfig *UNUSED(keyconf)) { } + + + diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index b55330602e9..2cf0a16f236 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -503,7 +503,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bGPDbrush *brush = BKE_gpencil_brush_getactive(scene->toolsettings); if (brush) { - CTX_data_pointer_set(result, NULL, &RNA_GPencilBrush, brush); + CTX_data_pointer_set(result, &scene->id, &RNA_GPencilBrush, brush); return 1; } } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index a65733ce667..e95ca32048d 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -62,7 +62,7 @@ typedef struct TreeElement { #define TREESTORE_ID_TYPE(_id) \ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_GD, ID_LS) || \ - ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF)) /* Only in 'blendfile' mode ... :/ */ + ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL)) /* Only in 'blendfile' mode ... :/ */ /* TreeElement->flag */ #define TE_ACTIVE 1 diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 059b384a9e2..a5c60248bf1 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -90,6 +90,10 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() +if(WITH_MOD_SMOKE) + add_definitions(-DWITH_SMOKE) +endif() + if(WITH_LEGACY_DEPSGRAPH) add_definitions(-DWITH_LEGACY_DEPSGRAPH) endif() diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 0a7dc9012f9..8ff68868286 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -6727,9 +6727,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* smoke debug render */ -#ifdef SMOKE_DEBUG_VELOCITY - draw_smoke_velocity(smd->domain, ob); -#endif + if (!render_override && sds->draw_velocity) { + draw_smoke_velocity(sds, viewnormal); + } + #ifdef SMOKE_DEBUG_HEAT draw_smoke_heat(smd->domain, ob); #endif diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 75ba8bc15d9..9cfcd6cef05 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -41,6 +41,8 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BKE_DerivedMesh.h" + #include "smoke_API.h" #include "BIF_gl.h" @@ -112,6 +114,63 @@ typedef struct VolumeSlicer { float (*verts)[3]; } VolumeSlicer; +/* *************************** Axis Aligned Slicing ************************** */ + +static void create_single_slice(VolumeSlicer *slicer, const float depth, + const int axis, const int idx) +{ + const float vertices[3][4][3] = { + { + { depth, slicer->min[1], slicer->min[2] }, + { depth, slicer->max[1], slicer->min[2] }, + { depth, slicer->max[1], slicer->max[2] }, + { depth, slicer->min[1], slicer->max[2] } + }, + { + { slicer->min[0], depth, slicer->min[2] }, + { slicer->min[0], depth, slicer->max[2] }, + { slicer->max[0], depth, slicer->max[2] }, + { slicer->max[0], depth, slicer->min[2] } + }, + { + { slicer->min[0], slicer->min[1], depth }, + { slicer->min[0], slicer->max[1], depth }, + { slicer->max[0], slicer->max[1], depth }, + { slicer->max[0], slicer->min[1], depth } + } + }; + + copy_v3_v3(slicer->verts[idx + 0], vertices[axis][0]); + copy_v3_v3(slicer->verts[idx + 1], vertices[axis][1]); + copy_v3_v3(slicer->verts[idx + 2], vertices[axis][2]); + copy_v3_v3(slicer->verts[idx + 3], vertices[axis][0]); + copy_v3_v3(slicer->verts[idx + 4], vertices[axis][2]); + copy_v3_v3(slicer->verts[idx + 5], vertices[axis][3]); +} + +static void create_axis_aligned_slices(VolumeSlicer *slicer, const int num_slices, + const float view_dir[3], const int axis) +{ + float depth, slice_size = slicer->size[axis] / num_slices; + + /* always process slices in back to front order! */ + if (view_dir[axis] > 0.0f) { + depth = slicer->min[axis]; + } + else { + depth = slicer->max[axis]; + slice_size = -slice_size; + } + + int count = 0; + for (int slice = 0; slice < num_slices; slice++) { + create_single_slice(slicer, depth, axis, count); + + count += 6; + depth += slice_size; + } +} + /* *************************** View Aligned Slicing ************************** */ /* Code adapted from: @@ -323,7 +382,7 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture GPU_shader_uniform_texture(shader, spec_location, tex_spec); } else { - float density_scale = 10.0f; + float density_scale = 10.0f * sds->display_thickness; GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx); GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale); @@ -432,8 +491,25 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, /* setup slicing information */ - const int max_slices = 256; - const int max_points = max_slices * 12; + const bool view_aligned = (sds->slice_method == MOD_SMOKE_SLICE_VIEW_ALIGNED); + int max_slices, max_points, axis = 0; + + if (view_aligned) { + max_slices = max_iii(sds->res[0], sds->res[1], sds->res[2]) * sds->slice_per_voxel; + max_points = max_slices * 12; + } + else { + if (sds->axis_slice_method == AXIS_SLICE_FULL) { + axis = axis_dominant_v3_single(viewnormal); + max_slices = sds->res[axis] * sds->slice_per_voxel; + } + else { + axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewnormal) : sds->slice_axis - 1; + max_slices = 1; + } + + max_points = max_slices * 6; + } VolumeSlicer slicer; copy_v3_v3(slicer.min, min); @@ -441,7 +517,22 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, copy_v3_v3(slicer.size, size); slicer.verts = MEM_mallocN(sizeof(float) * 3 * max_points, "smoke_slice_vertices"); - const int num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal); + int num_points; + + if (view_aligned) { + num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal); + } + else { + num_points = max_points; + + if (sds->axis_slice_method == AXIS_SLICE_FULL) { + create_axis_aligned_slices(&slicer, max_slices, viewnormal, axis); + } + else { + const float depth = (sds->slice_depth - 0.5f) * size[axis]; + create_single_slice(&slicer, depth, axis, 0); + } + } /* setup buffer and draw */ @@ -481,61 +572,193 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, } } -#ifdef SMOKE_DEBUG_VELOCITY -void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob) +#ifdef WITH_SMOKE +static void add_tri(float (*verts)[3], float(*colors)[3], int *offset, + float p1[3], float p2[3], float p3[3], float rgb[3]) { - float x, y, z; - float x0, y0, z0; - int *base_res = domain->base_res; - int *res = domain->res; - int *res_min = domain->res_min; - int *res_max = domain->res_max; - float *vel_x = smoke_get_velocity_x(domain->fluid); - float *vel_y = smoke_get_velocity_y(domain->fluid); - float *vel_z = smoke_get_velocity_z(domain->fluid); + copy_v3_v3(verts[*offset + 0], p1); + copy_v3_v3(verts[*offset + 1], p2); + copy_v3_v3(verts[*offset + 2], p3); - float min[3]; - float *cell_size = domain->cell_size; - float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f; - float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + copy_v3_v3(colors[*offset + 0], rgb); + copy_v3_v3(colors[*offset + 1], rgb); + copy_v3_v3(colors[*offset + 2], rgb); - glLineWidth(1.0f); + *offset += 3; +} + +static void add_needle(float (*verts)[3], float (*colors)[3], float center[3], + float dir[3], float scale, float voxel_size, int *offset) +{ + float len = len_v3(dir); + + float rgb[3]; + weight_to_rgb(rgb, len); + + if (len != 0.0f) { + mul_v3_fl(dir, 1.0f / len); + len *= scale; + } + + len *= voxel_size; + + float corners[4][3] = { + { 0.0f, 0.2f, -0.5f }, + { -0.2f * 0.866f, -0.2f * 0.5f, -0.5f }, + { 0.2f * 0.866f, -0.2f * 0.5f, -0.5f }, + { 0.0f, 0.0f, 0.5f } + }; + + const float up[3] = { 0.0f, 0.0f, 1.0f }; + float rot[3][3]; + + rotation_between_vecs_to_mat3(rot, up, dir); + transpose_m3(rot); + + for (int i = 0; i < 4; i++) { + mul_m3_v3(rot, corners[i]); + mul_v3_fl(corners[i], len); + add_v3_v3(corners[i], center); + } + + add_tri(verts, colors, offset, corners[0], corners[1], corners[2], rgb); + add_tri(verts, colors, offset, corners[0], corners[1], corners[3], rgb); + add_tri(verts, colors, offset, corners[1], corners[2], corners[3], rgb); + add_tri(verts, colors, offset, corners[2], corners[0], corners[3], rgb); +} + +static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3], + float dir[3], float scale, float voxel_size, int *offset) +{ + const float len = len_v3(dir); + + float rgb[3]; + weight_to_rgb(rgb, len); + + copy_v3_v3(colors[(*offset)], rgb); + copy_v3_v3(verts[(*offset)++], center); + + mul_v3_fl(dir, scale * voxel_size); + add_v3_v3(center, dir); + + copy_v3_v3(colors[(*offset)], rgb); + copy_v3_v3(verts[(*offset)++], center); +} + +typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*); +#endif /* WITH_SMOKE */ + +void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) +{ +#ifdef WITH_SMOKE + const float *vel_x = smoke_get_velocity_x(domain->fluid); + const float *vel_y = smoke_get_velocity_y(domain->fluid); + const float *vel_z = smoke_get_velocity_z(domain->fluid); + + if (ELEM(NULL, vel_x, vel_y, vel_z)) { + return; + } + + const int *base_res = domain->base_res; + const int *res = domain->res; + const int *res_min = domain->res_min; + + int res_max[3]; + copy_v3_v3_int(res_max, domain->res_max); + + const float *cell_size = domain->cell_size; + const float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.0f; /* set first position so that it doesn't jump when domain moves */ - x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size); - y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size); - z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size); - if (x0 < res_min[0]) x0 += step_size; - if (y0 < res_min[1]) y0 += step_size; - if (z0 < res_min[2]) z0 += step_size; - add_v3_v3v3(min, domain->p0, domain->obj_shift_f); + float xyz[3] = { + res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size), + res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size), + res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size) + }; - for (x = floor(x0); x < res_max[0]; x += step_size) - for (y = floor(y0); y < res_max[1]; y += step_size) - for (z = floor(z0); z < res_max[2]; z += step_size) { + if (xyz[0] < res_min[0]) xyz[0] += step_size; + if (xyz[1] < res_min[1]) xyz[1] += step_size; + if (xyz[2] < res_min[2]) xyz[2] += step_size; + + float min[3] = { + domain->p0[0] - domain->cell_size[0] * domain->adapt_res, + domain->p0[1] - domain->cell_size[1] * domain->adapt_res, + domain->p0[2] - domain->cell_size[2] * domain->adapt_res, + }; + + int num_points_v[3] = { + ((float)(res_max[0] - floor(xyz[0])) / step_size) + 0.5f, + ((float)(res_max[1] - floor(xyz[1])) / step_size) + 0.5f, + ((float)(res_max[2] - floor(xyz[2])) / step_size) + 0.5f + }; + + if (domain->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + domain->axis_slice_method == AXIS_SLICE_SINGLE) + { + const int axis = (domain->slice_axis == SLICE_AXIS_AUTO) ? + axis_dominant_v3_single(viewnormal) : domain->slice_axis - 1; + + xyz[axis] = (float)base_res[axis] * domain->slice_depth; + num_points_v[axis] = 1; + res_max[axis] = xyz[axis] + 1; + } + + vector_draw_func func; + int max_points; + + if (domain->vector_draw_type == VECTOR_DRAW_NEEDLE) { + func = add_needle; + max_points = (num_points_v[0] * num_points_v[1] * num_points_v[2]) * 4 * 3; + } + else { + func = add_streamline; + max_points = (num_points_v[0] * num_points_v[1] * num_points_v[2]) * 2; + } + + float (*verts)[3] = MEM_mallocN(sizeof(float) * 3 * max_points, ""); + float (*colors)[3] = MEM_mallocN(sizeof(float) * 3 * max_points, ""); + + int num_points = 0; + + for (float x = floor(xyz[0]); x < res_max[0]; x += step_size) { + for (float y = floor(xyz[1]); y < res_max[1]; y += step_size) { + for (float z = floor(xyz[2]); z < res_max[2]; z += step_size) { int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1]; - float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]}; - float vel = sqrtf(vel_x[index] * vel_x[index] + vel_y[index] * vel_y[index] + vel_z[index] * vel_z[index]); + float pos[3] = { + min[0] + ((float)x + 0.5f) * cell_size[0], + min[1] + ((float)y + 0.5f) * cell_size[1], + min[2] + ((float)z + 0.5f) * cell_size[2] + }; - /* draw heat as scaled "arrows" */ - if (vel >= 0.01f) { - float col_g = 1.0f - vel; - CLAMP(col_g, 0.0f, 1.0f); - glColor3f(1.0f, col_g, 0.0f); - glPointSize(10.0f * vel); + float vel[3] = { + vel_x[index], vel_y[index], vel_z[index] + }; - glBegin(GL_LINES); - glVertex3f(pos[0], pos[1], pos[2]); - glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); - glEnd(); - glBegin(GL_POINTS); - glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); - glEnd(); - } + func(verts, colors, pos, vel, domain->vector_scale, cell_size[0], &num_points); } -} + } + } + + glLineWidth(1.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, verts); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, colors); + + glDrawArrays(GL_LINES, 0, num_points); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + MEM_freeN(verts); + MEM_freeN(colors); +#else + UNUSED_VARS(domain, viewnormal); #endif +} #ifdef SMOKE_DEBUG_HEAT void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob) diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 46587fefd76..a6ef89d9802 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -295,12 +295,10 @@ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, const float min[3], const float max[3], const float viewnormal[3]); -//#define SMOKE_DEBUG_VELOCITY //#define SMOKE_DEBUG_HEAT -#ifdef SMOKE_DEBUG_VELOCITY -void draw_smoke_velocity(struct SmokeDomainSettings *domain, struct Object *ob); -#endif +void draw_smoke_velocity(struct SmokeDomainSettings *domain, float viewnormal[3]); + #ifdef SMOKE_DEBUG_HEAT void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob); #endif diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 71801ac4a5d..68b7f559fce 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -52,6 +52,31 @@ enum { /* viewsettings */ #define MOD_SMOKE_VIEW_SHOWBIG (1<<0) +/* slice method */ +enum { + MOD_SMOKE_SLICE_VIEW_ALIGNED = 0, + MOD_SMOKE_SLICE_AXIS_ALIGNED = 1, +}; + +/* axis aligned method */ +enum { + AXIS_SLICE_FULL = 0, + AXIS_SLICE_SINGLE = 1, +}; + +/* single slice direction */ +enum { + SLICE_AXIS_AUTO = 0, + SLICE_AXIS_X = 1, + SLICE_AXIS_Y = 2, + SLICE_AXIS_Z = 3, +}; + +enum { + VECTOR_DRAW_NEEDLE = 0, + VECTOR_DRAW_STREAMLINE = 1, +}; + /* cache compression */ #define SM_CACHE_LIGHT 0 #define SM_CACHE_HEAVY 1 @@ -158,6 +183,16 @@ typedef struct SmokeDomainSettings { float burning_rate, flame_smoke, flame_vorticity; float flame_ignition, flame_max_temp; float flame_smoke_color[3]; + + /* Display settings */ + char slice_method, axis_slice_method; + char slice_axis, draw_velocity; + float slice_per_voxel; + float slice_depth; + float display_thickness; + float vector_scale; + char vector_draw_type; + char pad2[3]; } SmokeDomainSettings; diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 3f9bcde4ce2..b0be30ac355 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -400,6 +400,32 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem smoke_view_items[] = { + {MOD_SMOKE_SLICE_VIEW_ALIGNED, "VIEW_ALIGNED", 0, "View", "Slice volume parallel to the view plane"}, + {MOD_SMOKE_SLICE_AXIS_ALIGNED, "AXIS_ALIGNED", 0, "Axis", "Slice volume parallel to the major axis"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem axis_slice_method_items[] = { + {AXIS_SLICE_FULL, "FULL", 0, "Full", "Slice the whole domain object"}, + {AXIS_SLICE_SINGLE, "SINGLE", 0, "Single", "Perform a single slice of the domain object"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem axis_slice_position_items[] = { + {SLICE_AXIS_AUTO, "AUTO", 0, "Auto", "Adjust slice direction according to the view direction"}, + {SLICE_AXIS_X, "X", 0, "X", "Slice along the X axis"}, + {SLICE_AXIS_Y, "Y", 0, "Y", "Slice along the Y axis"}, + {SLICE_AXIS_Z, "Z", 0, "Z", "Slice along the Z axis"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem vector_draw_items[] = { + {VECTOR_DRAW_NEEDLE, "NEEDLE", 0, "Needle", "Draw vectors as needles"}, + {VECTOR_DRAW_STREAMLINE, "STREAMLINE", 0, "Streamlines", "Draw vectors as streamlines"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL); RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings"); RNA_def_struct_sdna(srna, "SmokeDomainSettings"); @@ -658,7 +684,66 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.01, 0.5, 1.0, 5); RNA_def_property_ui_text(prop, "Threshold", "Maximum amount of fluid cell can contain before it is considered empty"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update"); + + /* display settings */ + + prop = RNA_def_property(srna, "slice_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "slice_method"); + RNA_def_property_enum_items(prop, smoke_view_items); + RNA_def_property_ui_text(prop, "View Method", "How to slice the volume for viewport rendering"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "axis_slice_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "axis_slice_method"); + RNA_def_property_enum_items(prop, axis_slice_method_items); + RNA_def_property_ui_text(prop, "Method", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "slice_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "slice_axis"); + RNA_def_property_enum_items(prop, axis_slice_position_items); + RNA_def_property_ui_text(prop, "Axis", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "slice_per_voxel", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "slice_per_voxel"); + RNA_def_property_range(prop, 0.0, 100.0); + RNA_def_property_ui_range(prop, 0.0, 5.0, 0.1, 1); + RNA_def_property_ui_text(prop, "Slice Per Voxel", + "How many slices per voxel should be generated"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "slice_depth", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "slice_depth"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Position", "Position of the slice"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "display_thickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "display_thickness"); + RNA_def_property_range(prop, 0.001, 1000.0); + RNA_def_property_ui_range(prop, 0.1, 100.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Thickness", "Thickness of smoke drawing in the viewport"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + + prop = RNA_def_property(srna, "draw_velocity", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "draw_velocity", 0); + RNA_def_property_ui_text(prop, "Draw Velocity", "Toggle visualation of the velocity field as needles"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_draw_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "vector_draw_type"); + RNA_def_property_enum_items(prop, vector_draw_items); + RNA_def_property_ui_text(prop, "Draw Type", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "vector_scale"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Scale", "Multiplier for scaling the vectors"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 5576a104123..1c1c2ad35af 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -168,7 +168,6 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) wmDrawData *drawdata; wmDrawTriple *triple; float halfx, halfy, ratiox, ratioy; - float alpha = 1.0f; int view; int soffx; bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; @@ -187,8 +186,6 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) soffx = 0; } - glEnable(triple->target); - const int sizex = triple->x; const int sizey = triple->y; @@ -206,9 +203,10 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) halfy /= triple->y; } + glEnable(triple->target); glBindTexture(triple->target, triple->bind); - glColor4f(1.0f, 1.0f, 1.0f, alpha); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(halfx, halfy); glVertex2f(soffx, 0); @@ -225,7 +223,6 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) glBindTexture(triple->target, 0); glDisable(triple->target); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } @@ -234,7 +231,6 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win) wmDrawData *drawdata; wmDrawTriple *triple; float halfx, halfy, ratiox, ratioy; - float alpha = 1.0f; int view; int soffy; @@ -249,8 +245,6 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win) soffy = 0; } - glEnable(triple->target); - const int sizex = triple->x; const int sizey = triple->y; @@ -268,9 +262,10 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win) halfy /= triple->y; } + glEnable(triple->target); glBindTexture(triple->target, triple->bind); - glColor4f(1.0f, 1.0f, 1.0f, alpha); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(halfx, halfy); glVertex2f(0, soffy); @@ -287,7 +282,6 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win) glBindTexture(triple->target, 0); glDisable(triple->target); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } |