diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2020-02-07 18:36:48 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2020-02-07 18:36:48 +0300 |
commit | c0146170af9175120b06416364e021ddbb5f4771 (patch) | |
tree | 529006013ab5e3bd3fc8f2bc6dd328e89eb79da1 | |
parent | 3846212d1e13842b1d7c7be7621371aa2794407d (diff) | |
parent | 677e027f2069dac18891db931c860542cbcb4bbe (diff) |
Merge branch 'master' into greasepencil-object
157 files changed, 6598 insertions, 5697 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 509de9943e2..60656a9e4fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -613,29 +613,25 @@ endif() # enable boost for cycles, audaspace or i18n # otherwise if the user disabled -if(NOT WITH_BOOST) - # Explicitly disabled. so disable all deps. - macro(set_and_warn - _setting _val) - if(${${_setting}}) - message(STATUS "'WITH_BOOST' is disabled: forcing 'set(${_setting} ${_val})'") - endif() - set(${_setting} ${_val}) - endmacro() - - set_and_warn(WITH_CYCLES OFF) - set_and_warn(WITH_INTERNATIONAL OFF) - set_and_warn(WITH_OPENVDB OFF) - set_and_warn(WITH_OPENCOLORIO OFF) - set_and_warn(WITH_QUADRIFLOW OFF) -elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR - WITH_OPENVDB OR WITH_OPENCOLORIO) - # Keep enabled -else() - # Disable boost if not needed. + +set_and_warn_dependency(WITH_BOOST WITH_CYCLES OFF) +set_and_warn_dependency(WITH_BOOST WITH_INTERNATIONAL OFF) +set_and_warn_dependency(WITH_BOOST WITH_OPENVDB OFF) +set_and_warn_dependency(WITH_BOOST WITH_OPENCOLORIO OFF) +set_and_warn_dependency(WITH_BOOST WITH_QUADRIFLOW OFF) +set_and_warn_dependency(WITH_BOOST WITH_USD OFF) + +if(NOT (WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR + WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_USD)) + message(STATUS "No dependencies need 'WITH_BOOST' forcing WITH_BOOST=OFF") set(WITH_BOOST OFF) endif() +set_and_warn_dependency(WITH_TBB WITH_USD OFF) +set_and_warn_dependency(WITH_TBB WITH_OPENIMAGEDENOISE OFF) +set_and_warn_dependency(WITH_TBB WITH_OPENVDB OFF) +set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF) + # auto enable openimageio for cycles if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 2d13476f09a..daf156bc3f2 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -1157,3 +1157,13 @@ macro(blender_precompile_headers target cpp header) set_source_files_properties(${cpp} PROPERTIES COMPILE_FLAGS "/Yc${header} /Fp${pchfinal}") endif() endmacro() + +macro(set_and_warn_dependency + _dependency _setting _val) + # when $_dependency is disabled, forces $_setting = $_val + if(NOT ${${_dependency}} AND ${${_setting}}) + message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'") + set(${_setting} ${_val}) + endif() +endmacro() + diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index a4de3876243..b231a2b6fa4 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -398,21 +398,6 @@ if(WITH_TBB) find_package(TBB) endif() -if(NOT WITH_TBB OR NOT TBB_FOUND) - if(WITH_OPENIMAGEDENOISE) - message(STATUS "TBB not found, disabling OpenImageDenoise") - set(WITH_OPENIMAGEDENOISE OFF) - endif() - if(WITH_OPENVDB) - message(STATUS "TBB not found, disabling OpenVDB") - set(WITH_OPENVDB OFF) - endif() - if(WITH_MOD_FLUID) - message(STATUS "TBB not found, disabling Fluid modifier") - set(WITH_MOD_FLUID OFF) - endif() -endif() - # CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags. if(WITH_OPENMP) if(CMAKE_C_COMPILER_ID MATCHES "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 2f9f39b46d9..91f836d5265 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -448,17 +448,6 @@ if(WITH_TBB) find_package_wrapper(TBB) endif() -if(NOT WITH_TBB OR NOT TBB_FOUND) - if(WITH_OPENIMAGEDENOISE) - message(STATUS "TBB not found, disabling OpenImageDenoise") - set(WITH_OPENIMAGEDENOISE OFF) - endif() - if(WITH_OPENVDB) - message(STATUS "TBB not found, disabling OpenVDB") - set(WITH_OPENVDB OFF) - endif() -endif() - # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed if(HAIKU) list(APPEND PLATFORM_LINKLIBS -lnetwork) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 04e5848dcfe..4241f307abc 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -570,19 +570,6 @@ if(WITH_TBB) if(WITH_TBB_MALLOC_PROXY) add_definitions(-DWITH_TBB_MALLOC) endif() -else() - if(WITH_OPENIMAGEDENOISE) - message(STATUS "TBB disabled, also disabling OpenImageDenoise") - set(WITH_OPENIMAGEDENOISE OFF) - endif() - if(WITH_OPENVDB) - message(STATUS "TBB disabled, also disabling OpenVDB") - set(WITH_OPENVDB OFF) - endif() - if(WITH_MOD_FLUID) - message(STATUS "TBB disabled, disabling Fluid modifier") - set(WITH_MOD_FLUID OFF) - endif() endif() # used in many places so include globally, like OpenGL diff --git a/extern/glew/CMakeLists.txt b/extern/glew/CMakeLists.txt index 18ca88e6fec..59f13eb73c7 100644 --- a/extern/glew/CMakeLists.txt +++ b/extern/glew/CMakeLists.txt @@ -25,6 +25,16 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") ) endif() +# MSVC's inliner is not having a happy time with glewIsSupported +# causing this to be one of the most expensive things to build +# in blender. Optimize for size rather than speed sidesteps this +# problem, more details at +# https://developercommunity.visualstudio.com/content/problem/732941/slow-compilation-of-glewc-for-visual-studio-2019-x.html + +if(MSVC) + add_c_flag("/Os") +endif() + set(INC include ) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 1dbe8a30ff2..2540786a014 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -326,6 +326,10 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str()); continue; } + else if (node_type->create == NULL) { + fprintf(stderr, "Can't create abstract node type \"%s\".\n", node_type->name.c_str()); + continue; + } snode = (ShaderNode *)node_type->create(node_type); } @@ -376,11 +380,11 @@ static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm) { /* create mesh */ Mesh *mesh = new Mesh(); - scene->meshes.push_back(mesh); + scene->geometry.push_back(mesh); /* create object*/ Object *object = new Object(); - object->mesh = mesh; + object->geometry = mesh; object->tfm = tfm; scene->objects.push_back(object); diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 0888eeb78bb..d9a2ebf8571 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -18,6 +18,9 @@ set(INC_SYS set(SRC blender_camera.cpp blender_device.cpp + blender_image.cpp + blender_geometry.cpp + blender_light.cpp blender_mesh.cpp blender_object.cpp blender_object_cull.cpp @@ -30,9 +33,11 @@ set(SRC blender_sync.cpp blender_texture.cpp blender_viewport.cpp + blender_volume.cpp CCL_api.h blender_device.h + blender_id_map.h blender_object_cull.h blender_sync.h blender_session.h diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 78db1d5c832..affd5685337 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -17,6 +17,7 @@ #include "render/attribute.h" #include "render/camera.h" #include "render/curves.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/object.h" #include "render/scene.h" @@ -107,12 +108,12 @@ static void InterpolateKeySegments( } static bool ObtainCacheParticleData( - Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background) + Geometry *geom, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background) { int curvenum = 0; int keyno = 0; - if (!(mesh && b_mesh && b_ob && CData)) + if (!(geom && b_mesh && b_ob && CData)) return false; Transform tfm = get_transform(b_ob->matrix_world()); @@ -128,7 +129,7 @@ static bool ObtainCacheParticleData( if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { - int shader = clamp(b_part.material() - 1, 0, mesh->used_shaders.size() - 1); + int shader = clamp(b_part.material() - 1, 0, geom->used_shaders.size() - 1); int display_step = background ? b_part.render_step() : b_part.display_step(); int totparts = b_psys.particles.length(); int totchild = background ? b_psys.child_particles.length() : @@ -202,14 +203,14 @@ static bool ObtainCacheParticleData( return true; } -static bool ObtainCacheParticleUV(Mesh *mesh, +static bool ObtainCacheParticleUV(Geometry *geom, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num) { - if (!(mesh && b_mesh && b_ob && CData)) + if (!(geom && b_mesh && b_ob && CData)) return false; CData->curve_uv.clear(); @@ -265,14 +266,14 @@ static bool ObtainCacheParticleUV(Mesh *mesh, return true; } -static bool ObtainCacheParticleVcol(Mesh *mesh, +static bool ObtainCacheParticleVcol(Geometry *geom, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num) { - if (!(mesh && b_mesh && b_ob && CData)) + if (!(geom && b_mesh && b_ob && CData)) return false; CData->curve_vcol.clear(); @@ -594,21 +595,55 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, in /* texture coords still needed */ } -static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) +static void export_hair_motion_validate_attribute(Hair *hair, + int motion_step, + int num_motion_keys, + bool have_motion) +{ + Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + const int num_keys = hair->curve_keys.size(); + + if (num_motion_keys != num_keys || !have_motion) { + /* No motion or hair "topology" changed, remove attributes again. */ + if (num_motion_keys != num_keys) { + VLOG(1) << "Hair topology changed, removing attribute."; + } + else { + VLOG(1) << "No motion, removing attribute."; + } + hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); + } + else if (motion_step > 0) { + VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step; + + /* Motion, fill up previous steps that we might have skipped because + * they had no motion, but we need them anyway now. */ + for (int step = 0; step < motion_step; step++) { + float4 *mP = attr_mP->data_float4() + step * num_keys; + + for (int key = 0; key < num_keys; key++) { + mP[key] = float3_to_float4(hair->curve_keys[key]); + mP[key].w = hair->curve_radius[key]; + } + } + } +} + +static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CData) { int num_keys = 0; int num_curves = 0; - if (mesh->num_curves()) + if (hair->num_curves()) return; Attribute *attr_intercept = NULL; Attribute *attr_random = NULL; - if (mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) - attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT); - if (mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) - attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM); + if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) + attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT); + if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) + attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM); /* compute and reserve size of arrays */ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { @@ -621,10 +656,10 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa } if (num_curves > 0) { - VLOG(1) << "Exporting curve segments for mesh " << mesh->name; + VLOG(1) << "Exporting curve segments for mesh " << hair->name; } - mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys); + hair->reserve_curves(hair->num_curves() + num_curves, hair->curve_keys.size() + num_keys); num_keys = 0; num_curves = 0; @@ -649,7 +684,7 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) { radius = 0.0f; } - mesh->add_curve_key(ickey_loc, radius); + hair->add_curve_key(ickey_loc, radius); if (attr_intercept) attr_intercept->add(time); @@ -660,16 +695,16 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa attr_random->add(hash_uint2_to_float(num_curves, 0)); } - mesh->add_curve(num_keys, CData->psys_shader[sys]); + hair->add_curve(num_keys, CData->psys_shader[sys]); num_keys += num_curve_keys; num_curves++; } } /* check allocation */ - if ((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) { + if ((hair->curve_keys.size() != num_keys) || (hair->num_curves() != num_curves)) { VLOG(1) << "Allocation failed, clearing data"; - mesh->clear(); + hair->clear(); } } @@ -713,24 +748,24 @@ static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int cu return lerp(mP, mP2, remainder); } -static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step) +static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step) { - VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name << ", motion step " + VLOG(1) << "Exporting curve motion segments for hair " << hair->name << ", motion step " << motion_step; /* find attribute */ - Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); bool new_attribute = false; /* add new attribute if it doesn't exist already */ if (!attr_mP) { VLOG(1) << "Creating new motion vertex position attribute"; - attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + attr_mP = hair->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); new_attribute = true; } /* export motion vectors for curve keys */ - size_t numkeys = mesh->curve_keys.size(); + size_t numkeys = hair->curve_keys.size(); float4 *mP = attr_mP->data_float4() + motion_step * numkeys; bool have_motion = false; int i = 0; @@ -741,24 +776,24 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) { /* Curve lengths may not match! Curves can be clipped. */ - int curve_key_end = (num_curves + 1 < (int)mesh->curve_first_key.size() ? - mesh->curve_first_key[num_curves + 1] : - (int)mesh->curve_keys.size()); - const int num_center_curve_keys = curve_key_end - mesh->curve_first_key[num_curves]; + int curve_key_end = (num_curves + 1 < (int)hair->curve_first_key.size() ? + hair->curve_first_key[num_curves + 1] : + (int)hair->curve_keys.size()); + const int num_center_curve_keys = curve_key_end - hair->curve_first_key[num_curves]; const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys; if (!is_num_keys_different) { for (int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) { - if (i < mesh->curve_keys.size()) { + if (i < hair->curve_keys.size()) { mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey); if (!have_motion) { /* unlike mesh coordinates, these tend to be slightly different * between frames due to particle transforms into/out of object * space, so we use an epsilon to detect actual changes */ - float4 curve_key = float3_to_float4(mesh->curve_keys[i]); - curve_key.w = mesh->curve_radius[i]; + float4 curve_key = float3_to_float4(hair->curve_keys[i]); + curve_key.w = hair->curve_radius[i]; if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f) have_motion = true; } @@ -784,40 +819,15 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int /* in case of new attribute, we verify if there really was any motion */ if (new_attribute) { - if (i != numkeys || !have_motion) { - /* No motion or hair "topology" changed, remove attributes again. */ - if (i != numkeys) { - VLOG(1) << "Hair topology changed, removing attribute."; - } - else { - VLOG(1) << "No motion, removing attribute."; - } - mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); - } - else if (motion_step > 0) { - VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step; - /* motion, fill up previous steps that we might have skipped because - * they had no motion, but we need them anyway now */ - for (int step = 0; step < motion_step; step++) { - float4 *mP = attr_mP->data_float4() + step * numkeys; - - for (int key = 0; key < numkeys; key++) { - mP[key] = float3_to_float4(mesh->curve_keys[key]); - mP[key].w = mesh->curve_radius[key]; - } - } - } + export_hair_motion_validate_attribute(hair, motion_step, i, have_motion); } } -static void ExportCurveTriangleUV(ParticleCurveData *CData, - int vert_offset, - int resol, - float2 *uvdata) +static void ExportCurveTriangleUV(ParticleCurveData *CData, int resol, float2 *uvdata) { if (uvdata == NULL) return; - int vertexindex = vert_offset; + int vertexindex = 0; for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { for (int curve = CData->psys_firstcurve[sys]; @@ -845,15 +855,12 @@ static void ExportCurveTriangleUV(ParticleCurveData *CData, } } -static void ExportCurveTriangleVcol(ParticleCurveData *CData, - int vert_offset, - int resol, - uchar4 *cdata) +static void ExportCurveTriangleVcol(ParticleCurveData *CData, int resol, uchar4 *cdata) { if (cdata == NULL) return; - int vertexindex = vert_offset; + int vertexindex = 0; for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { for (int curve = CData->psys_firstcurve[sys]; @@ -952,7 +959,7 @@ void BlenderSync::sync_curve_settings() if ((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) && (b_psys->settings().type() == BL::ParticleSettings::type_HAIR)) { BL::ID key = BKE_object_is_modified(*b_ob) ? *b_ob : b_ob->data(); - mesh_map.set_recalc(key); + geometry_map.set_recalc(key); object_map.set_recalc(*b_ob); } } @@ -964,42 +971,51 @@ void BlenderSync::sync_curve_settings() curve_system_manager->tag_update(scene); } -void BlenderSync::sync_curves( - Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step) +bool BlenderSync::object_has_particle_hair(BL::Object b_ob) { - if (!motion) { - /* Clear stored curve data */ - mesh->curve_keys.clear(); - mesh->curve_radius.clear(); - mesh->curve_first_key.clear(); - mesh->curve_shader.clear(); - mesh->curve_attributes.clear(); + /* Test if the object has a particle modifier with hair. */ + BL::Object::modifiers_iterator b_mod; + for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { + if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && + (preview ? b_mod->show_viewport() : b_mod->show_render())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && + (b_part.type() == BL::ParticleSettings::type_HAIR)) { + return true; + } + } } - /* obtain general settings */ - const bool use_curves = scene->curve_system_manager->use_curves; + return false; +} + +/* Old particle hair. */ +void BlenderSync::sync_particle_hair( + Geometry *geom, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step) +{ + Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL; + Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL; - if (!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT && b_ob.mode() != b_ob.mode_EDIT)) { - if (!motion) - mesh->compute_bounds(); + /* obtain general settings */ + if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) { return; } - const int primitive = scene->curve_system_manager->primitive; const int triangle_method = scene->curve_system_manager->triangle_method; const int resolution = scene->curve_system_manager->resolution; - const size_t vert_num = mesh->verts.size(); - const size_t tri_num = mesh->num_triangles(); int used_res = 1; /* extract particle hair data - should be combined with connecting to mesh later*/ ParticleCurveData CData; - ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); + ObtainCacheParticleData(geom, &b_mesh, &b_ob, &CData, !preview); /* add hair geometry to mesh */ - if (primitive == CURVE_TRIANGLES) { + if (mesh) { if (triangle_method == CURVE_CAMERA_TRIANGLES) { /* obtain camera parameters */ float3 RotCam; @@ -1023,31 +1039,31 @@ void BlenderSync::sync_curves( } else { if (motion) - ExportCurveSegmentsMotion(mesh, &CData, motion_step); + ExportCurveSegmentsMotion(hair, &CData, motion_step); else - ExportCurveSegments(scene, mesh, &CData); + ExportCurveSegments(scene, hair, &CData); } /* generated coordinates from first key. we should ideally get this from * blender to handle deforming objects */ if (!motion) { - if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + if (geom->need_attribute(scene, ATTR_STD_GENERATED)) { float3 loc, size; mesh_texture_space(b_mesh, loc, size); - if (primitive == CURVE_TRIANGLES) { + if (mesh) { Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED); float3 *generated = attr_generated->data_float3(); - for (size_t i = vert_num; i < mesh->verts.size(); i++) + for (size_t i = 0; i < mesh->verts.size(); i++) generated[i] = mesh->verts[i] * size - loc; } else { - Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED); + Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED); float3 *generated = attr_generated->data_float3(); - for (size_t i = 0; i < mesh->num_curves(); i++) { - float3 co = mesh->curve_keys[mesh->get_curve(i).first_key]; + for (size_t i = 0; i < hair->num_curves(); i++) { + float3 co = hair->curve_keys[hair->get_curve(i).first_key]; generated[i] = co * size - loc; } } @@ -1060,21 +1076,21 @@ void BlenderSync::sync_curves( int vcol_num = 0; for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) { - if (!mesh->need_attribute(scene, ustring(l->name().c_str()))) + if (!geom->need_attribute(scene, ustring(l->name().c_str()))) continue; - ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); + ObtainCacheParticleVcol(geom, &b_mesh, &b_ob, &CData, !preview, vcol_num); - if (primitive == CURVE_TRIANGLES) { + if (mesh) { Attribute *attr_vcol = mesh->attributes.add( ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); uchar4 *cdata = attr_vcol->data_uchar4(); - ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata); + ExportCurveTriangleVcol(&CData, used_res, cdata); } else { - Attribute *attr_vcol = mesh->curve_attributes.add( + Attribute *attr_vcol = hair->attributes.add( ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); float3 *fdata = attr_vcol->data_float3(); @@ -1102,12 +1118,12 @@ void BlenderSync::sync_curves( ustring name = ustring(l->name().c_str()); /* UV map */ - if (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + if (geom->need_attribute(scene, name) || geom->need_attribute(scene, std)) { Attribute *attr_uv; - ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num); + ObtainCacheParticleUV(geom, &b_mesh, &b_ob, &CData, !preview, uv_num); - if (primitive == CURVE_TRIANGLES) { + if (mesh) { if (active_render) attr_uv = mesh->attributes.add(std, name); else @@ -1115,13 +1131,13 @@ void BlenderSync::sync_curves( float2 *uv = attr_uv->data_float2(); - ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv); + ExportCurveTriangleUV(&CData, used_res, uv); } else { if (active_render) - attr_uv = mesh->curve_attributes.add(std, name); + attr_uv = hair->attributes.add(std, name); else - attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE); + attr_uv = hair->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE); float2 *uv = attr_uv->data_float2(); @@ -1136,8 +1152,77 @@ void BlenderSync::sync_curves( } } } +} + +void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom) +{ + Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL; + Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL; + + /* Compares curve_keys rather than strands in order to handle quick hair + * adjustments in dynamic BVH - other methods could probably do this better. */ + array<float3> oldcurve_keys; + array<float> oldcurve_radius; + array<int> oldtriangles; + if (hair) { + oldcurve_keys.steal_data(hair->curve_keys); + oldcurve_radius.steal_data(hair->curve_radius); + } + else { + oldtriangles.steal_data(mesh->triangles); + } + + if (view_layer.use_hair && scene->curve_system_manager->use_curves) { + /* Particle hair. */ + bool need_undeformed = geom->need_attribute(scene, ATTR_STD_GENERATED); + BL::Mesh b_mesh = object_to_mesh( + b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE); + + if (b_mesh) { + sync_particle_hair(geom, b_mesh, b_ob, false); + free_object_to_mesh(b_data, b_ob, b_mesh); + } + } + + /* tag update */ + const bool rebuild = (hair && ((oldcurve_keys != hair->curve_keys) || + (oldcurve_radius != hair->curve_radius))) || + (mesh && (oldtriangles != mesh->triangles)); + + geom->tag_update(scene, rebuild); +} - mesh->compute_bounds(); +void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Geometry *geom, + int motion_step) +{ + Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL; + Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL; + + /* Skip if nothing exported. */ + if ((hair && hair->num_keys() == 0) || (mesh && mesh->verts.size() == 0)) { + return; + } + + /* Export deformed coordinates. */ + if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { + /* Particle hair. */ + BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE); + if (b_mesh) { + sync_particle_hair(geom, b_mesh, b_ob, true, motion_step); + free_object_to_mesh(b_data, b_ob, b_mesh); + return; + } + } + + /* No deformation on this frame, copy coordinates if other frames did have it. */ + if (hair) { + hair->copy_center_to_motion_step(motion_step); + } + else { + mesh->copy_center_to_motion_step(motion_step); + } } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp new file mode 100644 index 00000000000..8b803835b62 --- /dev/null +++ b/intern/cycles/blender/blender_geometry.cpp @@ -0,0 +1,176 @@ + +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/curves.h" +#include "render/hair.h" +#include "render/mesh.h" +#include "render/object.h" + +#include "blender/blender_sync.h" +#include "blender/blender_util.h" + +CCL_NAMESPACE_BEGIN + +Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, + BL::Object &b_ob_instance, + bool object_updated, + bool use_particle_hair) +{ + /* Test if we can instance or if the object is modified. */ + BL::ID b_ob_data = b_ob.data(); + BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; + GeometryKey key(b_key_id.ptr.data, use_particle_hair); + BL::Material material_override = view_layer.material_override; + Shader *default_shader = scene->default_surface; + Geometry::Type geom_type = (use_particle_hair && + (scene->curve_system_manager->primitive != CURVE_TRIANGLES)) ? + Geometry::HAIR : + Geometry::MESH; + + /* Find shader indices. */ + vector<Shader *> used_shaders; + + BL::Object::material_slots_iterator slot; + for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { + if (material_override) { + find_shader(material_override, used_shaders, default_shader); + } + else { + BL::ID b_material(slot->material()); + find_shader(b_material, used_shaders, default_shader); + } + } + + if (used_shaders.size() == 0) { + if (material_override) + find_shader(material_override, used_shaders, default_shader); + else + used_shaders.push_back(default_shader); + } + + /* Test if we need to sync. */ + Geometry *geom = geometry_map.find(key); + bool sync = true; + if (geom == NULL) { + /* Add new geometry if it did not exist yet. */ + if (geom_type == Geometry::HAIR) { + geom = new Hair(); + } + else { + geom = new Mesh(); + } + geometry_map.add(key, geom); + } + else { + /* Test if we need to update existing geometry. */ + sync = geometry_map.update(geom, b_key_id); + } + + if (!sync) { + /* If transform was applied to geometry, need full update. */ + if (object_updated && geom->transform_applied) { + ; + } + /* Test if shaders changed, these can be object level so geometry + * does not get tagged for recalc. */ + else if (geom->used_shaders != used_shaders) { + ; + } + else { + /* Even if not tagged for recalc, we may need to sync anyway + * because the shader needs different geometry attributes. */ + bool attribute_recalc = false; + + foreach (Shader *shader, geom->used_shaders) { + if (shader->need_update_geometry) { + attribute_recalc = true; + } + } + + if (!attribute_recalc) { + return geom; + } + } + } + + /* Ensure we only sync instanced geometry once. */ + if (geometry_synced.find(geom) != geometry_synced.end()) { + return geom; + } + + progress.set_sync_status("Synchronizing object", b_ob.name()); + + geometry_synced.insert(geom); + + geom->clear(); + geom->used_shaders = used_shaders; + geom->name = ustring(b_ob_data.name().c_str()); + + if (use_particle_hair) { + sync_hair(b_depsgraph, b_ob, geom); + } + else if (object_fluid_gas_domain_find(b_ob)) { + Mesh *mesh = static_cast<Mesh *>(geom); + sync_volume(b_ob, mesh); + } + else { + Mesh *mesh = static_cast<Mesh *>(geom); + sync_mesh(b_depsgraph, b_ob, mesh); + } + + return geom; +} + +void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, + Object *object, + float motion_time, + bool use_particle_hair) +{ + /* Ensure we only sync instanced geometry once. */ + Geometry *geom = object->geometry; + + if (geometry_motion_synced.find(geom) != geometry_motion_synced.end()) + return; + + geometry_motion_synced.insert(geom); + + /* Ensure we only motion sync geometry that also had geometry synced, to avoid + * unnecessary work and to ensure that its attributes were clear. */ + if (geometry_synced.find(geom) == geometry_synced.end()) + return; + + /* Find time matching motion step required by geometry. */ + int motion_step = geom->motion_step(motion_time); + if (motion_step < 0) { + return; + } + + if (use_particle_hair) { + sync_hair_motion(b_depsgraph, b_ob, geom, motion_step); + } + else if (object_fluid_gas_domain_find(b_ob)) { + /* No volume motion blur support yet. */ + } + else { + Mesh *mesh = static_cast<Mesh *>(geom); + sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_id_map.h b/intern/cycles/blender/blender_id_map.h new file mode 100644 index 00000000000..83c93bb09ee --- /dev/null +++ b/intern/cycles/blender/blender_id_map.h @@ -0,0 +1,299 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BLENDER_ID_MAP_H__ +#define __BLENDER_ID_MAP_H__ + +#include <string.h> + +#include "util/util_map.h" +#include "util/util_set.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +/* ID Map + * + * Utility class to map between Blender datablocks and Cycles data structures, + * and keep track of recalc tags from the dependency graph. */ + +template<typename K, typename T> class id_map { + public: + id_map(vector<T *> *scene_data_) + { + scene_data = scene_data_; + } + + T *find(const BL::ID &id) + { + return find(id.ptr.owner_id); + } + + T *find(const K &key) + { + if (b_map.find(key) != b_map.end()) { + T *data = b_map[key]; + return data; + } + + return NULL; + } + + void set_recalc(const BL::ID &id) + { + b_recalc.insert(id.ptr.data); + } + + void set_recalc(void *id_ptr) + { + b_recalc.insert(id_ptr); + } + + bool has_recalc() + { + return !(b_recalc.empty()); + } + + void pre_sync() + { + used_set.clear(); + } + + /* Add new data. */ + void add(const K &key, T *data) + { + assert(find(key) == NULL); + scene_data->push_back(data); + b_map[key] = data; + used(data); + } + + /* Update existing data. */ + bool update(T *data, const BL::ID &id) + { + return update(data, id, id); + } + bool update(T *data, const BL::ID &id, const BL::ID &parent) + { + bool recalc = (b_recalc.find(id.ptr.data) != b_recalc.end()); + if (parent.ptr.data && parent.ptr.data != id.ptr.data) { + recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end()); + } + used(data); + return recalc; + } + + /* Combined add and update as needed. */ + bool add_or_update(T **r_data, const BL::ID &id) + { + return add_or_update(r_data, id, id, id.ptr.owner_id); + } + bool add_or_update(T **r_data, const BL::ID &id, const K &key) + { + return add_or_update(r_data, id, id, key); + } + bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key) + { + T *data = find(key); + bool recalc; + + if (!data) { + /* Add data if it didn't exist yet. */ + data = new T(); + add(key, data); + recalc = true; + } + else { + /* check if updated needed. */ + recalc = update(data, id, parent); + } + + *r_data = data; + return recalc; + } + + /* Combined add or update for convenience. */ + + bool is_used(const K &key) + { + T *data = find(key); + return (data) ? used_set.find(data) != used_set.end() : false; + } + + void used(T *data) + { + /* tag data as still in use */ + used_set.insert(data); + } + + void set_default(T *data) + { + b_map[NULL] = data; + } + + bool post_sync(bool do_delete = true) + { + /* remove unused data */ + vector<T *> new_scene_data; + typename vector<T *>::iterator it; + bool deleted = false; + + for (it = scene_data->begin(); it != scene_data->end(); it++) { + T *data = *it; + + if (do_delete && used_set.find(data) == used_set.end()) { + delete data; + deleted = true; + } + else + new_scene_data.push_back(data); + } + + *scene_data = new_scene_data; + + /* update mapping */ + map<K, T *> new_map; + typedef pair<const K, T *> TMapPair; + typename map<K, T *>::iterator jt; + + for (jt = b_map.begin(); jt != b_map.end(); jt++) { + TMapPair &pair = *jt; + + if (used_set.find(pair.second) != used_set.end()) + new_map[pair.first] = pair.second; + } + + used_set.clear(); + b_recalc.clear(); + b_map = new_map; + + return deleted; + } + + const map<K, T *> &key_to_scene_data() + { + return b_map; + } + + protected: + vector<T *> *scene_data; + map<K, T *> b_map; + set<T *> used_set; + set<void *> b_recalc; +}; + +/* Object Key + * + * To uniquely identify instances, we use the parent, object and persistent instance ID. + * We also export separate object for a mesh and its particle hair. */ + +enum { OBJECT_PERSISTENT_ID_SIZE = 16 }; + +struct ObjectKey { + void *parent; + int id[OBJECT_PERSISTENT_ID_SIZE]; + void *ob; + bool use_particle_hair; + + ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_) + : parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_) + { + if (id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } + + bool operator<(const ObjectKey &k) const + { + if (ob < k.ob) { + return true; + } + else if (ob == k.ob) { + if (parent < k.parent) { + return true; + } + else if (parent == k.parent) { + if (use_particle_hair < k.use_particle_hair) { + return true; + } + else if (use_particle_hair == k.use_particle_hair) { + return memcmp(id, k.id, sizeof(id)) < 0; + } + } + } + + return false; + } +}; + +/* Geometry Key + * + * We export separate geomtry for a mesh and its particle hair, so key needs to + * distinguish between them. */ + +struct GeometryKey { + void *id; + bool use_particle_hair; + + GeometryKey(void *id, bool use_particle_hair) : id(id), use_particle_hair(use_particle_hair) + { + } + + bool operator<(const GeometryKey &k) const + { + if (id < k.id) { + return true; + } + else if (id == k.id) { + if (use_particle_hair < k.use_particle_hair) { + return true; + } + } + + return false; + } +}; + +/* Particle System Key */ + +struct ParticleSystemKey { + void *ob; + int id[OBJECT_PERSISTENT_ID_SIZE]; + + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_) + { + if (id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } + + bool operator<(const ParticleSystemKey &k) const + { + /* first id is particle index, we don't compare that */ + if (ob < k.ob) + return true; + else if (ob == k.ob) + return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0; + + return false; + } +}; + +CCL_NAMESPACE_END + +#endif /* __BLENDER_ID_MAP_H__ */ diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp new file mode 100644 index 00000000000..0fe42b2d479 --- /dev/null +++ b/intern/cycles/blender/blender_image.cpp @@ -0,0 +1,360 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/image.h" + +#include "blender/blender_sync.h" +#include "blender/blender_session.h" +#include "blender/blender_util.h" + +CCL_NAMESPACE_BEGIN + +/* builtin image file name is actually an image datablock name with + * absolute sequence frame number concatenated via '@' character + * + * this function splits frame from builtin name + */ +int BlenderSession::builtin_image_frame(const string &builtin_name) +{ + int last = builtin_name.find_last_of('@'); + return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str()); +} + +void BlenderSession::builtin_image_info(const string &builtin_name, + void *builtin_data, + ImageMetaData &metadata) +{ + /* empty image */ + metadata.width = 1; + metadata.height = 1; + + if (!builtin_data) + return; + + /* recover ID pointer */ + PointerRNA ptr; + RNA_id_pointer_create((ID *)builtin_data, &ptr); + BL::ID b_id(ptr); + + if (b_id.is_a(&RNA_Image)) { + /* image data */ + BL::Image b_image(b_id); + + metadata.builtin_free_cache = !b_image.has_data(); + metadata.is_float = b_image.is_float(); + metadata.width = b_image.size()[0]; + metadata.height = b_image.size()[1]; + metadata.depth = 1; + metadata.channels = b_image.channels(); + + if (metadata.is_float) { + /* Float images are already converted on the Blender side, + * no need to do anything in Cycles. */ + metadata.colorspace = u_colorspace_raw; + } + } + else if (b_id.is_a(&RNA_Object)) { + /* smoke volume data */ + BL::Object b_ob(b_id); + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + + metadata.is_float = true; + metadata.depth = 1; + metadata.channels = 1; + + if (!b_domain) + return; + + if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) + metadata.channels = 1; + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) + metadata.channels = 4; + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) + metadata.channels = 3; + else + return; + + int3 resolution = get_int3(b_domain.domain_resolution()); + int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; + + /* Velocity and heat data is always low-resolution. */ + if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { + amplify = 1; + } + + metadata.width = resolution.x * amplify; + metadata.height = resolution.y * amplify; + metadata.depth = resolution.z * amplify; + } + else { + /* TODO(sergey): Check we're indeed in shader node tree. */ + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); + BL::Node b_node(ptr); + if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { + BL::ShaderNodeTexPointDensity b_point_density_node(b_node); + metadata.channels = 4; + metadata.width = b_point_density_node.resolution(); + metadata.height = metadata.width; + metadata.depth = metadata.width; + metadata.is_float = true; + } + } +} + +bool BlenderSession::builtin_image_pixels(const string &builtin_name, + void *builtin_data, + int tile, + unsigned char *pixels, + const size_t pixels_size, + const bool associate_alpha, + const bool free_cache) +{ + if (!builtin_data) { + return false; + } + + const int frame = builtin_image_frame(builtin_name); + + PointerRNA ptr; + RNA_id_pointer_create((ID *)builtin_data, &ptr); + BL::Image b_image(ptr); + + const int width = b_image.size()[0]; + const int height = b_image.size()[1]; + const int channels = b_image.channels(); + + unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile); + const size_t num_pixels = ((size_t)width) * height; + + if (image_pixels && num_pixels * channels == pixels_size) { + memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char)); + } + else { + if (channels == 1) { + memset(pixels, 0, pixels_size * sizeof(unsigned char)); + } + else { + const size_t num_pixels_safe = pixels_size / channels; + unsigned char *cp = pixels; + for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) { + cp[0] = 255; + cp[1] = 0; + cp[2] = 255; + if (channels == 4) { + cp[3] = 255; + } + } + } + } + + if (image_pixels) { + MEM_freeN(image_pixels); + } + + /* Free image buffers to save memory during render. */ + if (free_cache) { + b_image.buffers_free(); + } + + if (associate_alpha) { + /* Premultiply, byte images are always straight for Blender. */ + unsigned char *cp = pixels; + for (size_t i = 0; i < num_pixels; i++, cp += channels) { + cp[0] = (cp[0] * cp[3]) >> 8; + cp[1] = (cp[1] * cp[3]) >> 8; + cp[2] = (cp[2] * cp[3]) >> 8; + } + } + return true; +} + +bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, + void *builtin_data, + int tile, + float *pixels, + const size_t pixels_size, + const bool, + const bool free_cache) +{ + if (!builtin_data) { + return false; + } + + PointerRNA ptr; + RNA_id_pointer_create((ID *)builtin_data, &ptr); + BL::ID b_id(ptr); + + if (b_id.is_a(&RNA_Image)) { + /* image data */ + BL::Image b_image(b_id); + int frame = builtin_image_frame(builtin_name); + + const int width = b_image.size()[0]; + const int height = b_image.size()[1]; + const int channels = b_image.channels(); + + float *image_pixels; + image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile); + const size_t num_pixels = ((size_t)width) * height; + + if (image_pixels && num_pixels * channels == pixels_size) { + memcpy(pixels, image_pixels, pixels_size * sizeof(float)); + } + else { + if (channels == 1) { + memset(pixels, 0, num_pixels * sizeof(float)); + } + else { + const size_t num_pixels_safe = pixels_size / channels; + float *fp = pixels; + for (int i = 0; i < num_pixels_safe; i++, fp += channels) { + fp[0] = 1.0f; + fp[1] = 0.0f; + fp[2] = 1.0f; + if (channels == 4) { + fp[3] = 1.0f; + } + } + } + } + + if (image_pixels) { + MEM_freeN(image_pixels); + } + + /* Free image buffers to save memory during render. */ + if (free_cache) { + b_image.buffers_free(); + } + + return true; + } + else if (b_id.is_a(&RNA_Object)) { + /* smoke volume data */ + BL::Object b_ob(b_id); + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + + if (!b_domain) { + return false; + } +#if WITH_FLUID + int3 resolution = get_int3(b_domain.domain_resolution()); + int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; + + /* Velocity and heat data is always low-resolution. */ + if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { + amplify = 1; + } + + const int width = resolution.x * amplify; + const int height = resolution.y * amplify; + const int depth = resolution.z * amplify; + const size_t num_pixels = ((size_t)width) * height * depth; + + if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { + FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_density_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) { + /* this is in range 0..1, and interpreted by the OpenGL smoke viewer + * as 1500..3000 K with the first part faded to zero density */ + FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_flame_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { + /* the RGB is "premultiplied" by density for better interpolation results */ + FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels * 4) { + FluidDomainSettings_color_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) { + FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels * 3) { + FluidDomainSettings_velocity_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { + FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_heat_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) { + FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_temperature_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else { + fprintf( + stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str()); + pixels[0] = 0.0f; + return false; + } +#endif + fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); + } + else { + /* We originally were passing view_layer here but in reality we need a + * a depsgraph to pass to the RE_point_density_minmax() function. + */ + /* TODO(sergey): Check we're indeed in shader node tree. */ + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); + BL::Node b_node(ptr); + if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { + BL::ShaderNodeTexPointDensity b_point_density_node(b_node); + int length; + b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels); + } + } + + return false; +} + +void BlenderSession::builtin_images_load() +{ + /* Force builtin images to be loaded along with Blender data sync. This + * is needed because we may be reading from depsgraph evaluated data which + * can be freed by Blender before Cycles reads it. + * + * TODO: the assumption that no further access to builtin image data will + * happen is really weak, and likely to break in the future. We should find + * a better solution to hand over the data directly to the image manager + * instead of through callbacks whose timing is difficult to control. */ + ImageManager *manager = session->scene->image_manager; + Device *device = session->device; + manager->device_load_builtin(device, session->scene, session->progress); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp new file mode 100644 index 00000000000..6f95821e31e --- /dev/null +++ b/intern/cycles/blender/blender_light.cpp @@ -0,0 +1,212 @@ + + +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/light.h" + +#include "blender/blender_sync.h" +#include "blender/blender_util.h" + +#include "util/util_hash.h" + +CCL_NAMESPACE_BEGIN + +void BlenderSync::sync_light(BL::Object &b_parent, + int persistent_id[OBJECT_PERSISTENT_ID_SIZE], + BL::Object &b_ob, + BL::Object &b_ob_instance, + int random_id, + Transform &tfm, + bool *use_portal) +{ + /* test if we need to sync */ + Light *light; + ObjectKey key(b_parent, persistent_id, b_ob_instance, false); + BL::Light b_light(b_ob.data()); + + /* Update if either object or light data changed. */ + if (!light_map.add_or_update(&light, b_ob, b_parent, key)) { + Shader *shader; + if (!shader_map.add_or_update(&shader, b_light)) { + if (light->is_portal) + *use_portal = true; + return; + } + } + + /* type */ + switch (b_light.type()) { + case BL::Light::type_POINT: { + BL::PointLight b_point_light(b_light); + light->size = b_point_light.shadow_soft_size(); + light->type = LIGHT_POINT; + break; + } + case BL::Light::type_SPOT: { + BL::SpotLight b_spot_light(b_light); + light->size = b_spot_light.shadow_soft_size(); + light->type = LIGHT_SPOT; + light->spot_angle = b_spot_light.spot_size(); + light->spot_smooth = b_spot_light.spot_blend(); + break; + } + /* Hemi were removed from 2.8 */ + // case BL::Light::type_HEMI: { + // light->type = LIGHT_DISTANT; + // light->size = 0.0f; + // break; + // } + case BL::Light::type_SUN: { + BL::SunLight b_sun_light(b_light); + light->angle = b_sun_light.angle(); + light->type = LIGHT_DISTANT; + break; + } + case BL::Light::type_AREA: { + BL::AreaLight b_area_light(b_light); + light->size = 1.0f; + light->axisu = transform_get_column(&tfm, 0); + light->axisv = transform_get_column(&tfm, 1); + light->sizeu = b_area_light.size(); + switch (b_area_light.shape()) { + case BL::AreaLight::shape_SQUARE: + light->sizev = light->sizeu; + light->round = false; + break; + case BL::AreaLight::shape_RECTANGLE: + light->sizev = b_area_light.size_y(); + light->round = false; + break; + case BL::AreaLight::shape_DISK: + light->sizev = light->sizeu; + light->round = true; + break; + case BL::AreaLight::shape_ELLIPSE: + light->sizev = b_area_light.size_y(); + light->round = true; + break; + } + light->type = LIGHT_AREA; + break; + } + } + + /* strength */ + light->strength = get_float3(b_light.color()); + light->strength *= BL::PointLight(b_light).energy(); + + /* location and (inverted!) direction */ + light->co = transform_get_column(&tfm, 3); + light->dir = -transform_get_column(&tfm, 2); + light->tfm = tfm; + + /* shader */ + vector<Shader *> used_shaders; + find_shader(b_light, used_shaders, scene->default_light); + light->shader = used_shaders[0]; + + /* shadow */ + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles"); + light->cast_shadow = get_boolean(clight, "cast_shadow"); + light->use_mis = get_boolean(clight, "use_multiple_importance_sampling"); + + int samples = get_int(clight, "samples"); + if (get_boolean(cscene, "use_square_samples")) + light->samples = samples * samples; + else + light->samples = samples; + + light->max_bounces = get_int(clight, "max_bounces"); + + if (b_ob != b_ob_instance) { + light->random_id = random_id; + } + else { + light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0); + } + + if (light->type == LIGHT_AREA) + light->is_portal = get_boolean(clight, "is_portal"); + else + light->is_portal = false; + + if (light->is_portal) + *use_portal = true; + + /* visibility */ + uint visibility = object_ray_visibility(b_ob); + light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; + light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0; + light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0; + light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0; + + /* tag */ + light->tag_update(scene); +} + +void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal) +{ + BL::World b_world = b_scene.world(); + + if (b_world) { + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); + + enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM }; + int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC); + bool sample_as_light = (sampling_method != SAMPLING_NONE); + + if (sample_as_light || use_portal) { + /* test if we need to sync */ + Light *light; + ObjectKey key(b_world, 0, b_world, false); + + if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc || + b_world.ptr.data != world_map) { + light->type = LIGHT_BACKGROUND; + if (sampling_method == SAMPLING_MANUAL) { + light->map_resolution = get_int(cworld, "sample_map_resolution"); + } + else { + light->map_resolution = 0; + } + light->shader = scene->default_background; + light->use_mis = sample_as_light; + light->max_bounces = get_int(cworld, "max_bounces"); + + /* force enable light again when world is resynced */ + light->is_enabled = true; + + int samples = get_int(cworld, "samples"); + if (get_boolean(cscene, "use_square_samples")) + light->samples = samples * samples; + else + light->samples = samples; + + light->tag_update(scene); + light_map.set_recalc(b_world); + } + } + } + + world_map = b_world.ptr.data; + world_recalc = false; + viewport_parameters = BlenderViewportParameters(b_v3d); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index b18f9a37948..332c26161dc 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -278,54 +278,6 @@ static void mikk_compute_tangents( genTangSpaceDefault(&context); } -/* Create Volume Attribute */ - -static void create_mesh_volume_attribute( - BL::Object &b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std, float frame) -{ - BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob); - - if (!b_domain) - return; - - mesh->volume_isovalue = b_domain.clipping(); - - Attribute *attr = mesh->attributes.add(std); - VoxelAttribute *volume_data = attr->data_voxel(); - ImageMetaData metadata; - bool animated = false; - - volume_data->manager = image_manager; - volume_data->slot = image_manager->add_image(Attribute::standard_name(std), - b_ob.ptr.data, - animated, - frame, - INTERPOLATION_LINEAR, - EXTENSION_CLIP, - IMAGE_ALPHA_AUTO, - u_colorspace_raw, - metadata); -} - -static void create_mesh_volume_attributes(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame) -{ - /* for smoke volume rendering */ - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame); - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame); - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame); - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame); - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE)) - create_mesh_volume_attribute( - b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame); - if (mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY)) - create_mesh_volume_attribute( - b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame); -} - /* Create vertex color attributes. */ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) { @@ -859,9 +811,9 @@ static void create_mesh(Scene *scene, attr_create_uv_map(scene, mesh, b_mesh); } - /* for volume objects, create a matrix to transform from object space to + /* For volume objects, create a matrix to transform from object space to * mesh texture space. this does not work with deformations but that can - * probably only be done well with a volume grid mapping of coordinates */ + * probably only be done well with a volume grid mapping of coordinates. */ if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) { Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM); Transform *tfm = attr->data_transform(); @@ -930,7 +882,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) if (scene->need_motion() == Scene::MOTION_NONE) return; - BL::FluidDomainSettings b_fluid_domain = object_fluid_domain_find(b_ob); + BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob); if (!b_fluid_domain) return; @@ -963,82 +915,8 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) } } -Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, - BL::Object &b_ob_instance, - bool object_updated, - bool show_self, - bool show_particles) +void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh) { - /* test if we can instance or if the object is modified */ - BL::ID b_ob_data = b_ob.data(); - BL::ID key = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; - BL::Material material_override = view_layer.material_override; - - /* find shader indices */ - vector<Shader *> used_shaders; - - BL::Object::material_slots_iterator slot; - for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { - if (material_override) { - find_shader(material_override, used_shaders, scene->default_surface); - } - else { - BL::ID b_material(slot->material()); - find_shader(b_material, used_shaders, scene->default_surface); - } - } - - if (used_shaders.size() == 0) { - if (material_override) - find_shader(material_override, used_shaders, scene->default_surface); - else - used_shaders.push_back(scene->default_surface); - } - - /* test if we need to sync */ - int requested_geometry_flags = Mesh::GEOMETRY_NONE; - if (view_layer.use_surfaces) { - requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; - } - if (view_layer.use_hair) { - requested_geometry_flags |= Mesh::GEOMETRY_CURVES; - } - Mesh *mesh; - - if (!mesh_map.sync(&mesh, key)) { - /* if transform was applied to mesh, need full update */ - if (object_updated && mesh->transform_applied) - ; - /* test if shaders changed, these can be object level so mesh - * does not get tagged for recalc */ - else if (mesh->used_shaders != used_shaders) - ; - else if (requested_geometry_flags != mesh->geometry_flags) - ; - else { - /* even if not tagged for recalc, we may need to sync anyway - * because the shader needs different mesh attributes */ - bool attribute_recalc = false; - - foreach (Shader *shader, mesh->used_shaders) - if (shader->need_update_mesh) - attribute_recalc = true; - - if (!attribute_recalc) - return mesh; - } - } - - /* ensure we only sync instanced meshes once */ - if (mesh_synced.find(mesh) != mesh_synced.end()) - return mesh; - - progress.set_sync_status("Synchronizing object", b_ob.name()); - - mesh_synced.insert(mesh); - - /* create derived mesh */ array<int> oldtriangles; array<Mesh::SubdFace> oldsubd_faces; array<int> oldsubd_face_corners; @@ -1046,150 +924,64 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph, oldsubd_faces.steal_data(mesh->subd_faces); oldsubd_face_corners.steal_data(mesh->subd_face_corners); - /* compares curve_keys rather than strands in order to handle quick hair - * adjustments in dynamic BVH - other methods could probably do this better*/ - array<float3> oldcurve_keys; - array<float> oldcurve_radius; - oldcurve_keys.steal_data(mesh->curve_keys); - oldcurve_radius.steal_data(mesh->curve_radius); - - /* ensure bvh rebuild (instead of refit) if has_voxel_attributes() changed */ - bool oldhas_voxel_attributes = mesh->has_voxel_attributes(); - - mesh->clear(); - mesh->used_shaders = used_shaders; - mesh->name = ustring(b_ob_data.name().c_str()); + mesh->subdivision_type = Mesh::SUBDIVISION_NONE; - if (requested_geometry_flags != Mesh::GEOMETRY_NONE) { + if (view_layer.use_surfaces) { /* Adaptive subdivision setup. Not for baking since that requires * exact mapping to the Blender mesh. */ - if (scene->bake_manager->get_baking()) { - mesh->subdivision_type = Mesh::SUBDIVISION_NONE; - } - else { + if (!scene->bake_manager->get_baking()) { mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental); } /* For some reason, meshes do not need this... */ bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); - BL::Mesh b_mesh = object_to_mesh( b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type); if (b_mesh) { /* Sync mesh itself. */ - if (view_layer.use_surfaces && show_self) { - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) - create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions); - else - create_mesh(scene, mesh, b_mesh, used_shaders, false); - - create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); - } - - /* Sync hair curves. */ - if (view_layer.use_hair && show_particles && - mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { - sync_curves(mesh, b_mesh, b_ob, false); - } + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) + create_subd_mesh( + scene, mesh, b_ob, b_mesh, mesh->used_shaders, dicing_rate, max_subdivisions); + else + create_mesh(scene, mesh, b_mesh, mesh->used_shaders, false); free_object_to_mesh(b_data, b_ob, b_mesh); } } - mesh->geometry_flags = requested_geometry_flags; /* mesh fluid motion mantaflow */ sync_mesh_fluid_motion(b_ob, scene, mesh); /* tag update */ bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) || - (oldsubd_face_corners != mesh->subd_face_corners) || - (oldcurve_keys != mesh->curve_keys) || (oldcurve_radius != mesh->curve_radius) || - (oldhas_voxel_attributes != mesh->has_voxel_attributes()); + (oldsubd_face_corners != mesh->subd_face_corners); mesh->tag_update(scene, rebuild); - - return mesh; } -void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, - Object *object, - float motion_time) +void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Mesh *mesh, + int motion_step) { - /* ensure we only sync instanced meshes once */ - Mesh *mesh = object->mesh; - - if (mesh_motion_synced.find(mesh) != mesh_motion_synced.end()) - return; - - mesh_motion_synced.insert(mesh); - - /* ensure we only motion sync meshes that also had mesh synced, to avoid - * unnecessary work and to ensure that its attributes were clear */ - if (mesh_synced.find(mesh) == mesh_synced.end()) - return; - - /* Find time matching motion step required by mesh. */ - int motion_step = mesh->motion_step(motion_time); - if (motion_step < 0) { + /* Skip if no vertices were exported. */ + size_t numverts = mesh->verts.size(); + if (numverts == 0) { return; } - /* skip empty meshes */ - const size_t numverts = mesh->verts.size(); - const size_t numkeys = mesh->curve_keys.size(); - - if (!numverts && !numkeys) - return; - - /* skip objects without deforming modifiers. this is not totally reliable, - * would need a more extensive check to see which objects are animated */ + /* Skip objects without deforming modifiers. this is not totally reliable, + * would need a more extensive check to see which objects are animated. */ BL::Mesh b_mesh(PointerRNA_NULL); - - /* manta motion is exported immediate with mesh, skip here */ - BL::FluidDomainSettings b_fluid_domain = object_fluid_domain_find(b_ob); - if (b_fluid_domain) - return; - if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { /* get derived mesh */ b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE); } - if (!b_mesh) { - /* if we have no motion blur on this frame, but on other frames, copy */ - if (numverts) { - /* triangles */ - Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (attr_mP) { - Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); - Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); - float3 *P = &mesh->verts[0]; - float3 *N = (attr_N) ? attr_N->data_float3() : NULL; - - memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts); - if (attr_mN) - memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts); - } - } - - if (numkeys) { - /* curves */ - Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (attr_mP) { - float3 *keys = &mesh->curve_keys[0]; - memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys); - } - } - - return; - } - /* TODO(sergey): Perform preliminary check for number of vertices. */ - if (numverts) { + if (b_mesh) { + /* Export deformed coordinates. */ /* Find attributes. */ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); @@ -1254,14 +1046,13 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph, } } } - } - /* hair motion */ - if (numkeys) - sync_curves(mesh, b_mesh, b_ob, true, motion_step); + free_object_to_mesh(b_data, b_ob, b_mesh); + return; + } - /* free derived mesh */ - free_object_to_mesh(b_data, b_ob, b_mesh); + /* No deformation on this frame, copy coordinates if other frames did have it. */ + mesh->copy_center_to_motion_step(motion_step); } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 6981412bb88..2b1d1eff7e5 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -88,215 +88,13 @@ bool BlenderSync::object_is_light(BL::Object &b_ob) return (b_ob_data && b_ob_data.is_a(&RNA_Light)); } -static uint object_ray_visibility(BL::Object &b_ob) -{ - PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility"); - uint flag = 0; - - flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0; - flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0; - flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0; - flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0; - flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0; - flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0; - - return flag; -} - -/* Light */ - -void BlenderSync::sync_light(BL::Object &b_parent, - int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::Object &b_ob, - BL::Object &b_ob_instance, - int random_id, - Transform &tfm, - bool *use_portal) -{ - /* test if we need to sync */ - Light *light; - ObjectKey key(b_parent, persistent_id, b_ob_instance); - BL::Light b_light(b_ob.data()); - - /* Update if either object or light data changed. */ - if (!light_map.sync(&light, b_ob, b_parent, key)) { - Shader *shader; - if (!shader_map.sync(&shader, b_light)) { - if (light->is_portal) - *use_portal = true; - return; - } - } - - /* type */ - switch (b_light.type()) { - case BL::Light::type_POINT: { - BL::PointLight b_point_light(b_light); - light->size = b_point_light.shadow_soft_size(); - light->type = LIGHT_POINT; - break; - } - case BL::Light::type_SPOT: { - BL::SpotLight b_spot_light(b_light); - light->size = b_spot_light.shadow_soft_size(); - light->type = LIGHT_SPOT; - light->spot_angle = b_spot_light.spot_size(); - light->spot_smooth = b_spot_light.spot_blend(); - break; - } - /* Hemi were removed from 2.8 */ - // case BL::Light::type_HEMI: { - // light->type = LIGHT_DISTANT; - // light->size = 0.0f; - // break; - // } - case BL::Light::type_SUN: { - BL::SunLight b_sun_light(b_light); - light->angle = b_sun_light.angle(); - light->type = LIGHT_DISTANT; - break; - } - case BL::Light::type_AREA: { - BL::AreaLight b_area_light(b_light); - light->size = 1.0f; - light->axisu = transform_get_column(&tfm, 0); - light->axisv = transform_get_column(&tfm, 1); - light->sizeu = b_area_light.size(); - switch (b_area_light.shape()) { - case BL::AreaLight::shape_SQUARE: - light->sizev = light->sizeu; - light->round = false; - break; - case BL::AreaLight::shape_RECTANGLE: - light->sizev = b_area_light.size_y(); - light->round = false; - break; - case BL::AreaLight::shape_DISK: - light->sizev = light->sizeu; - light->round = true; - break; - case BL::AreaLight::shape_ELLIPSE: - light->sizev = b_area_light.size_y(); - light->round = true; - break; - } - light->type = LIGHT_AREA; - break; - } - } - - /* strength */ - light->strength = get_float3(b_light.color()); - light->strength *= BL::PointLight(b_light).energy(); - - /* location and (inverted!) direction */ - light->co = transform_get_column(&tfm, 3); - light->dir = -transform_get_column(&tfm, 2); - light->tfm = tfm; - - /* shader */ - vector<Shader *> used_shaders; - find_shader(b_light, used_shaders, scene->default_light); - light->shader = used_shaders[0]; - - /* shadow */ - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles"); - light->cast_shadow = get_boolean(clight, "cast_shadow"); - light->use_mis = get_boolean(clight, "use_multiple_importance_sampling"); - - int samples = get_int(clight, "samples"); - if (get_boolean(cscene, "use_square_samples")) - light->samples = samples * samples; - else - light->samples = samples; - - light->max_bounces = get_int(clight, "max_bounces"); - - if (b_ob != b_ob_instance) { - light->random_id = random_id; - } - else { - light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0); - } - - if (light->type == LIGHT_AREA) - light->is_portal = get_boolean(clight, "is_portal"); - else - light->is_portal = false; - - if (light->is_portal) - *use_portal = true; - - /* visibility */ - uint visibility = object_ray_visibility(b_ob); - light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; - light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0; - light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0; - light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0; - - /* tag */ - light->tag_update(scene); -} - -void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal) -{ - BL::World b_world = b_scene.world(); - - if (b_world) { - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); - - enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM }; - int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC); - bool sample_as_light = (sampling_method != SAMPLING_NONE); - - if (sample_as_light || use_portal) { - /* test if we need to sync */ - Light *light; - ObjectKey key(b_world, 0, b_world); - - if (light_map.sync(&light, b_world, b_world, key) || world_recalc || - b_world.ptr.data != world_map) { - light->type = LIGHT_BACKGROUND; - if (sampling_method == SAMPLING_MANUAL) { - light->map_resolution = get_int(cworld, "sample_map_resolution"); - } - else { - light->map_resolution = 0; - } - light->shader = scene->default_background; - light->use_mis = sample_as_light; - light->max_bounces = get_int(cworld, "max_bounces"); - - /* force enable light again when world is resynced */ - light->is_enabled = true; - - int samples = get_int(cworld, "samples"); - if (get_boolean(cscene, "use_square_samples")) - light->samples = samples * samples; - else - light->samples = samples; - - light->tag_update(scene); - light_map.set_recalc(b_world); - } - } - } - - world_map = b_world.ptr.data; - world_recalc = false; - viewport_parameters = BlenderViewportParameters(b_v3d); -} - /* Object */ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, BL::ViewLayer &b_view_layer, BL::DepsgraphObjectInstance &b_instance, float motion_time, - bool show_self, - bool show_particles, + bool use_particle_hair, bool show_lights, BlenderObjectCulling &culling, bool *use_portal) @@ -378,7 +176,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, } /* key to lookup object */ - ObjectKey key(b_parent, persistent_id, b_ob_instance); + ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair); Object *object; /* motion vector case */ @@ -393,8 +191,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, } /* mesh deformation */ - if (object->mesh) - sync_mesh_motion(b_depsgraph, b_ob, object, motion_time); + if (object->geometry) + sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair); } return object; @@ -403,12 +201,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* test if we need to sync */ bool object_updated = false; - if (object_map.sync(&object, b_ob, b_parent, key)) + if (object_map.add_or_update(&object, b_ob, b_parent, key)) object_updated = true; /* mesh sync */ - object->mesh = sync_mesh( - b_depsgraph, b_ob, b_ob_instance, object_updated, show_self, show_particles); + object->geometry = sync_geometry( + b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair); /* special case not tracked by object update flags */ @@ -450,7 +248,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* object sync * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ - if (object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { + if (object_updated || (object->geometry && object->geometry->need_update) || + tfm != object->tfm) { object->name = b_ob.name().c_str(); object->pass_id = b_ob.pass_index(); object->color = get_float3(b_ob.color()); @@ -459,23 +258,23 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* motion blur */ Scene::MotionType need_motion = scene->need_motion(); - if (need_motion != Scene::MOTION_NONE && object->mesh) { - Mesh *mesh = object->mesh; - mesh->use_motion_blur = false; - mesh->motion_steps = 0; + if (need_motion != Scene::MOTION_NONE && object->geometry) { + Geometry *geom = object->geometry; + geom->use_motion_blur = false; + geom->motion_steps = 0; uint motion_steps; if (need_motion == Scene::MOTION_BLUR) { motion_steps = object_motion_steps(b_parent, b_ob); - mesh->motion_steps = motion_steps; + geom->motion_steps = motion_steps; if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { - mesh->use_motion_blur = true; + geom->use_motion_blur = true; } } else { motion_steps = 3; - mesh->motion_steps = motion_steps; + geom->motion_steps = motion_steps; } object->motion.clear(); @@ -526,13 +325,13 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, if (!motion) { /* prepare for sync */ light_map.pre_sync(); - mesh_map.pre_sync(); + geometry_map.pre_sync(); object_map.pre_sync(); particle_system_map.pre_sync(); motion_times.clear(); } else { - mesh_motion_synced.clear(); + geometry_motion_synced.clear(); } /* initialize culling */ @@ -552,22 +351,34 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, BL::DepsgraphObjectInstance b_instance = *b_instance_iter; BL::Object b_ob = b_instance.object(); - /* load per-object culling data */ + /* Viewport visibility. */ + const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d); + if (show_in_viewport == false) { + continue; + } + + /* Load per-object culling data. */ culling.init_object(scene, b_ob); - /* test if object needs to be hidden */ - const bool show_self = b_instance.show_self(); - const bool show_particles = b_instance.show_particles(); - const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d); + /* Object itself. */ + if (b_instance.show_self()) { + sync_object(b_depsgraph, + b_view_layer, + b_instance, + motion_time, + false, + show_lights, + culling, + &use_portal); + } - if (show_in_viewport && (show_self || show_particles)) { - /* object itself */ + /* Particle hair as separate object. */ + if (b_instance.show_particles() && object_has_particle_hair(b_ob)) { sync_object(b_depsgraph, b_view_layer, b_instance, motion_time, - show_self, - show_particles, + true, show_lights, culling, &use_portal); @@ -584,8 +395,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, /* handle removed data and modified pointers */ if (light_map.post_sync()) scene->light_manager->tag_update(scene); - if (mesh_map.post_sync()) - scene->mesh_manager->tag_update(scene); + if (geometry_map.post_sync()) + scene->geometry_manager->tag_update(scene); if (object_map.post_sync()) scene->object_manager->tag_update(scene); if (particle_system_map.post_sync()) @@ -593,7 +404,7 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, } if (motion) - mesh_motion_synced.clear(); + geometry_motion_synced.clear(); } void BlenderSync::sync_motion(BL::RenderSettings &b_render, diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp index 74f8fb1dc53..bebecb364eb 100644 --- a/intern/cycles/blender/blender_object_cull.cpp +++ b/intern/cycles/blender/blender_object_cull.cpp @@ -19,6 +19,7 @@ #include "render/camera.h" #include "blender/blender_object_cull.h" +#include "blender/blender_util.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index d74f132ed60..e5eab1ae62b 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -39,7 +39,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, object->hide_on_missing_motion = true; /* test if we need particle data */ - if (!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + if (!object->geometry->need_attribute(scene, ATTR_STD_PARTICLE)) return false; /* don't handle child particles yet */ @@ -53,10 +53,10 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, ParticleSystem *psys; bool first_use = !particle_system_map.is_used(key); - bool need_update = particle_system_map.sync(&psys, b_ob, b_instance.object(), key); + bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key); /* no update needed? */ - if (!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update) return true; /* first time used in this sync loop? clear and tag update */ diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 335d4daf09c..816b4552fff 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -21,6 +21,7 @@ #include "blender/blender_device.h" #include "blender/blender_sync.h" #include "blender/blender_session.h" +#include "blender/blender_util.h" #include "render/denoising.h" #include "render/merge.h" diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index e2dea24fdd1..1490348743e 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -720,9 +720,12 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, int tri_offset = 0; for (size_t i = 0; i < scene->objects.size(); i++) { - if (strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) { + const Object *object = scene->objects[i]; + const Geometry *geom = object->geometry; + if (object->name == b_object.name() && geom->type == Geometry::MESH) { + const Mesh *mesh = static_cast<const Mesh *>(geom); object_index = i; - tri_offset = scene->objects[i]->mesh->tri_offset; + tri_offset = mesh->prim_offset; break; } } @@ -1112,341 +1115,6 @@ void BlenderSession::test_cancel() session->progress.set_cancel("Cancelled"); } -/* builtin image file name is actually an image datablock name with - * absolute sequence frame number concatenated via '@' character - * - * this function splits frame from builtin name - */ -int BlenderSession::builtin_image_frame(const string &builtin_name) -{ - int last = builtin_name.find_last_of('@'); - return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str()); -} - -void BlenderSession::builtin_image_info(const string &builtin_name, - void *builtin_data, - ImageMetaData &metadata) -{ - /* empty image */ - metadata.width = 1; - metadata.height = 1; - - if (!builtin_data) - return; - - /* recover ID pointer */ - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::ID b_id(ptr); - - if (b_id.is_a(&RNA_Image)) { - /* image data */ - BL::Image b_image(b_id); - - metadata.builtin_free_cache = !b_image.has_data(); - metadata.is_float = b_image.is_float(); - metadata.width = b_image.size()[0]; - metadata.height = b_image.size()[1]; - metadata.depth = 1; - metadata.channels = b_image.channels(); - - if (metadata.is_float) { - /* Float images are already converted on the Blender side, - * no need to do anything in Cycles. */ - metadata.colorspace = u_colorspace_raw; - } - } - else if (b_id.is_a(&RNA_Object)) { - /* smoke volume data */ - BL::Object b_ob(b_id); - BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob); - - metadata.is_float = true; - metadata.depth = 1; - metadata.channels = 1; - - if (!b_domain) - return; - - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) - metadata.channels = 1; - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) - metadata.channels = 4; - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) - metadata.channels = 3; - else - return; - - int3 resolution = get_int3(b_domain.domain_resolution()); - int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; - - /* Velocity and heat data is always low-resolution. */ - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - amplify = 1; - } - - metadata.width = resolution.x * amplify; - metadata.height = resolution.y * amplify; - metadata.depth = resolution.z * amplify; - } - else { - /* TODO(sergey): Check we're indeed in shader node tree. */ - PointerRNA ptr; - RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); - BL::Node b_node(ptr); - if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { - BL::ShaderNodeTexPointDensity b_point_density_node(b_node); - metadata.channels = 4; - metadata.width = b_point_density_node.resolution(); - metadata.height = metadata.width; - metadata.depth = metadata.width; - metadata.is_float = true; - } - } -} - -bool BlenderSession::builtin_image_pixels(const string &builtin_name, - void *builtin_data, - int tile, - unsigned char *pixels, - const size_t pixels_size, - const bool associate_alpha, - const bool free_cache) -{ - if (!builtin_data) { - return false; - } - - const int frame = builtin_image_frame(builtin_name); - - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::Image b_image(ptr); - - const int width = b_image.size()[0]; - const int height = b_image.size()[1]; - const int channels = b_image.channels(); - - unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile); - const size_t num_pixels = ((size_t)width) * height; - - if (image_pixels && num_pixels * channels == pixels_size) { - memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char)); - } - else { - if (channels == 1) { - memset(pixels, 0, pixels_size * sizeof(unsigned char)); - } - else { - const size_t num_pixels_safe = pixels_size / channels; - unsigned char *cp = pixels; - for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) { - cp[0] = 255; - cp[1] = 0; - cp[2] = 255; - if (channels == 4) { - cp[3] = 255; - } - } - } - } - - if (image_pixels) { - MEM_freeN(image_pixels); - } - - /* Free image buffers to save memory during render. */ - if (free_cache) { - b_image.buffers_free(); - } - - if (associate_alpha) { - /* Premultiply, byte images are always straight for Blender. */ - unsigned char *cp = pixels; - for (size_t i = 0; i < num_pixels; i++, cp += channels) { - cp[0] = (cp[0] * cp[3]) >> 8; - cp[1] = (cp[1] * cp[3]) >> 8; - cp[2] = (cp[2] * cp[3]) >> 8; - } - } - return true; -} - -bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, - void *builtin_data, - int tile, - float *pixels, - const size_t pixels_size, - const bool, - const bool free_cache) -{ - if (!builtin_data) { - return false; - } - - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::ID b_id(ptr); - - if (b_id.is_a(&RNA_Image)) { - /* image data */ - BL::Image b_image(b_id); - int frame = builtin_image_frame(builtin_name); - - const int width = b_image.size()[0]; - const int height = b_image.size()[1]; - const int channels = b_image.channels(); - - float *image_pixels; - image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile); - const size_t num_pixels = ((size_t)width) * height; - - if (image_pixels && num_pixels * channels == pixels_size) { - memcpy(pixels, image_pixels, pixels_size * sizeof(float)); - } - else { - if (channels == 1) { - memset(pixels, 0, num_pixels * sizeof(float)); - } - else { - const size_t num_pixels_safe = pixels_size / channels; - float *fp = pixels; - for (int i = 0; i < num_pixels_safe; i++, fp += channels) { - fp[0] = 1.0f; - fp[1] = 0.0f; - fp[2] = 1.0f; - if (channels == 4) { - fp[3] = 1.0f; - } - } - } - } - - if (image_pixels) { - MEM_freeN(image_pixels); - } - - /* Free image buffers to save memory during render. */ - if (free_cache) { - b_image.buffers_free(); - } - - return true; - } - else if (b_id.is_a(&RNA_Object)) { - /* smoke volume data */ - BL::Object b_ob(b_id); - BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob); - - if (!b_domain) { - return false; - } -#if WITH_FLUID - int3 resolution = get_int3(b_domain.domain_resolution()); - int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; - - /* Velocity and heat data is always low-resolution. */ - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - amplify = 1; - } - - const int width = resolution.x * amplify; - const int height = resolution.y * amplify; - const int depth = resolution.z * amplify; - const size_t num_pixels = ((size_t)width) * height * depth; - - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { - FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_density_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) { - /* this is in range 0..1, and interpreted by the OpenGL smoke viewer - * as 1500..3000 K with the first part faded to zero density */ - FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_flame_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { - /* the RGB is "premultiplied" by density for better interpolation results */ - FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels * 4) { - FluidDomainSettings_color_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) { - FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels * 3) { - FluidDomainSettings_velocity_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_heat_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) { - FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_temperature_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else { - fprintf( - stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str()); - pixels[0] = 0.0f; - return false; - } -#endif - fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); - } - else { - /* We originally were passing view_layer here but in reality we need a - * a depsgraph to pass to the RE_point_density_minmax() function. - */ - /* TODO(sergey): Check we're indeed in shader node tree. */ - PointerRNA ptr; - RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); - BL::Node b_node(ptr); - if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { - BL::ShaderNodeTexPointDensity b_point_density_node(b_node); - int length; - b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels); - } - } - - return false; -} - -void BlenderSession::builtin_images_load() -{ - /* Force builtin images to be loaded along with Blender data sync. This - * is needed because we may be reading from depsgraph evaluated data which - * can be freed by Blender before Cycles reads it. - * - * TODO: the assumption that no further access to builtin image data will - * happen is really weak, and likely to break in the future. We should find - * a better solution to hand over the data directly to the image manager - * instead of through callbacks whose timing is difficult to control. */ - ImageManager *manager = session->scene->image_manager; - Device *device = session->device; - manager->device_load_builtin(device, session->scene, session->progress); -} - void BlenderSession::update_resumable_tile_manager(int num_samples) { const int num_resumable_chunks = BlenderSession::num_resumable_chunks, diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 206058259af..635405e42c7 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -1255,7 +1255,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) Shader *shader; /* test if we need to sync */ - if (shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) { + if (shader_map.add_or_update(&shader, b_mat) || shader->need_sync_object || update_all) { ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat.name().c_str(); @@ -1480,7 +1480,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all) Shader *shader; /* test if we need to sync */ - if (shader_map.sync(&shader, b_light) || update_all) { + if (shader_map.add_or_update(&shader, b_light) || update_all) { ShaderGraph *graph = new ShaderGraph(); /* create nodes */ diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 20dbe23cdb7..8960c84567e 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -56,7 +56,7 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine, b_scene(b_scene), shader_map(&scene->shaders), object_map(&scene->objects), - mesh_map(&scene->meshes), + geometry_map(&scene->geometry), light_map(&scene->lights), particle_system_map(&scene->particle_systems), world_map(NULL), @@ -108,10 +108,15 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d } if (dicing_prop_changed) { - for (const pair<void *, Mesh *> &iter : mesh_map.key_to_scene_data()) { - Mesh *mesh = iter.second; - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { - mesh_map.set_recalc(iter.first); + for (const pair<GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) { + Geometry *geom = iter.second; + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + PointerRNA id_ptr; + RNA_id_pointer_create((::ID *)iter.first.id, &id_ptr); + geometry_map.set_recalc(BL::ID(id_ptr)); + } } } } @@ -146,7 +151,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d if (updated_geometry || (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) { BL::ID key = BKE_object_is_modified(b_ob) ? b_ob : b_ob.data(); - mesh_map.set_recalc(key); + geometry_map.set_recalc(key); } } else if (object_is_light(b_ob)) { @@ -164,7 +169,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d /* Mesh */ else if (b_id.is_a(&RNA_Mesh)) { BL::Mesh b_mesh(b_id); - mesh_map.set_recalc(b_mesh); + geometry_map.set_recalc(b_mesh); } /* World */ else if (b_id.is_a(&RNA_World)) { @@ -211,7 +216,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, sync_images(); sync_curve_settings(); - mesh_synced.clear(); /* use for objects and motion sync */ + geometry_synced.clear(); /* use for objects and motion sync */ if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE || scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) { @@ -219,7 +224,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, } sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state); - mesh_synced.clear(); + geometry_synced.clear(); /* Shader sync done at the end, since object sync uses it. * false = don't delete unused shaders, not supported. */ diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index a80f484fb92..f8134ff8b5c 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -22,7 +22,7 @@ #include "RNA_access.h" #include "RNA_blender_cpp.h" -#include "blender/blender_util.h" +#include "blender/blender_id_map.h" #include "blender/blender_viewport.h" #include "render/scene.h" @@ -40,6 +40,7 @@ class BlenderObjectCulling; class BlenderViewportParameters; class Camera; class Film; +class Hair; class Light; class Mesh; class Object; @@ -118,28 +119,57 @@ class BlenderSync { void **python_thread_state); void sync_film(BL::SpaceView3D &b_v3d); void sync_view(); + + /* Shader */ void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all); void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d); - void sync_curve_settings(); - void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree); - Mesh *sync_mesh(BL::Depsgraph &b_depsgrpah, - BL::Object &b_ob, - BL::Object &b_ob_instance, - bool object_updated, - bool show_self, - bool show_particles); - void sync_curves( - Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0); + + /* Object */ Object *sync_object(BL::Depsgraph &b_depsgraph, BL::ViewLayer &b_view_layer, BL::DepsgraphObjectInstance &b_instance, float motion_time, - bool show_self, - bool show_particles, + bool use_particle_hair, bool show_lights, BlenderObjectCulling &culling, bool *use_portal); + + /* Volume */ + void sync_volume(BL::Object &b_ob, Mesh *mesh); + + /* Mesh */ + void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh); + void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step); + + /* Hair */ + void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom); + void sync_hair_motion(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Geometry *geom, + int motion_step); + void sync_particle_hair( + Geometry *geom, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0); + void sync_curve_settings(); + bool object_has_particle_hair(BL::Object b_ob); + + /* Camera */ + void sync_camera_motion( + BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time); + + /* Geometry */ + Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah, + BL::Object &b_ob, + BL::Object &b_ob_instance, + bool object_updated, + bool use_particle_hair); + void sync_geometry_motion(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, + Object *object, + float motion_time, + bool use_particle_hair); + + /* Light */ void sync_light(BL::Object &b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object &b_ob, @@ -148,14 +178,8 @@ class BlenderSync { Transform &tfm, bool *use_portal); void sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal); - void sync_mesh_motion(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, - Object *object, - float motion_time); - void sync_camera_motion( - BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time); - /* particles */ + /* Particles */ bool sync_dupli_particle(BL::Object &b_ob, BL::DepsgraphObjectInstance &b_instance, Object *object); @@ -179,11 +203,11 @@ class BlenderSync { id_map<void *, Shader> shader_map; id_map<ObjectKey, Object> object_map; - id_map<void *, Mesh> mesh_map; + id_map<GeometryKey, Geometry> geometry_map; id_map<ObjectKey, Light> light_map; id_map<ParticleSystemKey, ParticleSystem> particle_system_map; - set<Mesh *> mesh_synced; - set<Mesh *> mesh_motion_synced; + set<Geometry *> geometry_synced; + set<Geometry *> geometry_motion_synced; set<float> motion_times; void *world_map; bool world_recalc; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index bea30a20b8c..cb7d1c62f60 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -531,7 +531,7 @@ static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ return use_deform_motion; } -static inline BL::FluidDomainSettings object_fluid_domain_find(BL::Object &b_ob) +static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object &b_ob) { BL::Object::modifiers_iterator b_mod; @@ -539,8 +539,28 @@ static inline BL::FluidDomainSettings object_fluid_domain_find(BL::Object &b_ob) if (b_mod->is_a(&RNA_FluidModifier)) { BL::FluidModifier b_mmd(*b_mod); - if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN) + if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN && + b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_LIQUID) { return b_mmd.domain_settings(); + } + } + } + + return BL::FluidDomainSettings(PointerRNA_NULL); +} + +static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob) +{ + BL::Object::modifiers_iterator b_mod; + + for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { + if (b_mod->is_a(&RNA_FluidModifier)) { + BL::FluidModifier b_mmd(*b_mod); + + if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN && + b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_GAS) { + return b_mmd.domain_settings(); + } } } @@ -573,209 +593,20 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, return Mesh::SUBDIVISION_NONE; } -/* ID Map - * - * Utility class to keep in sync with blender data. - * Used for objects, meshes, lights and shaders. */ - -template<typename K, typename T> class id_map { - public: - id_map(vector<T *> *scene_data_) - { - scene_data = scene_data_; - } - - T *find(const BL::ID &id) - { - return find(id.ptr.owner_id); - } - - T *find(const K &key) - { - if (b_map.find(key) != b_map.end()) { - T *data = b_map[key]; - return data; - } - - return NULL; - } - - void set_recalc(const BL::ID &id) - { - b_recalc.insert(id.ptr.data); - } - - void set_recalc(void *id_ptr) - { - b_recalc.insert(id_ptr); - } - - bool has_recalc() - { - return !(b_recalc.empty()); - } - - void pre_sync() - { - used_set.clear(); - } - - bool sync(T **r_data, const BL::ID &id) - { - return sync(r_data, id, id, id.ptr.owner_id); - } - - bool sync(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key) - { - T *data = find(key); - bool recalc; - - if (!data) { - /* add data if it didn't exist yet */ - data = new T(); - scene_data->push_back(data); - b_map[key] = data; - recalc = true; - } - else { - recalc = (b_recalc.find(id.ptr.data) != b_recalc.end()); - if (parent.ptr.data) - recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end()); - } - - used(data); - - *r_data = data; - return recalc; - } - - bool is_used(const K &key) - { - T *data = find(key); - return (data) ? used_set.find(data) != used_set.end() : false; - } - - void used(T *data) - { - /* tag data as still in use */ - used_set.insert(data); - } - - void set_default(T *data) - { - b_map[NULL] = data; - } - - bool post_sync(bool do_delete = true) - { - /* remove unused data */ - vector<T *> new_scene_data; - typename vector<T *>::iterator it; - bool deleted = false; - - for (it = scene_data->begin(); it != scene_data->end(); it++) { - T *data = *it; - - if (do_delete && used_set.find(data) == used_set.end()) { - delete data; - deleted = true; - } - else - new_scene_data.push_back(data); - } - - *scene_data = new_scene_data; - - /* update mapping */ - map<K, T *> new_map; - typedef pair<const K, T *> TMapPair; - typename map<K, T *>::iterator jt; - - for (jt = b_map.begin(); jt != b_map.end(); jt++) { - TMapPair &pair = *jt; - - if (used_set.find(pair.second) != used_set.end()) - new_map[pair.first] = pair.second; - } - - used_set.clear(); - b_recalc.clear(); - b_map = new_map; - - return deleted; - } - - const map<K, T *> &key_to_scene_data() - { - return b_map; - } - - protected: - vector<T *> *scene_data; - map<K, T *> b_map; - set<T *> used_set; - set<void *> b_recalc; -}; - -/* Object Key */ - -enum { OBJECT_PERSISTENT_ID_SIZE = 16 }; - -struct ObjectKey { - void *parent; - int id[OBJECT_PERSISTENT_ID_SIZE]; - void *ob; - - ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_) - : parent(parent_), ob(ob_) - { - if (id_) - memcpy(id, id_, sizeof(id)); - else - memset(id, 0, sizeof(id)); - } - - bool operator<(const ObjectKey &k) const - { - if (ob < k.ob) { - return true; - } - else if (ob == k.ob) { - if (parent < k.parent) - return true; - else if (parent == k.parent) - return memcmp(id, k.id, sizeof(id)) < 0; - } - - return false; - } -}; - -/* Particle System Key */ - -struct ParticleSystemKey { - void *ob; - int id[OBJECT_PERSISTENT_ID_SIZE]; - - ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_) - { - if (id_) - memcpy(id, id_, sizeof(id)); - else - memset(id, 0, sizeof(id)); - } +static inline uint object_ray_visibility(BL::Object &b_ob) +{ + PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility"); + uint flag = 0; - bool operator<(const ParticleSystemKey &k) const - { - /* first id is particle index, we don't compare that */ - if (ob < k.ob) - return true; - else if (ob == k.ob) - return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0; + flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0; + flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0; + flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0; + flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0; + flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0; + flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0; - return false; - } -}; + return flag; +} class EdgeMap { public: diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp new file mode 100644 index 00000000000..87fb9620725 --- /dev/null +++ b/intern/cycles/blender/blender_volume.cpp @@ -0,0 +1,95 @@ + +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/colorspace.h" +#include "render/mesh.h" +#include "render/object.h" + +#include "blender/blender_sync.h" +#include "blender/blender_util.h" + +CCL_NAMESPACE_BEGIN + +static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame) +{ + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + if (!b_domain) { + return; + } + + ImageManager *image_manager = scene->image_manager; + AttributeStandard attributes[] = {ATTR_STD_VOLUME_DENSITY, + ATTR_STD_VOLUME_COLOR, + ATTR_STD_VOLUME_FLAME, + ATTR_STD_VOLUME_HEAT, + ATTR_STD_VOLUME_TEMPERATURE, + ATTR_STD_VOLUME_VELOCITY, + ATTR_STD_NONE}; + + for (int i = 0; attributes[i] != ATTR_STD_NONE; i++) { + AttributeStandard std = attributes[i]; + if (!mesh->need_attribute(scene, std)) { + continue; + } + + mesh->volume_isovalue = b_domain.clipping(); + + Attribute *attr = mesh->attributes.add(std); + VoxelAttribute *volume_data = attr->data_voxel(); + ImageMetaData metadata; + bool animated = false; + + volume_data->manager = image_manager; + volume_data->slot = image_manager->add_image(Attribute::standard_name(std), + b_ob.ptr.data, + animated, + frame, + INTERPOLATION_LINEAR, + EXTENSION_CLIP, + IMAGE_ALPHA_AUTO, + u_colorspace_raw, + metadata); + } + + /* Create a matrix to transform from object space to mesh texture space. + * This does not work with deformations but that can probably only be done + * well with a volume grid mapping of coordinates. */ + if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM); + Transform *tfm = attr->data_transform(); + + BL::Mesh b_mesh(b_ob.data()); + float3 loc, size; + mesh_texture_space(b_mesh, loc, size); + + *tfm = transform_translate(-loc) * transform_scale(size); + } +} + +void BlenderSync::sync_volume(BL::Object &b_ob, Mesh *mesh) +{ + bool old_has_voxel_attributes = mesh->has_voxel_attributes(); + + /* Smoke domain. */ + sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current()); + + /* Tag update. */ + bool rebuild = (old_has_voxel_attributes != mesh->has_voxel_attributes()); + mesh->tag_update(scene, rebuild); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 16c721da06a..3a8b0fe7fa2 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -17,6 +17,7 @@ #include "bvh/bvh.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/object.h" @@ -99,31 +100,33 @@ int BVHStackEntry::encodeIdx() const /* BVH */ -BVH::BVH(const BVHParams ¶ms_, const vector<Mesh *> &meshes_, const vector<Object *> &objects_) - : params(params_), meshes(meshes_), objects(objects_) +BVH::BVH(const BVHParams ¶ms_, + const vector<Geometry *> &geometry_, + const vector<Object *> &objects_) + : params(params_), geometry(geometry_), objects(objects_) { } BVH *BVH::create(const BVHParams ¶ms, - const vector<Mesh *> &meshes, + const vector<Geometry *> &geometry, const vector<Object *> &objects) { switch (params.bvh_layout) { case BVH_LAYOUT_BVH2: - return new BVH2(params, meshes, objects); + return new BVH2(params, geometry, objects); case BVH_LAYOUT_BVH4: - return new BVH4(params, meshes, objects); + return new BVH4(params, geometry, objects); case BVH_LAYOUT_BVH8: - return new BVH8(params, meshes, objects); + return new BVH8(params, geometry, objects); case BVH_LAYOUT_EMBREE: #ifdef WITH_EMBREE - return new BVHEmbree(params, meshes, objects); + return new BVHEmbree(params, geometry, objects); #else break; #endif case BVH_LAYOUT_OPTIX: #ifdef WITH_OPTIX - return new BVHOptiX(params, meshes, objects); + return new BVHOptiX(params, geometry, objects); #else break; #endif @@ -217,36 +220,36 @@ void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility) } else { /* Primitives. */ - const Mesh *mesh = ob->mesh; - if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ - int str_offset = (params.top_level) ? mesh->curve_offset : 0; - Mesh::Curve curve = mesh->get_curve(pidx - str_offset); + const Hair *hair = static_cast<const Hair *>(ob->geometry); + int prim_offset = (params.top_level) ? hair->prim_offset : 0; + Hair::Curve curve = hair->get_curve(pidx - prim_offset); int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); + curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox); visibility |= PATH_RAY_CURVE; /* Motion curves. */ - if (mesh->use_motion_blur) { - Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (hair->use_motion_blur) { + Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr) { - size_t mesh_size = mesh->curve_keys.size(); - size_t steps = mesh->motion_steps - 1; + size_t hair_size = hair->curve_keys.size(); + size_t steps = hair->motion_steps - 1; float3 *key_steps = attr->data_float3(); for (size_t i = 0; i < steps; i++) - curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox); + curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox); } } } else { /* Triangles. */ - int tri_offset = (params.top_level) ? mesh->tri_offset : 0; - Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); + const Mesh *mesh = static_cast<const Mesh *>(ob->geometry); + int prim_offset = (params.top_level) ? mesh->prim_offset : 0; + Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset); const float3 *vpos = &mesh->verts[0]; triangle.bounds_grow(vpos, bbox); @@ -276,7 +279,7 @@ void BVH::pack_triangle(int idx, float4 tri_verts[3]) { int tob = pack.prim_object[idx]; assert(tob >= 0 && tob < objects.size()); - const Mesh *mesh = objects[tob]->mesh; + const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->geometry); int tidx = pack.prim_index[idx]; Mesh::Triangle t = mesh->get_triangle(tidx); @@ -347,15 +350,13 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8); /* Adjust primitive index to point to the triangle in the global array, for - * meshes with transform applied and already in the top level BVH. + * geometry with transform applied and already in the top level BVH. */ - for (size_t i = 0; i < pack.prim_index.size(); i++) + for (size_t i = 0; i < pack.prim_index.size(); i++) { if (pack.prim_index[i] != -1) { - if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; - else - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset; } + } /* track offsets of instanced BVH data in global array */ size_t prim_offset = pack.prim_index.size(); @@ -375,10 +376,10 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) size_t pack_leaf_nodes_offset = leaf_nodes_size; size_t object_offset = 0; - foreach (Mesh *mesh, meshes) { - BVH *bvh = mesh->bvh; + foreach (Geometry *geom, geometry) { + BVH *bvh = geom->bvh; - if (mesh->need_build_bvh(params.bvh_layout)) { + if (geom->need_build_bvh(params.bvh_layout)) { prim_index_size += bvh->pack.prim_index.size(); prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); nodes_size += bvh->pack.nodes.size(); @@ -410,36 +411,35 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL; float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL; - map<Mesh *, int> mesh_map; + map<Geometry *, int> geometry_map; /* merge */ foreach (Object *ob, objects) { - Mesh *mesh = ob->mesh; + Geometry *geom = ob->geometry; /* We assume that if mesh doesn't need own BVH it was already included * into a top-level BVH and no packing here is needed. */ - if (!mesh->need_build_bvh(params.bvh_layout)) { + if (!geom->need_build_bvh(params.bvh_layout)) { pack.object_node[object_offset++] = 0; continue; } /* if mesh already added once, don't add it again, but used set * node offset for this object */ - map<Mesh *, int>::iterator it = mesh_map.find(mesh); + map<Geometry *, int>::iterator it = geometry_map.find(geom); - if (mesh_map.find(mesh) != mesh_map.end()) { + if (geometry_map.find(geom) != geometry_map.end()) { int noffset = it->second; pack.object_node[object_offset++] = noffset; continue; } - BVH *bvh = mesh->bvh; + BVH *bvh = geom->bvh; int noffset = nodes_offset; int noffset_leaf = nodes_leaf_offset; - int mesh_tri_offset = mesh->tri_offset; - int mesh_curve_offset = mesh->curve_offset; + int geom_prim_offset = geom->prim_offset; /* fill in node indexes for instances */ if (bvh->pack.root_index == -1) @@ -447,7 +447,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) else pack.object_node[object_offset++] = noffset; - mesh_map[mesh] = pack.object_node[object_offset - 1]; + geometry_map[geom] = pack.object_node[object_offset - 1]; /* merge primitive, object and triangle indexes */ if (bvh->pack.prim_index.size()) { @@ -460,11 +460,11 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) for (size_t i = 0; i < bvh_prim_index_size; i++) { if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset; pack_prim_tri_index[pack_prim_index_offset] = -1; } else { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset; pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] + pack_prim_tri_verts_offset; } diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 92082e4de86..bdde38640c9 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -33,7 +33,7 @@ struct BVHStackEntry; class BVHParams; class BoundBox; class LeafNode; -class Mesh; +class Geometry; class Object; class Progress; @@ -84,11 +84,11 @@ class BVH { public: PackedBVH pack; BVHParams params; - vector<Mesh *> meshes; + vector<Geometry *> geometry; vector<Object *> objects; static BVH *create(const BVHParams ¶ms, - const vector<Mesh *> &meshes, + const vector<Geometry *> &geometry, const vector<Object *> &objects); virtual ~BVH() { @@ -102,7 +102,9 @@ class BVH { void refit(Progress &progress); protected: - BVH(const BVHParams ¶ms, const vector<Mesh *> &meshes, const vector<Object *> &objects); + BVH(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects); /* Refit range of primitives. */ void refit_primitives(int start, int end, BoundBox &bbox, uint &visibility); diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp index b1a9148c297..c903070429e 100644 --- a/intern/cycles/bvh/bvh2.cpp +++ b/intern/cycles/bvh/bvh2.cpp @@ -26,9 +26,9 @@ CCL_NAMESPACE_BEGIN BVH2::BVH2(const BVHParams ¶ms_, - const vector<Mesh *> &meshes_, + const vector<Geometry *> &geometry_, const vector<Object *> &objects_) - : BVH(params_, meshes_, objects_) + : BVH(params_, geometry_, objects_) { } diff --git a/intern/cycles/bvh/bvh2.h b/intern/cycles/bvh/bvh2.h index a3eaff9cf65..fa3e45b72d2 100644 --- a/intern/cycles/bvh/bvh2.h +++ b/intern/cycles/bvh/bvh2.h @@ -46,7 +46,9 @@ class BVH2 : public BVH { protected: /* constructor */ friend class BVH; - BVH2(const BVHParams ¶ms, const vector<Mesh *> &meshes, const vector<Object *> &objects); + BVH2(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects); /* Building process. */ virtual BVHNode *widen_children_nodes(const BVHNode *root) override; diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp index 89b42ee1d21..143c3e54f94 100644 --- a/intern/cycles/bvh/bvh4.cpp +++ b/intern/cycles/bvh/bvh4.cpp @@ -32,9 +32,9 @@ CCL_NAMESPACE_BEGIN */ BVH4::BVH4(const BVHParams ¶ms_, - const vector<Mesh *> &meshes_, + const vector<Geometry *> &geometry_, const vector<Object *> &objects_) - : BVH(params_, meshes_, objects_) + : BVH(params_, geometry_, objects_) { params.bvh_layout = BVH_LAYOUT_BVH4; } diff --git a/intern/cycles/bvh/bvh4.h b/intern/cycles/bvh/bvh4.h index c44f2833c84..afbb9007afb 100644 --- a/intern/cycles/bvh/bvh4.h +++ b/intern/cycles/bvh/bvh4.h @@ -46,7 +46,9 @@ class BVH4 : public BVH { protected: /* constructor */ friend class BVH; - BVH4(const BVHParams ¶ms, const vector<Mesh *> &meshes, const vector<Object *> &objects); + BVH4(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects); /* Building process. */ virtual BVHNode *widen_children_nodes(const BVHNode *root) override; diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp index d3516525f78..342dd9e85a5 100644 --- a/intern/cycles/bvh/bvh8.cpp +++ b/intern/cycles/bvh/bvh8.cpp @@ -28,6 +28,7 @@ #include "bvh/bvh8.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/object.h" @@ -37,9 +38,9 @@ CCL_NAMESPACE_BEGIN BVH8::BVH8(const BVHParams ¶ms_, - const vector<Mesh *> &meshes_, + const vector<Geometry *> &geometry_, const vector<Object *> &objects_) - : BVH(params_, meshes_, objects_) + : BVH(params_, geometry_, objects_) { } @@ -429,37 +430,37 @@ void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility) } else { /* Primitives. */ - const Mesh *mesh = ob->mesh; - if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ - int str_offset = (params.top_level) ? mesh->curve_offset : 0; - Mesh::Curve curve = mesh->get_curve(pidx - str_offset); + const Hair *hair = static_cast<const Hair *>(ob->geometry); + int prim_offset = (params.top_level) ? hair->prim_offset : 0; + Hair::Curve curve = hair->get_curve(pidx - prim_offset); int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); + curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox); visibility |= PATH_RAY_CURVE; /* Motion curves. */ - if (mesh->use_motion_blur) { - Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (hair->use_motion_blur) { + Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr) { - size_t mesh_size = mesh->curve_keys.size(); - size_t steps = mesh->motion_steps - 1; + size_t hair_size = hair->curve_keys.size(); + size_t steps = hair->motion_steps - 1; float3 *key_steps = attr->data_float3(); for (size_t i = 0; i < steps; i++) { - curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox); + curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox); } } } } else { /* Triangles. */ - int tri_offset = (params.top_level) ? mesh->tri_offset : 0; - Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); + const Mesh *mesh = static_cast<const Mesh *>(ob->geometry); + int prim_offset = (params.top_level) ? mesh->prim_offset : 0; + Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset); const float3 *vpos = &mesh->verts[0]; triangle.bounds_grow(vpos, bbox); diff --git a/intern/cycles/bvh/bvh8.h b/intern/cycles/bvh/bvh8.h index 5f26fd423e1..d23fa528e3e 100644 --- a/intern/cycles/bvh/bvh8.h +++ b/intern/cycles/bvh/bvh8.h @@ -57,7 +57,9 @@ class BVH8 : public BVH { protected: /* constructor */ friend class BVH; - BVH8(const BVHParams ¶ms, const vector<Mesh *> &meshes, const vector<Object *> &objects); + BVH8(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects); /* Building process. */ virtual BVHNode *widen_children_nodes(const BVHNode *root) override; diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 1d9b006e8cb..b472c55d156 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -22,6 +22,7 @@ #include "bvh/bvh_params.h" #include "bvh_split.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/object.h" #include "render/scene.h" @@ -194,21 +195,21 @@ void BVHBuild::add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *m } } -void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i) +void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i) { const Attribute *curve_attr_mP = NULL; - if (mesh->has_motion_blur()) { - curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (hair->has_motion_blur()) { + curve_attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); } - const size_t num_curves = mesh->num_curves(); + const size_t num_curves = hair->num_curves(); for (uint j = 0; j < num_curves; j++) { - const Mesh::Curve curve = mesh->get_curve(j); - const float *curve_radius = &mesh->curve_radius[0]; + const Hair::Curve curve = hair->get_curve(j); + const float *curve_radius = &hair->curve_radius[0]; for (int k = 0; k < curve.num_keys - 1; k++) { if (curve_attr_mP == NULL) { /* Really simple logic for static hair. */ BoundBox bounds = BoundBox::empty; - curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); + curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds); if (bounds.valid()) { int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k); references.push_back(BVHReference(bounds, j, i, packed_type)); @@ -223,9 +224,9 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Mesh *mesh */ /* TODO(sergey): Support motion steps for spatially split BVH. */ BoundBox bounds = BoundBox::empty; - curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); - const size_t num_keys = mesh->curve_keys.size(); - const size_t num_steps = mesh->motion_steps; + curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds); + const size_t num_keys = hair->curve_keys.size(); + const size_t num_steps = hair->motion_steps; const float3 *key_steps = curve_attr_mP->data_float3(); for (size_t step = 0; step < num_steps - 1; step++) { curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds); @@ -244,10 +245,10 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Mesh *mesh */ const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); - const size_t num_steps = mesh->motion_steps; - const float3 *curve_keys = &mesh->curve_keys[0]; + const size_t num_steps = hair->motion_steps; + const float3 *curve_keys = &hair->curve_keys[0]; const float3 *key_steps = curve_attr_mP->data_float3(); - const size_t num_keys = mesh->curve_keys.size(); + const size_t num_keys = hair->curve_keys.size(); /* Calculate bounding box of the previous time step. * Will be reused later to avoid duplicated work on * calculating BVH time step boundbox. @@ -302,13 +303,15 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Mesh *mesh } } -void BVHBuild::add_reference_mesh(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i) +void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i) { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); add_reference_triangles(root, center, mesh, i); } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE) { - add_reference_curves(root, center, mesh, i); + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + add_reference_curves(root, center, hair, i); } } @@ -319,16 +322,30 @@ void BVHBuild::add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob center.grow(ob->bounds.center2()); } -static size_t count_curve_segments(Mesh *mesh) +static size_t count_curve_segments(Hair *hair) { - size_t num = 0, num_curves = mesh->num_curves(); + size_t num = 0, num_curves = hair->num_curves(); for (size_t i = 0; i < num_curves; i++) - num += mesh->get_curve(i).num_keys - 1; + num += hair->get_curve(i).num_keys - 1; return num; } +static size_t count_primitives(Geometry *geom) +{ + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + return mesh->num_triangles(); + } + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + return count_curve_segments(hair); + } + + return 0; +} + void BVHBuild::add_references(BVHRange &root) { /* reserve space for references */ @@ -339,24 +356,14 @@ void BVHBuild::add_references(BVHRange &root) if (!ob->is_traceable()) { continue; } - if (!ob->mesh->is_instanced()) { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { - num_alloc_references += ob->mesh->num_triangles(); - } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE) { - num_alloc_references += count_curve_segments(ob->mesh); - } + if (!ob->geometry->is_instanced()) { + num_alloc_references += count_primitives(ob->geometry); } else num_alloc_references++; } else { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { - num_alloc_references += ob->mesh->num_triangles(); - } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE) { - num_alloc_references += count_curve_segments(ob->mesh); - } + num_alloc_references += count_primitives(ob->geometry); } } @@ -372,13 +379,13 @@ void BVHBuild::add_references(BVHRange &root) ++i; continue; } - if (!ob->mesh->is_instanced()) - add_reference_mesh(bounds, center, ob->mesh, i); + if (!ob->geometry->is_instanced()) + add_reference_geometry(bounds, center, ob->geometry, i); else add_reference_object(bounds, center, ob, i); } else - add_reference_mesh(bounds, center, ob->mesh, i); + add_reference_geometry(bounds, center, ob->geometry, i); i++; diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 9685e26cfac..3fe4c3799e2 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -35,6 +35,8 @@ class BVHNode; class BVHSpatialSplitBuildTask; class BVHParams; class InnerNode; +class Geometry; +class Hair; class Mesh; class Object; class Progress; @@ -65,8 +67,8 @@ class BVHBuild { /* Adding references. */ void add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i); - void add_reference_curves(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i); - void add_reference_mesh(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i); + void add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i); + void add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i); void add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i); void add_references(BVHRange &root); diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 3e4978a2c0a..88302f11e7e 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -49,6 +49,7 @@ # include "kernel/kernel_globals.h" # include "kernel/kernel_random.h" +# include "render/hair.h" # include "render/mesh.h" # include "render/object.h" # include "util/util_foreach.h" @@ -301,10 +302,24 @@ RTCDevice BVHEmbree::rtc_shared_device = NULL; int BVHEmbree::rtc_shared_users = 0; thread_mutex BVHEmbree::rtc_shared_mutex; +static size_t count_primitives(Geometry *geom) +{ + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + return mesh->num_triangles(); + } + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + return hair->num_segments(); + } + + return 0; +} + BVHEmbree::BVHEmbree(const BVHParams ¶ms_, - const vector<Mesh *> &meshes_, + const vector<Geometry *> &geometry_, const vector<Object *> &objects_) - : BVH(params_, meshes_, objects_), + : BVH(params_, geometry_, objects_), scene(NULL), mem_used(0), top_level(NULL), @@ -436,29 +451,15 @@ void BVHEmbree::build(Progress &progress, Stats *stats_) if (!ob->is_traceable()) { continue; } - if (!ob->mesh->is_instanced()) { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { - prim_count += ob->mesh->num_triangles(); - } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE) { - for (size_t j = 0; j < ob->mesh->num_curves(); ++j) { - prim_count += ob->mesh->get_curve(j).num_segments(); - } - } + if (!ob->geometry->is_instanced()) { + prim_count += count_primitives(ob->geometry); } else { ++prim_count; } } else { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { - prim_count += ob->mesh->num_triangles(); - } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE) { - for (size_t j = 0; j < ob->mesh->num_curves(); ++j) { - prim_count += ob->mesh->get_curve(j).num_segments(); - } - } + prim_count += count_primitives(ob->geometry); } } @@ -477,7 +478,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_) ++i; continue; } - if (!ob->mesh->is_instanced()) { + if (!ob->geometry->is_instanced()) { add_object(ob, i); } else { @@ -528,22 +529,29 @@ BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/) void BVHEmbree::add_object(Object *ob, int i) { - Mesh *mesh = ob->mesh; - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) { - add_triangles(ob, i); + Geometry *geom = ob->geometry; + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->num_triangles() > 0) { + add_triangles(ob, mesh, i); + } } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) { - add_curves(ob, i); + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + if (hair->num_curves() > 0) { + add_curves(ob, hair, i); + } } } void BVHEmbree::add_instance(Object *ob, int i) { - if (!ob || !ob->mesh) { + if (!ob || !ob->geometry) { assert(0); return; } - BVHEmbree *instance_bvh = (BVHEmbree *)(ob->mesh->bvh); + BVHEmbree *instance_bvh = (BVHEmbree *)(ob->geometry->bvh); if (instance_bvh->top_level != this) { instance_bvh->top_level = this; @@ -577,10 +585,9 @@ void BVHEmbree::add_instance(Object *ob, int i) rtcReleaseGeometry(geom_id); } -void BVHEmbree::add_triangles(Object *ob, int i) +void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) { size_t prim_offset = pack.prim_index.size(); - Mesh *mesh = ob->mesh; const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; if (mesh->has_motion_blur()) { @@ -684,31 +691,31 @@ void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh) } } -void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh) +void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair) { const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; - if (mesh->has_motion_blur()) { - attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (hair->has_motion_blur()) { + attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = mesh->motion_steps; + num_motion_steps = hair->motion_steps; } } - const size_t num_curves = mesh->num_curves(); + const size_t num_curves = hair->num_curves(); size_t num_keys = 0; for (size_t j = 0; j < num_curves; ++j) { - const Mesh::Curve c = mesh->get_curve(j); + const Hair::Curve c = hair->get_curve(j); num_keys += c.num_keys; } /* Copy the CV data to Embree */ const int t_mid = (num_motion_steps - 1) / 2; - const float *curve_radius = &mesh->curve_radius[0]; + const float *curve_radius = &hair->curve_radius[0]; for (int t = 0; t < num_motion_steps; ++t) { const float3 *verts; if (t == t_mid || attr_mP == NULL) { - verts = &mesh->curve_keys[0]; + verts = &hair->curve_keys[0]; } else { int t_ = (t > t_mid) ? (t - 1) : t; @@ -726,9 +733,9 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh assert(rtc_verts); if (rtc_verts) { if (use_curves && rtc_tangents) { - const size_t num_curves = mesh->num_curves(); + const size_t num_curves = hair->num_curves(); for (size_t j = 0; j < num_curves; ++j) { - Mesh::Curve c = mesh->get_curve(j); + Hair::Curve c = hair->get_curve(j); int fk = c.first_key; rtc_verts[0] = float3_to_float4(verts[fk]); rtc_verts[0].w = curve_radius[fk]; @@ -760,23 +767,22 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh } } -void BVHEmbree::add_curves(Object *ob, int i) +void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) { size_t prim_offset = pack.prim_index.size(); - const Mesh *mesh = ob->mesh; const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; - if (mesh->has_motion_blur()) { - attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (hair->has_motion_blur()) { + attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = mesh->motion_steps; + num_motion_steps = hair->motion_steps; } } - const size_t num_curves = mesh->num_curves(); + const size_t num_curves = hair->num_curves(); size_t num_segments = 0; for (size_t j = 0; j < num_curves; ++j) { - Mesh::Curve c = mesh->get_curve(j); + Hair::Curve c = hair->get_curve(j); assert(c.num_segments() > 0); num_segments += c.num_segments(); } @@ -802,7 +808,7 @@ void BVHEmbree::add_curves(Object *ob, int i) geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments); size_t rtc_index = 0; for (size_t j = 0; j < num_curves; ++j) { - Mesh::Curve c = mesh->get_curve(j); + Hair::Curve c = hair->get_curve(j); for (size_t k = 0; k < c.num_segments(); ++k) { rtc_indices[rtc_index] = c.first_key + k; /* Cycles specific data. */ @@ -819,7 +825,7 @@ void BVHEmbree::add_curves(Object *ob, int i) rtcSetGeometryBuildQuality(geom_id, build_quality); rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); - update_curve_vertex_buffer(geom_id, mesh); + update_curve_vertex_buffer(geom_id, hair); rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func); @@ -840,10 +846,7 @@ void BVHEmbree::pack_nodes(const BVHNode *) for (size_t i = 0; i < pack.prim_index.size(); ++i) { if (pack.prim_index[i] != -1) { - if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; - else - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset; } } @@ -857,22 +860,22 @@ void BVHEmbree::pack_nodes(const BVHNode *) size_t pack_prim_tri_verts_offset = prim_tri_verts_size; size_t object_offset = 0; - map<Mesh *, int> mesh_map; + map<Geometry *, int> geometry_map; foreach (Object *ob, objects) { - Mesh *mesh = ob->mesh; - BVH *bvh = mesh->bvh; + Geometry *geom = ob->geometry; + BVH *bvh = geom->bvh; - if (mesh->need_build_bvh(BVH_LAYOUT_EMBREE)) { - if (mesh_map.find(mesh) == mesh_map.end()) { + if (geom->need_build_bvh(BVH_LAYOUT_EMBREE)) { + if (geometry_map.find(geom) == geometry_map.end()) { prim_index_size += bvh->pack.prim_index.size(); prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); - mesh_map[mesh] = 1; + geometry_map[geom] = 1; } } } - mesh_map.clear(); + geometry_map.clear(); pack.prim_index.resize(prim_index_size); pack.prim_type.resize(prim_index_size); @@ -890,38 +893,37 @@ void BVHEmbree::pack_nodes(const BVHNode *) /* merge */ foreach (Object *ob, objects) { - Mesh *mesh = ob->mesh; + Geometry *geom = ob->geometry; /* We assume that if mesh doesn't need own BVH it was already included * into a top-level BVH and no packing here is needed. */ - if (!mesh->need_build_bvh(BVH_LAYOUT_EMBREE)) { + if (!geom->need_build_bvh(BVH_LAYOUT_EMBREE)) { pack.object_node[object_offset++] = prim_offset; continue; } - /* if mesh already added once, don't add it again, but used set + /* if geom already added once, don't add it again, but used set * node offset for this object */ - map<Mesh *, int>::iterator it = mesh_map.find(mesh); + map<Geometry *, int>::iterator it = geometry_map.find(geom); - if (mesh_map.find(mesh) != mesh_map.end()) { + if (geometry_map.find(geom) != geometry_map.end()) { int noffset = it->second; pack.object_node[object_offset++] = noffset; continue; } - BVHEmbree *bvh = (BVHEmbree *)mesh->bvh; + BVHEmbree *bvh = (BVHEmbree *)geom->bvh; rtc_memory_monitor_func(stats, unaccounted_mem, true); unaccounted_mem = 0; - int mesh_tri_offset = mesh->tri_offset; - int mesh_curve_offset = mesh->curve_offset; + int prim_offset = geom->prim_offset; /* fill in node indexes for instances */ pack.object_node[object_offset++] = prim_offset; - mesh_map[mesh] = pack.object_node[object_offset - 1]; + geometry_map[geom] = pack.object_node[object_offset - 1]; /* merge primitive, object and triangle indexes */ if (bvh->pack.prim_index.size()) { @@ -932,11 +934,11 @@ void BVHEmbree::pack_nodes(const BVHNode *) for (size_t i = 0; i < bvh_prim_index_size; ++i) { if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + prim_offset; pack_prim_tri_index[pack_prim_index_offset] = -1; } else { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + prim_offset; pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] + pack_prim_tri_verts_offset; } @@ -966,15 +968,22 @@ void BVHEmbree::refit_nodes() /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */ unsigned geom_id = 0; foreach (Object *ob, objects) { - if (!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { - update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh); - rtcCommitGeometry(rtcGetGeometry(scene, geom_id)); + if (!params.top_level || (ob->is_traceable() && !ob->geometry->is_instanced())) { + Geometry *geom = ob->geometry; + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->num_triangles() > 0) { + update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), mesh); + rtcCommitGeometry(rtcGetGeometry(scene, geom_id)); + } } - - if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) { - update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh); - rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1)); + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + if (hair->num_curves() > 0) { + update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), hair); + rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1)); + } } } geom_id += 2; diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h index 123e87dd9b0..eb121d060b7 100644 --- a/intern/cycles/bvh/bvh_embree.h +++ b/intern/cycles/bvh/bvh_embree.h @@ -31,6 +31,8 @@ CCL_NAMESPACE_BEGIN +class Geometry; +class Hair; class Mesh; class BVHEmbree : public BVH { @@ -47,7 +49,7 @@ class BVHEmbree : public BVH { protected: friend class BVH; BVHEmbree(const BVHParams ¶ms, - const vector<Mesh *> &meshes, + const vector<Geometry *> &geometry, const vector<Object *> &objects); virtual void pack_nodes(const BVHNode *) override; @@ -55,8 +57,8 @@ class BVHEmbree : public BVH { void add_object(Object *ob, int i); void add_instance(Object *ob, int i); - void add_curves(Object *ob, int i); - void add_triangles(Object *ob, int i); + void add_curves(const Object *ob, const Hair *hair, int i); + void add_triangles(const Object *ob, const Mesh *mesh, int i); ssize_t mem_used; @@ -69,7 +71,7 @@ class BVHEmbree : public BVH { private: void delete_rtcScene(); void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh); - void update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh); + void update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair); static RTCDevice rtc_shared_device; static int rtc_shared_users; diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp index 86d755ab06a..a3b6261dcad 100644 --- a/intern/cycles/bvh/bvh_optix.cpp +++ b/intern/cycles/bvh/bvh_optix.cpp @@ -18,6 +18,8 @@ #ifdef WITH_OPTIX # include "bvh/bvh_optix.h" +# include "render/hair.h" +# include "render/geometry.h" # include "render/mesh.h" # include "render/object.h" # include "util/util_logging.h" @@ -26,9 +28,9 @@ CCL_NAMESPACE_BEGIN BVHOptiX::BVHOptiX(const BVHParams ¶ms_, - const vector<Mesh *> &meshes_, + const vector<Geometry *> &geometry_, const vector<Object *> &objects_) - : BVH(params_, meshes_, objects_) + : BVH(params_, geometry_, objects_) { } @@ -56,47 +58,52 @@ void BVHOptiX::copy_to_device(Progress &progress, DeviceScene *dscene) void BVHOptiX::pack_blas() { // Bottom-level BVH can contain multiple primitive types, so merge them: - assert(meshes.size() == 1 && objects.size() == 1); // These are build per-mesh - Mesh *const mesh = meshes[0]; - - if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) { - const size_t num_curves = mesh->num_curves(); - const size_t num_segments = mesh->num_segments(); - pack.prim_type.reserve(pack.prim_type.size() + num_segments); - pack.prim_index.reserve(pack.prim_index.size() + num_segments); - pack.prim_object.reserve(pack.prim_object.size() + num_segments); - // 'pack.prim_time' is only used in geom_curve_intersect.h - // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH - - uint type = PRIMITIVE_CURVE; - if (mesh->use_motion_blur && mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) - type = PRIMITIVE_MOTION_CURVE; - - for (size_t j = 0; j < num_curves; ++j) { - const Mesh::Curve curve = mesh->get_curve(j); - for (size_t k = 0; k < curve.num_segments(); ++k) { - pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k)); - // Each curve segment points back to its curve index - pack.prim_index.push_back_reserved(j); - pack.prim_object.push_back_reserved(0); + assert(geometry.size() == 1 && objects.size() == 1); // These are built per-mesh + Geometry *const geom = geometry[0]; + + if (geom->type == Geometry::HAIR) { + Hair *const hair = static_cast<Hair *const>(geom); + if (hair->num_curves() > 0) { + const size_t num_curves = hair->num_curves(); + const size_t num_segments = hair->num_segments(); + pack.prim_type.reserve(pack.prim_type.size() + num_segments); + pack.prim_index.reserve(pack.prim_index.size() + num_segments); + pack.prim_object.reserve(pack.prim_object.size() + num_segments); + // 'pack.prim_time' is only used in geom_curve_intersect.h + // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH + + uint type = PRIMITIVE_CURVE; + if (hair->use_motion_blur && hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) + type = PRIMITIVE_MOTION_CURVE; + + for (size_t j = 0; j < num_curves; ++j) { + const Hair::Curve curve = hair->get_curve(j); + for (size_t k = 0; k < curve.num_segments(); ++k) { + pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k)); + // Each curve segment points back to its curve index + pack.prim_index.push_back_reserved(j); + pack.prim_object.push_back_reserved(0); + } } } } - - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) { - const size_t num_triangles = mesh->num_triangles(); - pack.prim_type.reserve(pack.prim_type.size() + num_triangles); - pack.prim_index.reserve(pack.prim_index.size() + num_triangles); - pack.prim_object.reserve(pack.prim_object.size() + num_triangles); - - uint type = PRIMITIVE_TRIANGLE; - if (mesh->use_motion_blur && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) - type = PRIMITIVE_MOTION_TRIANGLE; - - for (size_t k = 0; k < num_triangles; ++k) { - pack.prim_type.push_back_reserved(type); - pack.prim_index.push_back_reserved(k); - pack.prim_object.push_back_reserved(0); + else if (geom->type == Geometry::MESH) { + Mesh *const mesh = static_cast<Mesh *const>(geom); + if (mesh->num_triangles() > 0) { + const size_t num_triangles = mesh->num_triangles(); + pack.prim_type.reserve(pack.prim_type.size() + num_triangles); + pack.prim_index.reserve(pack.prim_index.size() + num_triangles); + pack.prim_object.reserve(pack.prim_object.size() + num_triangles); + + uint type = PRIMITIVE_TRIANGLE; + if (mesh->use_motion_blur && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) + type = PRIMITIVE_MOTION_TRIANGLE; + + for (size_t k = 0; k < num_triangles; ++k) { + pack.prim_type.push_back_reserved(type); + pack.prim_index.push_back_reserved(k); + pack.prim_object.push_back_reserved(0); + } } } @@ -116,8 +123,8 @@ void BVHOptiX::pack_tlas() // Calculate total packed size size_t prim_index_size = 0; size_t prim_tri_verts_size = 0; - foreach (Mesh *mesh, meshes) { - BVH *const bvh = mesh->bvh; + foreach (Geometry *geom, geometry) { + BVH *const bvh = geom->bvh; prim_index_size += bvh->pack.prim_index.size(); prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); } @@ -141,13 +148,12 @@ void BVHOptiX::pack_tlas() pack.prim_tri_verts.resize(prim_tri_verts_size); float4 *pack_prim_tri_verts = pack.prim_tri_verts.data(); - // Top-level BVH should only contain instances, see 'Mesh::need_build_bvh' + // Top-level BVH should only contain instances, see 'Geometry::need_build_bvh' // Iterate over scene mesh list instead of objects, since the 'prim_offset' is calculated based // on that list, which may be ordered differently from the object list. - foreach (Mesh *mesh, meshes) { - PackedBVH &bvh_pack = mesh->bvh->pack; - int mesh_tri_offset = mesh->tri_offset; - int mesh_curve_offset = mesh->curve_offset; + foreach (Geometry *geom, geometry) { + PackedBVH &bvh_pack = geom->bvh->pack; + int geom_prim_offset = geom->prim_offset; // Merge primitive, object and triangle indexes if (!bvh_pack.prim_index.empty()) { @@ -158,16 +164,16 @@ void BVHOptiX::pack_tlas() for (size_t i = 0; i < bvh_pack.prim_index.size(); i++, pack_offset++) { if (bvh_pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack_prim_index[pack_offset] = bvh_prim_index[i] + mesh_curve_offset; + pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset; pack_prim_tri_index[pack_offset] = -1; } else { - pack_prim_index[pack_offset] = bvh_prim_index[i] + mesh_tri_offset; + pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset; pack_prim_tri_index[pack_offset] = bvh_prim_tri_index[i] + pack_verts_offset; } pack_prim_type[pack_offset] = bvh_prim_type[i]; - pack_prim_object[pack_offset] = 0; // Unused for instanced meshes + pack_prim_object[pack_offset] = 0; // Unused for instanced geometry pack_prim_visibility[pack_offset] = bvh_prim_visibility[i]; } } @@ -182,15 +188,24 @@ void BVHOptiX::pack_tlas() } } - // Merge visibility flags of all objects and fix object indices for non-instanced meshes + // Merge visibility flags of all objects and fix object indices for non-instanced geometry foreach (Object *ob, objects) { - Mesh *const mesh = ob->mesh; - for (size_t i = 0; i < mesh->num_primitives(); ++i) { - if (!ob->mesh->is_instanced()) { - assert(pack.prim_object[mesh->prim_offset + i] == 0); - pack.prim_object[mesh->prim_offset + i] = ob->get_device_index(); + Geometry *const geom = ob->geometry; + size_t num_primitives = 0; + + if (geom->type == Geometry::MESH) { + num_primitives = static_cast<Mesh *const>(geom)->num_triangles(); + } + else if (geom->type == Geometry::HAIR) { + num_primitives = static_cast<Hair *const>(geom)->num_segments(); + } + + for (size_t i = 0; i < num_primitives; ++i) { + if (!geom->is_instanced()) { + assert(pack.prim_object[geom->optix_prim_offset + i] == 0); + pack.prim_object[geom->optix_prim_offset + i] = ob->get_device_index(); } - pack.prim_visibility[mesh->prim_offset + i] |= ob->visibility_for_tracing(); + pack.prim_visibility[geom->optix_prim_offset + i] |= ob->visibility_for_tracing(); } } } diff --git a/intern/cycles/bvh/bvh_optix.h b/intern/cycles/bvh/bvh_optix.h index 35033fe635f..e4745b093b5 100644 --- a/intern/cycles/bvh/bvh_optix.h +++ b/intern/cycles/bvh/bvh_optix.h @@ -26,11 +26,16 @@ CCL_NAMESPACE_BEGIN +class Geometry; +class Optix; + class BVHOptiX : public BVH { friend class BVH; public: - BVHOptiX(const BVHParams ¶ms, const vector<Mesh *> &meshes, const vector<Object *> &objects); + BVHOptiX(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects); virtual ~BVHOptiX(); virtual void build(Progress &progress, Stats *) override; diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 2731662a39d..5e2c4b63f1b 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -69,9 +69,6 @@ class BVHParams { /* BVH layout to be built. */ BVHLayout bvh_layout; - /* Mask of primitives to be included into the BVH. */ - int primitive_mask; - /* Use unaligned bounding boxes. * Only used for curves BVH. */ @@ -120,8 +117,6 @@ class BVHParams { bvh_layout = BVH_LAYOUT_BVH2; use_unaligned_nodes = false; - primitive_mask = PRIMITIVE_ALL; - num_motion_curve_steps = 0; num_motion_triangle_steps = 0; diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index bd261c10d55..7e787674b74 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -20,6 +20,7 @@ #include "bvh/bvh_build.h" #include "bvh/bvh_sort.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/object.h" @@ -378,7 +379,7 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh, } } -void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh, +void BVHSpatialSplit::split_curve_primitive(const Hair *hair, const Transform *tfm, int prim_index, int segment_index, @@ -388,11 +389,11 @@ void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh, BoundBox &right_bounds) { /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ - Mesh::Curve curve = mesh->get_curve(prim_index); + Hair::Curve curve = hair->get_curve(prim_index); const int k0 = curve.first_key + segment_index; const int k1 = k0 + 1; - float3 v0 = mesh->curve_keys[k0]; - float3 v1 = mesh->curve_keys[k1]; + float3 v0 = hair->curve_keys[k0]; + float3 v1 = hair->curve_keys[k1]; if (tfm != NULL) { v0 = transform_point(tfm, v0); @@ -436,13 +437,13 @@ void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref, } void BVHSpatialSplit::split_curve_reference(const BVHReference &ref, - const Mesh *mesh, + const Hair *hair, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds) { - split_curve_primitive(mesh, + split_curve_primitive(hair, NULL, ref.prim_index(), PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()), @@ -455,15 +456,22 @@ void BVHSpatialSplit::split_curve_reference(const BVHReference &ref, void BVHSpatialSplit::split_object_reference( const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds) { - Mesh *mesh = object->mesh; - for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) { - split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds); + Geometry *geom = object->geometry; + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) { + split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds); + } } - for (int curve_idx = 0; curve_idx < mesh->num_curves(); ++curve_idx) { - Mesh::Curve curve = mesh->get_curve(curve_idx); - for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) { - split_curve_primitive( - mesh, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds); + else if (geom->type == Geometry::MESH) { + Hair *hair = static_cast<Hair *>(geom); + for (int curve_idx = 0; curve_idx < hair->num_curves(); ++curve_idx) { + Hair::Curve curve = hair->get_curve(curve_idx); + for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) { + split_curve_primitive( + hair, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds); + } } } } @@ -481,13 +489,14 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder, /* loop over vertices/edges. */ const Object *ob = builder.objects[ref.prim_object()]; - const Mesh *mesh = ob->mesh; if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { + Mesh *mesh = static_cast<Mesh *>(ob->geometry); split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds); } else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) { - split_curve_reference(ref, mesh, dim, pos, left_bounds, right_bounds); + Hair *hair = static_cast<Hair *>(ob->geometry); + split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds); } else { split_object_reference(ob, dim, pos, left_bounds, right_bounds); diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h index eddd1c27f49..5f2e41cf343 100644 --- a/intern/cycles/bvh/bvh_split.h +++ b/intern/cycles/bvh/bvh_split.h @@ -24,6 +24,8 @@ CCL_NAMESPACE_BEGIN class BVHBuild; +class Hair; +class Mesh; struct Transform; /* Object Split */ @@ -113,7 +115,7 @@ class BVHSpatialSplit { float pos, BoundBox &left_bounds, BoundBox &right_bounds); - void split_curve_primitive(const Mesh *mesh, + void split_curve_primitive(const Hair *hair, const Transform *tfm, int prim_index, int segment_index, @@ -134,7 +136,7 @@ class BVHSpatialSplit { BoundBox &left_bounds, BoundBox &right_bounds); void split_curve_reference(const BVHReference &ref, - const Mesh *mesh, + const Hair *hair, int dim, float pos, BoundBox &left_bounds, diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp index 1843ca403a5..f0995f343fe 100644 --- a/intern/cycles/bvh/bvh_unaligned.cpp +++ b/intern/cycles/bvh/bvh_unaligned.cpp @@ -16,7 +16,7 @@ #include "bvh/bvh_unaligned.h" -#include "render/mesh.h" +#include "render/hair.h" #include "render/object.h" #include "bvh/bvh_binning.h" @@ -71,10 +71,10 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali if (type & PRIMITIVE_CURVE) { const int curve_index = ref.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); - const Mesh *mesh = object->mesh; - const Mesh::Curve &curve = mesh->get_curve(curve_index); + const Hair *hair = static_cast<const Hair *>(object->geometry); + const Hair::Curve &curve = hair->get_curve(curve_index); const int key = curve.first_key + segment; - const float3 v1 = mesh->curve_keys[key], v2 = mesh->curve_keys[key + 1]; + const float3 v1 = hair->curve_keys[key], v2 = hair->curve_keys[key + 1]; float length; const float3 axis = normalize_len(v2 - v1, &length); if (length > 1e-6f) { @@ -96,10 +96,10 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim, if (type & PRIMITIVE_CURVE) { const int curve_index = prim.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); - const Mesh *mesh = object->mesh; - const Mesh::Curve &curve = mesh->get_curve(curve_index); + const Hair *hair = static_cast<const Hair *>(object->geometry); + const Hair::Curve &curve = hair->get_curve(curve_index); curve.bounds_grow( - segment, &mesh->curve_keys[0], &mesh->curve_radius[0], aligned_space, bounds); + segment, &hair->curve_keys[0], &hair->curve_radius[0], aligned_space, bounds); } else { bounds = prim.bounds().transformed(&aligned_space); diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index f479cbd7414..98469fb37b0 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -22,6 +22,7 @@ # include "device/device_denoising.h" # include "bvh/bvh.h" # include "render/scene.h" +# include "render/hair.h" # include "render/mesh.h" # include "render/object.h" # include "render/buffers.h" @@ -1229,8 +1230,8 @@ class OptiXDevice : public Device { assert(bvh->params.top_level); unsigned int num_instances = 0; - unordered_map<Mesh *, vector<OptixTraversableHandle>> meshes; - meshes.reserve(bvh->meshes.size()); + unordered_map<Geometry *, OptixTraversableHandle> geometry; + geometry.reserve(bvh->geometry.size()); // Free all previous acceleration structures for (CUdeviceptr mem : as_mem) { @@ -1241,23 +1242,25 @@ class OptiXDevice : public Device { // Build bottom level acceleration structures (BLAS) // Note: Always keep this logic in sync with bvh_optix.cpp! for (Object *ob : bvh->objects) { - // Skip meshes for which acceleration structure already exists - if (meshes.find(ob->mesh) != meshes.end()) + // Skip geometry for which acceleration structure already exists + Geometry *geom = ob->geometry; + if (geometry.find(geom) != geometry.end()) continue; - Mesh *const mesh = ob->mesh; - vector<OptixTraversableHandle> handles; - handles.reserve(2); + if (geom->type == Geometry::HAIR) { + // Build BLAS for curve primitives + Hair *const hair = static_cast<Hair *const>(ob->geometry); + if (hair->num_curves() == 0) { + continue; + } - // Build BLAS for curve primitives - if (bvh->params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) { - const size_t num_curves = mesh->num_curves(); - const size_t num_segments = mesh->num_segments(); + const size_t num_curves = hair->num_curves(); + const size_t num_segments = hair->num_segments(); size_t num_motion_steps = 1; - Attribute *motion_keys = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (motion_blur && mesh->use_motion_blur && motion_keys) { - num_motion_steps = mesh->motion_steps; + Attribute *motion_keys = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (motion_blur && hair->use_motion_blur && motion_keys) { + num_motion_steps = hair->motion_steps; } device_vector<OptixAabb> aabb_data(this, "temp_aabb_data", MEM_READ_ONLY); @@ -1266,21 +1269,21 @@ class OptiXDevice : public Device { // Get AABBs for each motion step for (size_t step = 0; step < num_motion_steps; ++step) { // The center step for motion vertices is not stored in the attribute - const float3 *keys = mesh->curve_keys.data(); + const float3 *keys = hair->curve_keys.data(); size_t center_step = (num_motion_steps - 1) / 2; if (step != center_step) { size_t attr_offset = (step > center_step) ? step - 1 : step; // Technically this is a float4 array, but sizeof(float3) is the same as sizeof(float4) - keys = motion_keys->data_float3() + attr_offset * mesh->curve_keys.size(); + keys = motion_keys->data_float3() + attr_offset * hair->curve_keys.size(); } size_t i = step * num_segments; for (size_t j = 0; j < num_curves; ++j) { - const Mesh::Curve c = mesh->get_curve(j); + const Hair::Curve c = hair->get_curve(j); for (size_t k = 0; k < c.num_segments(); ++i, ++k) { BoundBox bounds = BoundBox::empty; - c.bounds_grow(k, keys, mesh->curve_radius.data(), bounds); + c.bounds_grow(k, keys, hair->curve_radius.data(), bounds); aabb_data[i].minX = bounds.min.x; aabb_data[i].minY = bounds.min.y; @@ -1311,16 +1314,24 @@ class OptiXDevice : public Device { build_input.aabbArray.strideInBytes = sizeof(OptixAabb); build_input.aabbArray.flags = &build_flags; build_input.aabbArray.numSbtRecords = 1; - build_input.aabbArray.primitiveIndexOffset = mesh->prim_offset; + build_input.aabbArray.primitiveIndexOffset = hair->optix_prim_offset; // Allocate memory for new BLAS and build it - handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, handles.back())) + OptixTraversableHandle handle; + if (build_optix_bvh(build_input, num_motion_steps, handle)) { + geometry.insert({ob->geometry, handle}); + } + else { return false; + } } + else if (geom->type == Geometry::MESH) { + // Build BLAS for triangle primitives + Mesh *const mesh = static_cast<Mesh *const>(ob->geometry); + if (mesh->num_triangles() == 0) { + continue; + } - // Build BLAS for triangle primitives - if (bvh->params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) { const size_t num_verts = mesh->verts.size(); size_t num_motion_steps = 1; @@ -1375,23 +1386,24 @@ class OptiXDevice : public Device { // buffers for that purpose. OptiX does not allow this to be zero though, so just pass in // one and rely on that having the same meaning in this case. build_input.triangleArray.numSbtRecords = 1; - // Triangle primitives are packed right after the curve primitives of this mesh - build_input.triangleArray.primitiveIndexOffset = mesh->prim_offset + mesh->num_segments(); + build_input.triangleArray.primitiveIndexOffset = mesh->optix_prim_offset; // Allocate memory for new BLAS and build it - handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, handles.back())) + OptixTraversableHandle handle; + if (build_optix_bvh(build_input, num_motion_steps, handle)) { + geometry.insert({ob->geometry, handle}); + } + else { return false; + } } - - meshes.insert({mesh, handles}); } // Fill instance descriptions device_vector<OptixAabb> aabbs(this, "tlas_aabbs", MEM_READ_ONLY); - aabbs.alloc(bvh->objects.size() * 2); + aabbs.alloc(bvh->objects.size()); device_vector<OptixInstance> instances(this, "tlas_instances", MEM_READ_ONLY); - instances.alloc(bvh->objects.size() * 2); + instances.alloc(bvh->objects.size()); for (Object *ob : bvh->objects) { // Skip non-traceable objects @@ -1399,113 +1411,117 @@ class OptiXDevice : public Device { continue; // Create separate instance for triangle/curve meshes of an object - for (OptixTraversableHandle handle : meshes[ob->mesh]) { - OptixAabb &aabb = aabbs[num_instances]; - aabb.minX = ob->bounds.min.x; - aabb.minY = ob->bounds.min.y; - aabb.minZ = ob->bounds.min.z; - aabb.maxX = ob->bounds.max.x; - aabb.maxY = ob->bounds.max.y; - aabb.maxZ = ob->bounds.max.z; - - OptixInstance &instance = instances[num_instances++]; - memset(&instance, 0, sizeof(instance)); - - // Clear transform to identity matrix - instance.transform[0] = 1.0f; - instance.transform[5] = 1.0f; - instance.transform[10] = 1.0f; - - // Set user instance ID to object index - instance.instanceId = ob->get_device_index(); - - // Volumes have a special bit set in the visibility mask so a trace can mask only volumes - // See 'scene_intersect_volume' in bvh.h - instance.visibilityMask = (ob->mesh->has_volume ? 3 : 1); - - // Insert motion traversable if object has motion - if (motion_blur && ob->use_motion()) { - size_t motion_keys = max(ob->motion.size(), 2) - 2; - size_t motion_transform_size = sizeof(OptixSRTMotionTransform) + - motion_keys * sizeof(OptixSRTData); - - const CUDAContextScope scope(cuda_context); - - CUdeviceptr motion_transform_gpu = 0; - check_result_cuda_ret(cuMemAlloc(&motion_transform_gpu, motion_transform_size)); - as_mem.push_back(motion_transform_gpu); - - // Allocate host side memory for motion transform and fill it with transform data - OptixSRTMotionTransform &motion_transform = *reinterpret_cast<OptixSRTMotionTransform *>( - new uint8_t[motion_transform_size]); - motion_transform.child = handle; - motion_transform.motionOptions.numKeys = ob->motion.size(); - motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE; - motion_transform.motionOptions.timeBegin = 0.0f; - motion_transform.motionOptions.timeEnd = 1.0f; - - OptixSRTData *const srt_data = motion_transform.srtData; - array<DecomposedTransform> decomp(ob->motion.size()); - transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size()); - - for (size_t i = 0; i < ob->motion.size(); ++i) { - // Scale - srt_data[i].sx = decomp[i].y.w; // scale.x.x - srt_data[i].sy = decomp[i].z.w; // scale.y.y - srt_data[i].sz = decomp[i].w.w; // scale.z.z - - // Shear - srt_data[i].a = decomp[i].z.x; // scale.x.y - srt_data[i].b = decomp[i].z.y; // scale.x.z - srt_data[i].c = decomp[i].w.x; // scale.y.z - assert(decomp[i].z.z == 0.0f); // scale.y.x - assert(decomp[i].w.y == 0.0f); // scale.z.x - assert(decomp[i].w.z == 0.0f); // scale.z.y - - // Pivot point - srt_data[i].pvx = 0.0f; - srt_data[i].pvy = 0.0f; - srt_data[i].pvz = 0.0f; - - // Rotation - srt_data[i].qx = decomp[i].x.x; - srt_data[i].qy = decomp[i].x.y; - srt_data[i].qz = decomp[i].x.z; - srt_data[i].qw = decomp[i].x.w; - - // Translation - srt_data[i].tx = decomp[i].y.x; - srt_data[i].ty = decomp[i].y.y; - srt_data[i].tz = decomp[i].y.z; - } + auto handle_it = geometry.find(ob->geometry); + if (handle_it == geometry.end()) { + continue; + } + OptixTraversableHandle handle = handle_it->second; - // Upload motion transform to GPU - cuMemcpyHtoD(motion_transform_gpu, &motion_transform, motion_transform_size); - delete[] reinterpret_cast<uint8_t *>(&motion_transform); + OptixAabb &aabb = aabbs[num_instances]; + aabb.minX = ob->bounds.min.x; + aabb.minY = ob->bounds.min.y; + aabb.minZ = ob->bounds.min.z; + aabb.maxX = ob->bounds.max.x; + aabb.maxY = ob->bounds.max.y; + aabb.maxZ = ob->bounds.max.z; - // Disable instance transform if object uses motion transform already - instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM; + OptixInstance &instance = instances[num_instances++]; + memset(&instance, 0, sizeof(instance)); - // Get traversable handle to motion transform - optixConvertPointerToTraversableHandle(context, - motion_transform_gpu, - OPTIX_TRAVERSABLE_TYPE_SRT_MOTION_TRANSFORM, - &instance.traversableHandle); + // Clear transform to identity matrix + instance.transform[0] = 1.0f; + instance.transform[5] = 1.0f; + instance.transform[10] = 1.0f; + + // Set user instance ID to object index + instance.instanceId = ob->get_device_index(); + + // Volumes have a special bit set in the visibility mask so a trace can mask only volumes + // See 'scene_intersect_volume' in bvh.h + instance.visibilityMask = (ob->geometry->has_volume ? 3 : 1); + + // Insert motion traversable if object has motion + if (motion_blur && ob->use_motion()) { + size_t motion_keys = max(ob->motion.size(), 2) - 2; + size_t motion_transform_size = sizeof(OptixSRTMotionTransform) + + motion_keys * sizeof(OptixSRTData); + + const CUDAContextScope scope(cuda_context); + + CUdeviceptr motion_transform_gpu = 0; + check_result_cuda_ret(cuMemAlloc(&motion_transform_gpu, motion_transform_size)); + as_mem.push_back(motion_transform_gpu); + + // Allocate host side memory for motion transform and fill it with transform data + OptixSRTMotionTransform &motion_transform = *reinterpret_cast<OptixSRTMotionTransform *>( + new uint8_t[motion_transform_size]); + motion_transform.child = handle; + motion_transform.motionOptions.numKeys = ob->motion.size(); + motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE; + motion_transform.motionOptions.timeBegin = 0.0f; + motion_transform.motionOptions.timeEnd = 1.0f; + + OptixSRTData *const srt_data = motion_transform.srtData; + array<DecomposedTransform> decomp(ob->motion.size()); + transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size()); + + for (size_t i = 0; i < ob->motion.size(); ++i) { + // Scale + srt_data[i].sx = decomp[i].y.w; // scale.x.x + srt_data[i].sy = decomp[i].z.w; // scale.y.y + srt_data[i].sz = decomp[i].w.w; // scale.z.z + + // Shear + srt_data[i].a = decomp[i].z.x; // scale.x.y + srt_data[i].b = decomp[i].z.y; // scale.x.z + srt_data[i].c = decomp[i].w.x; // scale.y.z + assert(decomp[i].z.z == 0.0f); // scale.y.x + assert(decomp[i].w.y == 0.0f); // scale.z.x + assert(decomp[i].w.z == 0.0f); // scale.z.y + + // Pivot point + srt_data[i].pvx = 0.0f; + srt_data[i].pvy = 0.0f; + srt_data[i].pvz = 0.0f; + + // Rotation + srt_data[i].qx = decomp[i].x.x; + srt_data[i].qy = decomp[i].x.y; + srt_data[i].qz = decomp[i].x.z; + srt_data[i].qw = decomp[i].x.w; + + // Translation + srt_data[i].tx = decomp[i].y.x; + srt_data[i].ty = decomp[i].y.y; + srt_data[i].tz = decomp[i].y.z; } - else { - instance.traversableHandle = handle; - if (ob->mesh->is_instanced()) { - // Set transform matrix - memcpy(instance.transform, &ob->tfm, sizeof(instance.transform)); - } - else { - // Disable instance transform if mesh already has it applied to vertex data - instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM; - // Non-instanced objects read ID from prim_object, so - // distinguish them from instanced objects with high bit set - instance.instanceId |= 0x800000; - } + // Upload motion transform to GPU + cuMemcpyHtoD(motion_transform_gpu, &motion_transform, motion_transform_size); + delete[] reinterpret_cast<uint8_t *>(&motion_transform); + + // Disable instance transform if object uses motion transform already + instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM; + + // Get traversable handle to motion transform + optixConvertPointerToTraversableHandle(context, + motion_transform_gpu, + OPTIX_TRAVERSABLE_TYPE_SRT_MOTION_TRANSFORM, + &instance.traversableHandle); + } + else { + instance.traversableHandle = handle; + + if (ob->geometry->is_instanced()) { + // Set transform matrix + memcpy(instance.transform, &ob->tfm, sizeof(instance.transform)); + } + else { + // Disable instance transform if geometry already has it applied to vertex data + instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM; + // Non-instanced objects read ID from prim_object, so + // distinguish them from instanced objects with high bit set + instance.instanceId |= 0x800000; } } } @@ -2603,8 +2619,8 @@ bool device_optix_init() # ifdef WITH_CUDA_DYNLOAD // Load NVRTC function pointers for adaptive kernel compilation if (DebugFlags().cuda.adaptive_compile && cuewInit(CUEW_INIT_NVRTC) != CUEW_SUCCESS) { - VLOG(1) - << "CUEW initialization failed for NVRTC. Adaptive kernel compilation won't be available."; + VLOG(1) << "CUEW initialization failed for NVRTC. Adaptive kernel compilation won't be " + "available."; } # endif diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp index 4f79a7518dc..1439fb5a407 100644 --- a/intern/cycles/graph/node.cpp +++ b/intern/cycles/graph/node.cpp @@ -669,4 +669,14 @@ size_t Node::get_total_size_in_bytes() const return total_size; } +bool Node::is_a(const NodeType *type_) +{ + for (const NodeType *base = type; base; base = base->base) { + if (base == type_) { + return true; + } + } + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h index d35a1bb489c..4473b8aca28 100644 --- a/intern/cycles/graph/node.h +++ b/intern/cycles/graph/node.h @@ -94,6 +94,9 @@ struct Node { /* Get total size of this node. */ size_t get_total_size_in_bytes() const; + /* Type testing, taking into account base classes. */ + bool is_a(const NodeType *type); + ustring name; const NodeType *type; }; diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp index f46d4e48026..0283ed7c817 100644 --- a/intern/cycles/graph/node_type.cpp +++ b/intern/cycles/graph/node_type.cpp @@ -135,8 +135,13 @@ bool SocketType::is_float3(Type type) /* Node Type */ -NodeType::NodeType(Type type_) : type(type_) +NodeType::NodeType(Type type, const NodeType *base) : type(type), base(base) { + if (base) { + /* Inherit sockets. */ + inputs = base->inputs; + outputs = base->outputs; + } } NodeType::~NodeType() @@ -209,7 +214,7 @@ unordered_map<ustring, NodeType, ustringHash> &NodeType::types() return _types; } -NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_) +NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_, const NodeType *base_) { ustring name(name_); @@ -219,7 +224,7 @@ NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_) return NULL; } - types()[name] = NodeType(type_); + types()[name] = NodeType(type_, base_); NodeType *type = &types()[name]; type->name = name; diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h index e9496a42658..a79d44b82f3 100644 --- a/intern/cycles/graph/node_type.h +++ b/intern/cycles/graph/node_type.h @@ -103,7 +103,7 @@ struct SocketType { struct NodeType { enum Type { NONE, SHADER }; - explicit NodeType(Type type = NONE); + explicit NodeType(Type type = NONE, const NodeType *base = NULL); ~NodeType(); void register_input(ustring name, @@ -124,11 +124,15 @@ struct NodeType { ustring name; Type type; + const NodeType *base; vector<SocketType, std::allocator<SocketType>> inputs; vector<SocketType, std::allocator<SocketType>> outputs; CreateFunc create; - static NodeType *add(const char *name, CreateFunc create, Type type = NONE); + static NodeType *add(const char *name, + CreateFunc create, + Type type = NONE, + const NodeType *base = NULL); static const NodeType *find(ustring name); static unordered_map<ustring, NodeType, ustringHash> &types(); }; @@ -148,6 +152,14 @@ struct NodeType { } \ template<typename T> const NodeType *structname::register_type() +#define NODE_ABSTRACT_DECLARE \ + template<typename T> static const NodeType *register_base_type(); \ + static const NodeType *node_base_type; + +#define NODE_ABSTRACT_DEFINE(structname) \ + const NodeType *structname::node_base_type = structname::register_base_type<structname>(); \ + template<typename T> const NodeType *structname::register_base_type() + /* Sock Definition Macros */ #define SOCKET_OFFSETOF(T, name) (((char *)&(((T *)1)->name)) - (char *)1) diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp index a96970cc904..d333400cc4a 100644 --- a/intern/cycles/graph/node_xml.cpp +++ b/intern/cycles/graph/node_xml.cpp @@ -200,7 +200,7 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node) map<ustring, Node *>::iterator it = reader.node_map.find(value); if (it != reader.node_map.end()) { Node *value_node = it->second; - if (value_node->type == *(socket.node_type)) + if (value_node->is_a(*(socket.node_type))) node->set(socket, it->second); } break; @@ -215,7 +215,7 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node) map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i])); if (it != reader.node_map.end()) { Node *value_node = it->second; - value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL; + value[i] = (value_node->is_a(*(socket.node_type))) ? value_node : NULL; } else { value[i] = NULL; diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h index 456608bfa22..e1b0e6fb81c 100644 --- a/intern/cycles/kernel/geom/geom_attribute.h +++ b/intern/cycles/kernel/geom/geom_attribute.h @@ -29,17 +29,11 @@ ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData * ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderData *sd) { -#ifdef __HAIR__ - if (sd->type & PRIMITIVE_ALL_CURVE) { - return ATTR_PRIM_CURVE; - } - else -#endif - if (subd_triangle_patch(kg, sd) != ~0) { + if ((sd->type & PRIMITIVE_ALL_TRIANGLE) && subd_triangle_patch(kg, sd) != ~0) { return ATTR_PRIM_SUBD; } else { - return ATTR_PRIM_TRIANGLE; + return ATTR_PRIM_GEOMETRY; } } diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h index 7380c506bf4..0e2a00e9d2e 100644 --- a/intern/cycles/kernel/geom/geom_motion_curve.h +++ b/intern/cycles/kernel/geom/geom_motion_curve.h @@ -36,7 +36,7 @@ ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, * zero iterations and rendering is really slow with motion curves. For until other * areas are speed up it's probably not so crucial to optimize this out. */ - uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE; + uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_GEOMETRY; uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); while (attr_map.x != id) { diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 4cac6e9ca5f..bf34450df4b 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -725,8 +725,7 @@ typedef enum PrimitiveType { /* Attributes */ typedef enum AttributePrimitive { - ATTR_PRIM_TRIANGLE = 0, - ATTR_PRIM_CURVE, + ATTR_PRIM_GEOMETRY = 0, ATTR_PRIM_SUBD, ATTR_PRIM_TYPES diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index db5ad06d3fc..0994bfaf950 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -382,10 +382,6 @@ int OSLShader::find_attribute(KernelGlobals *kg, { /* for OSL, a hash map is used to lookup the attribute by name. */ int object = sd->object * ATTR_PRIM_TYPES; -#ifdef __HAIR__ - if (sd->type & PRIMITIVE_ALL_CURVE) - object += ATTR_PRIM_CURVE; -#endif OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object]; ustring stdname(std::string("geom:") + diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 92578b888a6..9e876b8d95c 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -19,7 +19,9 @@ set(SRC coverage.cpp denoising.cpp film.cpp + geometry.cpp graph.cpp + hair.cpp image.cpp integrator.cpp light.cpp @@ -54,7 +56,9 @@ set(SRC_HEADERS coverage.h denoising.h film.h + geometry.h graph.h + hair.h image.h integrator.h light.h diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index b65c2faa788..05c0b5693bc 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -15,6 +15,7 @@ */ #include "render/image.h" +#include "render/hair.h" #include "render/mesh.h" #include "render/attribute.h" @@ -52,13 +53,13 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) type == TypeRGBA); } -void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only) +void Attribute::resize(Geometry *geom, AttributePrimitive prim, bool reserve_only) { if (reserve_only) { - buffer.reserve(buffer_size(mesh, prim)); + buffer.reserve(buffer_size(geom, prim)); } else { - buffer.resize(buffer_size(mesh, prim), 0); + buffer.resize(buffer_size(geom, prim), 0); } } @@ -157,13 +158,13 @@ size_t Attribute::data_sizeof() const return sizeof(float3); } -size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const +size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const { if (flags & ATTR_FINAL_SIZE) { return buffer.size() / data_sizeof(); } - size_t size; + size_t size = 0; switch (element) { case ATTR_ELEMENT_OBJECT: @@ -172,54 +173,74 @@ size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const size = 1; break; case ATTR_ELEMENT_VERTEX: - size = mesh->verts.size() + mesh->num_ngons; - if (prim == ATTR_PRIM_SUBD) { - size -= mesh->num_subd_verts; + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + size = mesh->verts.size() + mesh->num_ngons; + if (prim == ATTR_PRIM_SUBD) { + size -= mesh->num_subd_verts; + } } break; case ATTR_ELEMENT_VERTEX_MOTION: - size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1); - if (prim == ATTR_PRIM_SUBD) { - size -= mesh->num_subd_verts * (mesh->motion_steps - 1); + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1); + if (prim == ATTR_PRIM_SUBD) { + size -= mesh->num_subd_verts * (mesh->motion_steps - 1); + } } break; case ATTR_ELEMENT_FACE: - if (prim == ATTR_PRIM_TRIANGLE) { - size = mesh->num_triangles(); - } - else { - size = mesh->subd_faces.size() + mesh->num_ngons; + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (prim == ATTR_PRIM_GEOMETRY) { + size = mesh->num_triangles(); + } + else { + size = mesh->subd_faces.size() + mesh->num_ngons; + } } break; case ATTR_ELEMENT_CORNER: case ATTR_ELEMENT_CORNER_BYTE: - if (prim == ATTR_PRIM_TRIANGLE) { - size = mesh->num_triangles() * 3; - } - else { - size = mesh->subd_face_corners.size() + mesh->num_ngons; + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (prim == ATTR_PRIM_GEOMETRY) { + size = mesh->num_triangles() * 3; + } + else { + size = mesh->subd_face_corners.size() + mesh->num_ngons; + } } break; case ATTR_ELEMENT_CURVE: - size = mesh->num_curves(); + if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + size = hair->num_curves(); + } break; case ATTR_ELEMENT_CURVE_KEY: - size = mesh->curve_keys.size(); + if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + size = hair->curve_keys.size(); + } break; case ATTR_ELEMENT_CURVE_KEY_MOTION: - size = mesh->curve_keys.size() * (mesh->motion_steps - 1); + if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + size = hair->curve_keys.size() * (hair->motion_steps - 1); + } break; default: - size = 0; break; } return size; } -size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const +size_t Attribute::buffer_size(Geometry *geom, AttributePrimitive prim) const { - return element_size(mesh, prim) * data_sizeof(); + return element_size(geom, prim) * data_sizeof(); } bool Attribute::same_storage(TypeDesc a, TypeDesc b) @@ -336,13 +357,42 @@ AttributeStandard Attribute::name_standard(const char *name) return ATTR_STD_NONE; } +void Attribute::get_uv_tiles(Geometry *geom, + AttributePrimitive prim, + unordered_set<int> &tiles) const +{ + if (type != TypeFloat2) { + return; + } + + const int num = element_size(geom, prim); + const float2 *uv = data_float2(); + for (int i = 0; i < num; i++, uv++) { + float u = uv->x, v = uv->y; + int x = (int)u, y = (int)v; + + if (x < 0 || y < 0 || x >= 10) { + continue; + } + + /* Be conservative in corners - precisely touching the right or upper edge of a tile + * should not load its right/upper neighbor as well. */ + if (x > 0 && (u < x + 1e-6f)) { + x--; + } + if (y > 0 && (v < y + 1e-6f)) { + y--; + } + + tiles.insert(1001 + 10 * y + x); + } +} + /* Attribute Set */ -AttributeSet::AttributeSet() +AttributeSet::AttributeSet(Geometry *geometry, AttributePrimitive prim) + : geometry(geometry), prim(prim) { - triangle_mesh = NULL; - curve_mesh = NULL; - subd_mesh = NULL; } AttributeSet::~AttributeSet() @@ -376,12 +426,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme #endif /* this is weak .. */ - if (triangle_mesh) - attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false); - if (curve_mesh) - attr->resize(curve_mesh, ATTR_PRIM_CURVE, false); - if (subd_mesh) - attr->resize(subd_mesh, ATTR_PRIM_SUBD, false); + attr->resize(geometry, prim, false); return attr; } @@ -418,7 +463,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) if (name == ustring()) name = Attribute::standard_name(std); - if (triangle_mesh || subd_mesh) { + if (geometry->type == Geometry::MESH) { switch (std) { case ATTR_STD_VERTEX_NORMAL: attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX); @@ -478,7 +523,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) break; } } - else if (curve_mesh) { + else if (geometry->type == Geometry::HAIR) { switch (std) { case ATTR_STD_UV: attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE); @@ -561,12 +606,7 @@ void AttributeSet::remove(Attribute *attribute) void AttributeSet::resize(bool reserve_only) { foreach (Attribute &attr, attributes) { - if (triangle_mesh) - attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only); - if (curve_mesh) - attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only); - if (subd_mesh) - attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only); + attr.resize(geometry, prim, reserve_only); } } @@ -596,15 +636,10 @@ AttributeRequest::AttributeRequest(ustring name_) name = name_; std = ATTR_STD_NONE; - triangle_type = TypeDesc::TypeFloat; - triangle_desc.element = ATTR_ELEMENT_NONE; - triangle_desc.offset = 0; - triangle_desc.type = NODE_ATTR_FLOAT; - - curve_type = TypeDesc::TypeFloat; - curve_desc.element = ATTR_ELEMENT_NONE; - curve_desc.offset = 0; - curve_desc.type = NODE_ATTR_FLOAT; + type = TypeDesc::TypeFloat; + desc.element = ATTR_ELEMENT_NONE; + desc.offset = 0; + desc.type = NODE_ATTR_FLOAT; subd_type = TypeDesc::TypeFloat; subd_desc.element = ATTR_ELEMENT_NONE; @@ -617,15 +652,10 @@ AttributeRequest::AttributeRequest(AttributeStandard std_) name = ustring(); std = std_; - triangle_type = TypeDesc::TypeFloat; - triangle_desc.element = ATTR_ELEMENT_NONE; - triangle_desc.offset = 0; - triangle_desc.type = NODE_ATTR_FLOAT; - - curve_type = TypeDesc::TypeFloat; - curve_desc.element = ATTR_ELEMENT_NONE; - curve_desc.offset = 0; - curve_desc.type = NODE_ATTR_FLOAT; + type = TypeDesc::TypeFloat; + desc.element = ATTR_ELEMENT_NONE; + desc.offset = 0; + desc.type = NODE_ATTR_FLOAT; subd_type = TypeDesc::TypeFloat; subd_desc.element = ATTR_ELEMENT_NONE; diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index ebab0fe7f88..f1fd30fd85a 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -21,6 +21,7 @@ #include "util/util_list.h" #include "util/util_param.h" +#include "util/util_set.h" #include "util/util_types.h" #include "util/util_vector.h" @@ -31,6 +32,8 @@ class AttributeRequest; class AttributeRequestSet; class AttributeSet; class ImageManager; +class Geometry; +class Hair; class Mesh; struct Transform; @@ -61,12 +64,12 @@ class Attribute { } ~Attribute(); void set(ustring name, TypeDesc type, AttributeElement element); - void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only); + void resize(Geometry *geom, AttributePrimitive prim, bool reserve_only); void resize(size_t num_elements); size_t data_sizeof() const; - size_t element_size(Mesh *mesh, AttributePrimitive prim) const; - size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const; + size_t element_size(Geometry *geom, AttributePrimitive prim) const; + size_t buffer_size(Geometry *geom, AttributePrimitive prim) const; char *data() { @@ -157,6 +160,8 @@ class Attribute { static bool same_storage(TypeDesc a, TypeDesc b); static const char *standard_name(AttributeStandard std); static AttributeStandard name_standard(const char *name); + + void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set<int> &tiles) const; }; /* Attribute Set @@ -165,12 +170,11 @@ class Attribute { class AttributeSet { public: - Mesh *triangle_mesh; - Mesh *curve_mesh; - Mesh *subd_mesh; + Geometry *geometry; + AttributePrimitive prim; list<Attribute> attributes; - AttributeSet(); + AttributeSet(Geometry *geometry, AttributePrimitive prim); ~AttributeSet(); Attribute *add(ustring name, TypeDesc type, AttributeElement element); @@ -200,9 +204,9 @@ class AttributeRequest { ustring name; AttributeStandard std; - /* temporary variables used by MeshManager */ - TypeDesc triangle_type, curve_type, subd_type; - AttributeDescriptor triangle_desc, curve_desc, subd_desc; + /* temporary variables used by GeometryManager */ + TypeDesc type, subd_type; + AttributeDescriptor desc, subd_desc; explicit AttributeRequest(ustring name_); explicit AttributeRequest(AttributeStandard std); diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index b906357b7b5..9613da7c152 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -253,8 +253,8 @@ int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType ty /* Only antialias normal if mesh has bump mapping. */ Object *object = scene->objects[bake_data->object()]; - if (object->mesh) { - foreach (Shader *shader, object->mesh->used_shaders) { + if (object->geometry) { + foreach (Shader *shader, object->geometry->used_shaders) { if (shader->has_bump) { return scene->integrator->aa_samples; } diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 38306a63c74..14ccf6696bd 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -498,7 +498,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen BoundBox viewplane_boundbox = viewplane_bounds_get(); for (size_t i = 0; i < scene->objects.size(); ++i) { Object *object = scene->objects[i]; - if (object->mesh->has_volume && viewplane_boundbox.intersects(object->bounds)) { + if (object->geometry->has_volume && viewplane_boundbox.intersects(object->bounds)) { /* TODO(sergey): Consider adding more grained check. */ VLOG(1) << "Detected camera inside volume."; kcam->is_inside_volume = 1; diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 4af0f3c45f0..00356790261 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -593,13 +593,13 @@ bool Film::modified(const Film &film) void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes) { if (Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) { - scene->mesh_manager->tag_update(scene); + scene->geometry_manager->tag_update(scene); foreach (Shader *shader, scene->shaders) - shader->need_update_mesh = true; + shader->need_update_geometry = true; } else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) { - scene->mesh_manager->tag_update(scene); + scene->geometry_manager->tag_update(scene); } else if (Pass::contains(passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) { scene->integrator->tag_update(scene); diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp new file mode 100644 index 00000000000..880fb7b4c7d --- /dev/null +++ b/intern/cycles/render/geometry.cpp @@ -0,0 +1,1469 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bvh/bvh.h" +#include "bvh/bvh_build.h" + +#ifdef WITH_EMBREE +# include "bvh/bvh_embree.h" +#endif + +#include "render/attribute.h" +#include "render/camera.h" +#include "render/geometry.h" +#include "render/hair.h" +#include "render/light.h" +#include "render/mesh.h" +#include "render/nodes.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/shader.h" +#include "render/stats.h" + +#include "subd/subd_split.h" +#include "subd/subd_patch_table.h" + +#include "kernel/osl/osl_globals.h" + +#include "util/util_foreach.h" +#include "util/util_logging.h" +#include "util/util_progress.h" + +CCL_NAMESPACE_BEGIN + +/* Geometry */ + +NODE_ABSTRACT_DEFINE(Geometry) +{ + NodeType *type = NodeType::add("geometry_base", NULL); + + SOCKET_UINT(motion_steps, "Motion Steps", 3); + SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false); + + return type; +} + +Geometry::Geometry(const NodeType *node_type, const Type type) + : Node(node_type), type(type), attributes(this, ATTR_PRIM_GEOMETRY) +{ + need_update = true; + need_update_rebuild = false; + + transform_applied = false; + transform_negative_scaled = false; + transform_normal = transform_identity(); + bounds = BoundBox::empty; + + has_volume = false; + has_surface_bssrdf = false; + + bvh = NULL; + attr_map_offset = 0; + optix_prim_offset = 0; + prim_offset = 0; +} + +Geometry::~Geometry() +{ + delete bvh; +} + +void Geometry::clear() +{ + used_shaders.clear(); + transform_applied = false; + transform_negative_scaled = false; + transform_normal = transform_identity(); +} + +bool Geometry::need_attribute(Scene *scene, AttributeStandard std) +{ + if (std == ATTR_STD_NONE) + return false; + + if (scene->need_global_attribute(std)) + return true; + + foreach (Shader *shader, used_shaders) + if (shader->attributes.find(std)) + return true; + + return false; +} + +bool Geometry::need_attribute(Scene * /*scene*/, ustring name) +{ + if (name == ustring()) + return false; + + foreach (Shader *shader, used_shaders) + if (shader->attributes.find(name)) + return true; + + return false; +} + +float Geometry::motion_time(int step) const +{ + return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; +} + +int Geometry::motion_step(float time) const +{ + if (motion_steps > 1) { + int attr_step = 0; + + for (int step = 0; step < motion_steps; step++) { + float step_time = motion_time(step); + if (step_time == time) { + return attr_step; + } + + /* Center step is stored in a separate attribute. */ + if (step != motion_steps / 2) { + attr_step++; + } + } + } + + return -1; +} + +bool Geometry::need_build_bvh(BVHLayout layout) const +{ + return !transform_applied || has_surface_bssrdf || layout == BVH_LAYOUT_OPTIX; +} + +bool Geometry::is_instanced() const +{ + /* Currently we treat subsurface objects as instanced. + * + * While it might be not very optimal for ray traversal, it avoids having + * duplicated BVH in the memory, saving quite some space. + */ + return !transform_applied || has_surface_bssrdf; +} + +bool Geometry::has_true_displacement() const +{ + foreach (Shader *shader, used_shaders) { + if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) { + return true; + } + } + + return false; +} + +void Geometry::compute_bvh( + Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total) +{ + if (progress->get_cancel()) + return; + + compute_bounds(); + + const BVHLayout bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout, + device->get_bvh_layout_mask()); + if (need_build_bvh(bvh_layout)) { + string msg = "Updating Geometry BVH "; + if (name.empty()) + msg += string_printf("%u/%u", (uint)(n + 1), (uint)total); + else + msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total); + + Object object; + object.geometry = this; + + vector<Geometry *> geometry; + geometry.push_back(this); + vector<Object *> objects; + objects.push_back(&object); + + if (bvh && !need_update_rebuild) { + progress->set_status(msg, "Refitting BVH"); + + bvh->geometry = geometry; + bvh->objects = objects; + + bvh->refit(*progress); + } + else { + progress->set_status(msg, "Building BVH"); + + BVHParams bparams; + bparams.use_spatial_split = params->use_bvh_spatial_split; + bparams.bvh_layout = bvh_layout; + bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && + params->use_bvh_unaligned_nodes; + bparams.num_motion_triangle_steps = params->num_bvh_time_steps; + bparams.num_motion_curve_steps = params->num_bvh_time_steps; + bparams.bvh_type = params->bvh_type; + bparams.curve_flags = dscene->data.curve.curveflags; + bparams.curve_subdivisions = dscene->data.curve.subdivisions; + + delete bvh; + bvh = BVH::create(bparams, geometry, objects); + MEM_GUARDED_CALL(progress, bvh->build, *progress); + } + } + + need_update = false; + need_update_rebuild = false; +} + +bool Geometry::has_motion_blur() const +{ + return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)); +} + +bool Geometry::has_voxel_attributes() const +{ + foreach (const Attribute &attr, attributes.attributes) { + if (attr.element == ATTR_ELEMENT_VOXEL) { + return true; + } + } + + return false; +} + +void Geometry::tag_update(Scene *scene, bool rebuild) +{ + need_update = true; + + if (rebuild) { + need_update_rebuild = true; + scene->light_manager->need_update = true; + } + else { + foreach (Shader *shader, used_shaders) + if (shader->has_surface_emission) + scene->light_manager->need_update = true; + } + + scene->geometry_manager->need_update = true; + scene->object_manager->need_update = true; +} + +/* Geometry Manager */ + +GeometryManager::GeometryManager() +{ + need_update = true; + need_flags_update = true; +} + +GeometryManager::~GeometryManager() +{ +} + +void GeometryManager::update_osl_attributes(Device *device, + Scene *scene, + vector<AttributeRequestSet> &geom_attributes) +{ +#ifdef WITH_OSL + /* for OSL, a hash map is used to lookup the attribute by name. */ + OSLGlobals *og = (OSLGlobals *)device->osl_memory(); + + og->object_name_map.clear(); + og->attribute_map.clear(); + og->object_names.clear(); + + og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES); + + for (size_t i = 0; i < scene->objects.size(); i++) { + /* set object name to object index map */ + Object *object = scene->objects[i]; + og->object_name_map[object->name] = i; + og->object_names.push_back(object->name); + + /* set object attributes */ + foreach (ParamValue &attr, object->attributes) { + OSLGlobals::Attribute osl_attr; + + osl_attr.type = attr.type(); + osl_attr.desc.element = ATTR_ELEMENT_OBJECT; + osl_attr.value = attr; + osl_attr.desc.offset = 0; + osl_attr.desc.flags = 0; + + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][attr.name()] = osl_attr; + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr; + } + + /* find geometry attributes */ + size_t j; + + for (j = 0; j < scene->geometry.size(); j++) + if (scene->geometry[j] == object->geometry) + break; + + AttributeRequestSet &attributes = geom_attributes[j]; + + /* set object attributes */ + foreach (AttributeRequest &req, attributes.requests) { + OSLGlobals::Attribute osl_attr; + + if (req.desc.element != ATTR_ELEMENT_NONE) { + osl_attr.desc = req.desc; + + if (req.type == TypeDesc::TypeFloat) + osl_attr.type = TypeDesc::TypeFloat; + else if (req.type == TypeDesc::TypeMatrix) + osl_attr.type = TypeDesc::TypeMatrix; + else if (req.type == TypeFloat2) + osl_attr.type = TypeFloat2; + else if (req.type == TypeRGBA) + osl_attr.type = TypeRGBA; + else + osl_attr.type = TypeDesc::TypeColor; + + if (req.std != ATTR_STD_NONE) { + /* if standard attribute, add lookup by geom: name convention */ + ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][stdname] = osl_attr; + } + else if (req.name != ustring()) { + /* add lookup by geometry attribute name */ + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][req.name] = osl_attr; + } + } + + if (req.subd_desc.element != ATTR_ELEMENT_NONE) { + osl_attr.desc = req.subd_desc; + + if (req.subd_type == TypeDesc::TypeFloat) + osl_attr.type = TypeDesc::TypeFloat; + else if (req.subd_type == TypeDesc::TypeMatrix) + osl_attr.type = TypeDesc::TypeMatrix; + else if (req.subd_type == TypeFloat2) + osl_attr.type = TypeFloat2; + else if (req.subd_type == TypeRGBA) + osl_attr.type = TypeRGBA; + else + osl_attr.type = TypeDesc::TypeColor; + + if (req.std != ATTR_STD_NONE) { + /* if standard attribute, add lookup by geom: name convention */ + ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr; + } + else if (req.name != ustring()) { + /* add lookup by geometry attribute name */ + og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr; + } + } + } + } +#else + (void)device; + (void)scene; + (void)geom_attributes; +#endif +} + +void GeometryManager::update_svm_attributes(Device *, + DeviceScene *dscene, + Scene *scene, + vector<AttributeRequestSet> &geom_attributes) +{ + /* for SVM, the attributes_map table is used to lookup the offset of an + * attribute, based on a unique shader attribute id. */ + + /* compute array stride */ + int attr_map_size = 0; + + for (size_t i = 0; i < scene->geometry.size(); i++) { + Geometry *geom = scene->geometry[i]; + geom->attr_map_offset = attr_map_size; + attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES; + } + + if (attr_map_size == 0) + return; + + /* create attribute map */ + uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); + memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); + + for (size_t i = 0; i < scene->geometry.size(); i++) { + Geometry *geom = scene->geometry[i]; + AttributeRequestSet &attributes = geom_attributes[i]; + + /* set object attributes */ + int index = geom->attr_map_offset; + + foreach (AttributeRequest &req, attributes.requests) { + uint id; + + if (req.std == ATTR_STD_NONE) + id = scene->shader_manager->get_attribute_id(req.name); + else + id = scene->shader_manager->get_attribute_id(req.std); + + attr_map[index].x = id; + attr_map[index].y = req.desc.element; + attr_map[index].z = as_uint(req.desc.offset); + + if (req.type == TypeDesc::TypeFloat) + attr_map[index].w = NODE_ATTR_FLOAT; + else if (req.type == TypeDesc::TypeMatrix) + attr_map[index].w = NODE_ATTR_MATRIX; + else if (req.type == TypeFloat2) + attr_map[index].w = NODE_ATTR_FLOAT2; + else if (req.type == TypeRGBA) + attr_map[index].w = NODE_ATTR_RGBA; + else + attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= req.desc.flags << 8; + + index++; + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->subd_faces.size()) { + attr_map[index].x = id; + attr_map[index].y = req.subd_desc.element; + attr_map[index].z = as_uint(req.subd_desc.offset); + + if (req.subd_type == TypeDesc::TypeFloat) + attr_map[index].w = NODE_ATTR_FLOAT; + else if (req.subd_type == TypeDesc::TypeMatrix) + attr_map[index].w = NODE_ATTR_MATRIX; + else if (req.subd_type == TypeFloat2) + attr_map[index].w = NODE_ATTR_FLOAT2; + else if (req.subd_type == TypeRGBA) + attr_map[index].w = NODE_ATTR_RGBA; + else + attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= req.subd_desc.flags << 8; + } + } + + index++; + } + + /* terminator */ + for (int j = 0; j < ATTR_PRIM_TYPES; j++) { + attr_map[index].x = ATTR_STD_NONE; + attr_map[index].y = 0; + attr_map[index].z = 0; + attr_map[index].w = 0; + + index++; + } + } + + /* copy to device */ + dscene->attributes_map.copy_to_device(); +} + +static void update_attribute_element_size(Geometry *geom, + Attribute *mattr, + AttributePrimitive prim, + size_t *attr_float_size, + size_t *attr_float2_size, + size_t *attr_float3_size, + size_t *attr_uchar4_size) +{ + if (mattr) { + size_t size = mattr->element_size(geom, prim); + + if (mattr->element == ATTR_ELEMENT_VOXEL) { + /* pass */ + } + else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { + *attr_uchar4_size += size; + } + else if (mattr->type == TypeDesc::TypeFloat) { + *attr_float_size += size; + } + else if (mattr->type == TypeFloat2) { + *attr_float2_size += size; + } + else if (mattr->type == TypeDesc::TypeMatrix) { + *attr_float3_size += size * 4; + } + else { + *attr_float3_size += size; + } + } +} + +static void update_attribute_element_offset(Geometry *geom, + device_vector<float> &attr_float, + size_t &attr_float_offset, + device_vector<float2> &attr_float2, + size_t &attr_float2_offset, + device_vector<float4> &attr_float3, + size_t &attr_float3_offset, + device_vector<uchar4> &attr_uchar4, + size_t &attr_uchar4_offset, + Attribute *mattr, + AttributePrimitive prim, + TypeDesc &type, + AttributeDescriptor &desc) +{ + if (mattr) { + /* store element and type */ + desc.element = mattr->element; + desc.flags = mattr->flags; + type = mattr->type; + + /* store attribute data in arrays */ + size_t size = mattr->element_size(geom, prim); + + AttributeElement &element = desc.element; + int &offset = desc.offset; + + if (mattr->element == ATTR_ELEMENT_VOXEL) { + /* store slot in offset value */ + VoxelAttribute *voxel_data = mattr->data_voxel(); + offset = voxel_data->slot; + } + else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { + uchar4 *data = mattr->data_uchar4(); + offset = attr_uchar4_offset; + + assert(attr_uchar4.size() >= offset + size); + for (size_t k = 0; k < size; k++) { + attr_uchar4[offset + k] = data[k]; + } + attr_uchar4_offset += size; + } + else if (mattr->type == TypeDesc::TypeFloat) { + float *data = mattr->data_float(); + offset = attr_float_offset; + + assert(attr_float.size() >= offset + size); + for (size_t k = 0; k < size; k++) { + attr_float[offset + k] = data[k]; + } + attr_float_offset += size; + } + else if (mattr->type == TypeFloat2) { + float2 *data = mattr->data_float2(); + offset = attr_float2_offset; + + assert(attr_float2.size() >= offset + size); + for (size_t k = 0; k < size; k++) { + attr_float2[offset + k] = data[k]; + } + attr_float2_offset += size; + } + else if (mattr->type == TypeDesc::TypeMatrix) { + Transform *tfm = mattr->data_transform(); + offset = attr_float3_offset; + + assert(attr_float3.size() >= offset + size * 3); + for (size_t k = 0; k < size * 3; k++) { + attr_float3[offset + k] = (&tfm->x)[k]; + } + attr_float3_offset += size * 3; + } + else { + float4 *data = mattr->data_float4(); + offset = attr_float3_offset; + + assert(attr_float3.size() >= offset + size); + for (size_t k = 0; k < size; k++) { + attr_float3[offset + k] = data[k]; + } + attr_float3_offset += size; + } + + /* mesh vertex/curve index is global, not per object, so we sneak + * a correction for that in here */ + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && + desc.flags & ATTR_SUBDIVIDED) { + /* indices for subdivided attributes are retrieved + * from patch table so no need for correction here*/ + } + else if (element == ATTR_ELEMENT_VERTEX) + offset -= mesh->vert_offset; + else if (element == ATTR_ELEMENT_VERTEX_MOTION) + offset -= mesh->vert_offset; + else if (element == ATTR_ELEMENT_FACE) { + if (prim == ATTR_PRIM_GEOMETRY) + offset -= mesh->prim_offset; + else + offset -= mesh->face_offset; + } + else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) { + if (prim == ATTR_PRIM_GEOMETRY) + offset -= 3 * mesh->prim_offset; + else + offset -= mesh->corner_offset; + } + } + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + if (element == ATTR_ELEMENT_CURVE) + offset -= hair->prim_offset; + else if (element == ATTR_ELEMENT_CURVE_KEY) + offset -= hair->curvekey_offset; + else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) + offset -= hair->curvekey_offset; + } + } + else { + /* attribute not found */ + desc.element = ATTR_ELEMENT_NONE; + desc.offset = 0; + } +} + +void GeometryManager::device_update_attributes(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) +{ + progress.set_status("Updating Mesh", "Computing attributes"); + + /* gather per mesh requested attributes. as meshes may have multiple + * shaders assigned, this merges the requested attributes that have + * been set per shader by the shader manager */ + vector<AttributeRequestSet> geom_attributes(scene->geometry.size()); + + for (size_t i = 0; i < scene->geometry.size(); i++) { + Geometry *geom = scene->geometry[i]; + + scene->need_global_attributes(geom_attributes[i]); + + foreach (Shader *shader, geom->used_shaders) { + geom_attributes[i].add(shader->attributes); + } + } + + /* mesh attribute are stored in a single array per data type. here we fill + * those arrays, and set the offset and element type to create attribute + * maps next */ + + /* Pre-allocate attributes to avoid arrays re-allocation which would + * take 2x of overall attribute memory usage. + */ + size_t attr_float_size = 0; + size_t attr_float2_size = 0; + size_t attr_float3_size = 0; + size_t attr_uchar4_size = 0; + for (size_t i = 0; i < scene->geometry.size(); i++) { + Geometry *geom = scene->geometry[i]; + AttributeRequestSet &attributes = geom_attributes[i]; + foreach (AttributeRequest &req, attributes.requests) { + Attribute *attr = geom->attributes.find(req); + + update_attribute_element_size(geom, + attr, + ATTR_PRIM_GEOMETRY, + &attr_float_size, + &attr_float2_size, + &attr_float3_size, + &attr_uchar4_size); + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + Attribute *subd_attr = mesh->subd_attributes.find(req); + + update_attribute_element_size(mesh, + subd_attr, + ATTR_PRIM_SUBD, + &attr_float_size, + &attr_float2_size, + &attr_float3_size, + &attr_uchar4_size); + } + } + } + + dscene->attributes_float.alloc(attr_float_size); + dscene->attributes_float2.alloc(attr_float2_size); + dscene->attributes_float3.alloc(attr_float3_size); + dscene->attributes_uchar4.alloc(attr_uchar4_size); + + size_t attr_float_offset = 0; + size_t attr_float2_offset = 0; + size_t attr_float3_offset = 0; + size_t attr_uchar4_offset = 0; + + /* Fill in attributes. */ + for (size_t i = 0; i < scene->geometry.size(); i++) { + Geometry *geom = scene->geometry[i]; + AttributeRequestSet &attributes = geom_attributes[i]; + + /* todo: we now store std and name attributes from requests even if + * they actually refer to the same mesh attributes, optimize */ + foreach (AttributeRequest &req, attributes.requests) { + Attribute *attr = geom->attributes.find(req); + update_attribute_element_offset(geom, + dscene->attributes_float, + attr_float_offset, + dscene->attributes_float2, + attr_float2_offset, + dscene->attributes_float3, + attr_float3_offset, + dscene->attributes_uchar4, + attr_uchar4_offset, + attr, + ATTR_PRIM_GEOMETRY, + req.type, + req.desc); + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + Attribute *subd_attr = mesh->subd_attributes.find(req); + + update_attribute_element_offset(mesh, + dscene->attributes_float, + attr_float_offset, + dscene->attributes_float2, + attr_float2_offset, + dscene->attributes_float3, + attr_float3_offset, + dscene->attributes_uchar4, + attr_uchar4_offset, + subd_attr, + ATTR_PRIM_SUBD, + req.subd_type, + req.subd_desc); + } + + if (progress.get_cancel()) + return; + } + } + + /* create attribute lookup maps */ + if (scene->shader_manager->use_osl()) + update_osl_attributes(device, scene, geom_attributes); + + update_svm_attributes(device, dscene, scene, geom_attributes); + + if (progress.get_cancel()) + return; + + /* copy to device */ + progress.set_status("Updating Mesh", "Copying Attributes to device"); + + if (dscene->attributes_float.size()) { + dscene->attributes_float.copy_to_device(); + } + if (dscene->attributes_float2.size()) { + dscene->attributes_float2.copy_to_device(); + } + if (dscene->attributes_float3.size()) { + dscene->attributes_float3.copy_to_device(); + } + if (dscene->attributes_uchar4.size()) { + dscene->attributes_uchar4.copy_to_device(); + } + + if (progress.get_cancel()) + return; + + /* After mesh attributes and patch tables have been copied to device memory, + * we need to update offsets in the objects. */ + scene->object_manager->device_update_mesh_offsets(device, dscene, scene); +} + +void GeometryManager::mesh_calc_offset(Scene *scene) +{ + size_t vert_size = 0; + size_t tri_size = 0; + + size_t curve_key_size = 0; + size_t curve_size = 0; + + size_t patch_size = 0; + size_t face_size = 0; + size_t corner_size = 0; + + size_t optix_prim_size = 0; + + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + + mesh->vert_offset = vert_size; + mesh->prim_offset = tri_size; + + mesh->patch_offset = patch_size; + mesh->face_offset = face_size; + mesh->corner_offset = corner_size; + + vert_size += mesh->verts.size(); + tri_size += mesh->num_triangles(); + + if (mesh->subd_faces.size()) { + Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1]; + patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; + + /* patch tables are stored in same array so include them in patch_size */ + if (mesh->patch_table) { + mesh->patch_table_offset = patch_size; + patch_size += mesh->patch_table->total_size(); + } + } + + face_size += mesh->subd_faces.size(); + corner_size += mesh->subd_face_corners.size(); + + mesh->optix_prim_offset = optix_prim_size; + optix_prim_size += mesh->num_triangles(); + } + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + + hair->curvekey_offset = curve_key_size; + hair->prim_offset = curve_size; + + curve_key_size += hair->curve_keys.size(); + curve_size += hair->num_curves(); + + hair->optix_prim_offset = optix_prim_size; + optix_prim_size += hair->num_segments(); + } + } +} + +void GeometryManager::device_update_mesh( + Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress) +{ + /* Count. */ + size_t vert_size = 0; + size_t tri_size = 0; + + size_t curve_key_size = 0; + size_t curve_size = 0; + + size_t patch_size = 0; + + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + + vert_size += mesh->verts.size(); + tri_size += mesh->num_triangles(); + + if (mesh->subd_faces.size()) { + Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1]; + patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; + + /* patch tables are stored in same array so include them in patch_size */ + if (mesh->patch_table) { + mesh->patch_table_offset = patch_size; + patch_size += mesh->patch_table->total_size(); + } + } + } + else if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + + curve_key_size += hair->curve_keys.size(); + curve_size += hair->num_curves(); + } + } + + /* Create mapping from triangle to primitive triangle array. */ + vector<uint> tri_prim_index(tri_size); + if (for_displacement) { + /* For displacement kernels we do some trickery to make them believe + * we've got all required data ready. However, that data is different + * from final render kernels since we don't have BVH yet, so can't + * really use same semantic of arrays. + */ + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + for (size_t i = 0; i < mesh->num_triangles(); ++i) { + tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset); + } + } + } + } + else { + for (size_t i = 0; i < dscene->prim_index.size(); ++i) { + if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { + tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i]; + } + } + } + + /* Fill in all the arrays. */ + if (tri_size != 0) { + /* normals */ + progress.set_status("Updating Mesh", "Computing normals"); + + uint *tri_shader = dscene->tri_shader.alloc(tri_size); + float4 *vnormal = dscene->tri_vnormal.alloc(vert_size); + uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size); + uint *tri_patch = dscene->tri_patch.alloc(tri_size); + float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); + + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); + mesh->pack_normals(&vnormal[mesh->vert_offset]); + mesh->pack_verts(tri_prim_index, + &tri_vindex[mesh->prim_offset], + &tri_patch[mesh->prim_offset], + &tri_patch_uv[mesh->vert_offset], + mesh->vert_offset, + mesh->prim_offset); + if (progress.get_cancel()) + return; + } + } + + /* vertex coordinates */ + progress.set_status("Updating Mesh", "Copying Mesh to device"); + + dscene->tri_shader.copy_to_device(); + dscene->tri_vnormal.copy_to_device(); + dscene->tri_vindex.copy_to_device(); + dscene->tri_patch.copy_to_device(); + dscene->tri_patch_uv.copy_to_device(); + } + + if (curve_size != 0) { + progress.set_status("Updating Mesh", "Copying Strands to device"); + + float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); + float4 *curves = dscene->curves.alloc(curve_size); + + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + hair->pack_curves(scene, + &curve_keys[hair->curvekey_offset], + &curves[hair->prim_offset], + hair->curvekey_offset); + if (progress.get_cancel()) + return; + } + } + + dscene->curve_keys.copy_to_device(); + dscene->curves.copy_to_device(); + } + + if (patch_size != 0) { + progress.set_status("Updating Mesh", "Copying Patches to device"); + + uint *patch_data = dscene->patches.alloc(patch_size); + + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + mesh->pack_patches(&patch_data[mesh->patch_offset], + mesh->vert_offset, + mesh->face_offset, + mesh->corner_offset); + + if (mesh->patch_table) { + mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], + mesh->patch_table_offset); + } + + if (progress.get_cancel()) + return; + } + } + + dscene->patches.copy_to_device(); + } + + if (for_displacement) { + float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3); + foreach (Geometry *geom, scene->geometry) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + for (size_t i = 0; i < mesh->num_triangles(); ++i) { + Mesh::Triangle t = mesh->get_triangle(i); + size_t offset = 3 * (i + mesh->prim_offset); + prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]); + prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]); + prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]); + } + } + } + dscene->prim_tri_verts.copy_to_device(); + } +} + +void GeometryManager::device_update_bvh(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) +{ + /* bvh build */ + progress.set_status("Updating Scene BVH", "Building"); + + BVHParams bparams; + bparams.top_level = true; + bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, + device->get_bvh_layout_mask()); + bparams.use_spatial_split = scene->params.use_bvh_spatial_split; + bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && + scene->params.use_bvh_unaligned_nodes; + bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps; + bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps; + bparams.bvh_type = scene->params.bvh_type; + bparams.curve_flags = dscene->data.curve.curveflags; + bparams.curve_subdivisions = dscene->data.curve.subdivisions; + + VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; + +#ifdef WITH_EMBREE + if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { + if (dscene->data.bvh.scene) { + BVHEmbree::destroy(dscene->data.bvh.scene); + } + } +#endif + + BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects); + bvh->build(progress, &device->stats); + + if (progress.get_cancel()) { +#ifdef WITH_EMBREE + if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { + if (dscene->data.bvh.scene) { + BVHEmbree::destroy(dscene->data.bvh.scene); + } + } +#endif + delete bvh; + return; + } + + /* copy to device */ + progress.set_status("Updating Scene BVH", "Copying BVH to device"); + + PackedBVH &pack = bvh->pack; + + if (pack.nodes.size()) { + dscene->bvh_nodes.steal_data(pack.nodes); + dscene->bvh_nodes.copy_to_device(); + } + if (pack.leaf_nodes.size()) { + dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes); + dscene->bvh_leaf_nodes.copy_to_device(); + } + if (pack.object_node.size()) { + dscene->object_node.steal_data(pack.object_node); + dscene->object_node.copy_to_device(); + } + if (pack.prim_tri_index.size()) { + dscene->prim_tri_index.steal_data(pack.prim_tri_index); + dscene->prim_tri_index.copy_to_device(); + } + if (pack.prim_tri_verts.size()) { + dscene->prim_tri_verts.steal_data(pack.prim_tri_verts); + dscene->prim_tri_verts.copy_to_device(); + } + if (pack.prim_type.size()) { + dscene->prim_type.steal_data(pack.prim_type); + dscene->prim_type.copy_to_device(); + } + if (pack.prim_visibility.size()) { + dscene->prim_visibility.steal_data(pack.prim_visibility); + dscene->prim_visibility.copy_to_device(); + } + if (pack.prim_index.size()) { + dscene->prim_index.steal_data(pack.prim_index); + dscene->prim_index.copy_to_device(); + } + if (pack.prim_object.size()) { + dscene->prim_object.steal_data(pack.prim_object); + dscene->prim_object.copy_to_device(); + } + if (pack.prim_time.size()) { + dscene->prim_time.steal_data(pack.prim_time); + dscene->prim_time.copy_to_device(); + } + + dscene->data.bvh.root = pack.root_index; + dscene->data.bvh.bvh_layout = bparams.bvh_layout; + dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); + + bvh->copy_to_device(progress, dscene); + + delete bvh; +} + +void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) +{ + if (!need_update && !need_flags_update) { + return; + } + + progress.set_status("Updating Meshes Flags"); + + /* Update flags. */ + bool volume_images_updated = false; + + foreach (Geometry *geom, scene->geometry) { + geom->has_volume = false; + + foreach (const Shader *shader, geom->used_shaders) { + if (shader->has_volume) { + geom->has_volume = true; + } + if (shader->has_surface_bssrdf) { + geom->has_surface_bssrdf = true; + } + } + + if (need_update && geom->has_volume && geom->type == Geometry::MESH) { + /* Create volume meshes if there is voxel data. */ + if (geom->has_voxel_attributes()) { + if (!volume_images_updated) { + progress.set_status("Updating Meshes Volume Bounds"); + device_update_volume_images(device, scene, progress); + volume_images_updated = true; + } + + Mesh *mesh = static_cast<Mesh *>(geom); + create_volume_mesh(scene, mesh, progress); + } + } + } + + need_flags_update = false; +} + +void GeometryManager::device_update_displacement_images(Device *device, + Scene *scene, + Progress &progress) +{ + progress.set_status("Updating Displacement Images"); + TaskPool pool; + ImageManager *image_manager = scene->image_manager; + set<int> bump_images; + foreach (Geometry *geom, scene->geometry) { + if (geom->need_update) { + foreach (Shader *shader, geom->used_shaders) { + if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { + continue; + } + foreach (ShaderNode *node, shader->graph->nodes) { + if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { + continue; + } + + ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); + foreach (int slot, image_node->slots) { + if (slot != -1) { + bump_images.insert(slot); + } + } + } + } + } + } + foreach (int slot, bump_images) { + pool.push(function_bind( + &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress)); + } + pool.wait_work(); +} + +void GeometryManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress) +{ + progress.set_status("Updating Volume Images"); + TaskPool pool; + ImageManager *image_manager = scene->image_manager; + set<int> volume_images; + + foreach (Geometry *geom, scene->geometry) { + if (!geom->need_update) { + continue; + } + + foreach (Attribute &attr, geom->attributes.attributes) { + if (attr.element != ATTR_ELEMENT_VOXEL) { + continue; + } + + VoxelAttribute *voxel = attr.data_voxel(); + + if (voxel->slot != -1) { + volume_images.insert(voxel->slot); + } + } + } + + foreach (int slot, volume_images) { + pool.push(function_bind( + &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress)); + } + pool.wait_work(); +} + +void GeometryManager::device_update(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) +{ + if (!need_update) + return; + + VLOG(1) << "Total " << scene->geometry.size() << " meshes."; + + bool true_displacement_used = false; + size_t total_tess_needed = 0; + + foreach (Geometry *geom, scene->geometry) { + foreach (Shader *shader, geom->used_shaders) { + if (shader->need_update_geometry) + geom->need_update = true; + } + + if (geom->need_update && geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + + /* Update normals. */ + mesh->add_face_normals(); + mesh->add_vertex_normals(); + + if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) { + mesh->add_undisplaced(); + } + + /* Test if we need tessellation. */ + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 && + mesh->subd_params) { + total_tess_needed++; + } + + /* Test if we need displacement. */ + if (mesh->has_true_displacement()) { + true_displacement_used = true; + } + + if (progress.get_cancel()) + return; + } + } + + /* Tessellate meshes that are using subdivision */ + if (total_tess_needed) { + Camera *dicing_camera = scene->dicing_camera; + dicing_camera->update(scene); + + size_t i = 0; + foreach (Geometry *geom, scene->geometry) { + if (!(geom->need_update && geom->type == Geometry::MESH)) { + continue; + } + + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 && + mesh->subd_params) { + string msg = "Tessellating "; + if (mesh->name == "") + msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed); + else + msg += string_printf( + "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed); + + progress.set_status("Updating Mesh", msg); + + mesh->subd_params->camera = dicing_camera; + DiagSplit dsplit(*mesh->subd_params); + mesh->tessellate(&dsplit); + + i++; + + if (progress.get_cancel()) + return; + } + } + } + + /* Update images needed for true displacement. */ + bool old_need_object_flags_update = false; + if (true_displacement_used) { + VLOG(1) << "Updating images used for true displacement."; + device_update_displacement_images(device, scene, progress); + old_need_object_flags_update = scene->object_manager->need_flags_update; + scene->object_manager->device_update_flags(device, dscene, scene, progress, false); + } + + /* Device update. */ + device_free(device, dscene); + + mesh_calc_offset(scene); + if (true_displacement_used) { + device_update_mesh(device, dscene, scene, true, progress); + } + if (progress.get_cancel()) + return; + + device_update_attributes(device, dscene, scene, progress); + if (progress.get_cancel()) + return; + + /* Update displacement. */ + bool displacement_done = false; + size_t num_bvh = 0; + BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, + device->get_bvh_layout_mask()); + + foreach (Geometry *geom, scene->geometry) { + if (geom->need_update) { + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (displace(device, dscene, scene, mesh, progress)) { + displacement_done = true; + } + } + + if (geom->need_build_bvh(bvh_layout)) { + num_bvh++; + } + } + + if (progress.get_cancel()) + return; + } + + /* Device re-update after displacement. */ + if (displacement_done) { + device_free(device, dscene); + + device_update_attributes(device, dscene, scene, progress); + if (progress.get_cancel()) + return; + } + + TaskPool pool; + + size_t i = 0; + foreach (Geometry *geom, scene->geometry) { + if (geom->need_update) { + pool.push(function_bind( + &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh)); + if (geom->need_build_bvh(bvh_layout)) { + i++; + } + } + } + + TaskPool::Summary summary; + pool.wait_work(&summary); + VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report(); + + foreach (Shader *shader, scene->shaders) { + shader->need_update_geometry = false; + } + + Scene::MotionType need_motion = scene->need_motion(); + bool motion_blur = need_motion == Scene::MOTION_BLUR; + + /* Update objects. */ + vector<Object *> volume_objects; + foreach (Object *object, scene->objects) { + object->compute_bounds(motion_blur); + } + + if (progress.get_cancel()) + return; + + device_update_bvh(device, dscene, scene, progress); + if (progress.get_cancel()) + return; + + device_update_mesh(device, dscene, scene, false, progress); + if (progress.get_cancel()) + return; + + need_update = false; + + if (true_displacement_used) { + /* Re-tag flags for update, so they're re-evaluated + * for meshes with correct bounding boxes. + * + * This wouldn't cause wrong results, just true + * displacement might be less optimal ot calculate. + */ + scene->object_manager->need_flags_update = old_need_object_flags_update; + } +} + +void GeometryManager::device_free(Device *device, DeviceScene *dscene) +{ + dscene->bvh_nodes.free(); + dscene->bvh_leaf_nodes.free(); + dscene->object_node.free(); + dscene->prim_tri_verts.free(); + dscene->prim_tri_index.free(); + dscene->prim_type.free(); + dscene->prim_visibility.free(); + dscene->prim_index.free(); + dscene->prim_object.free(); + dscene->prim_time.free(); + dscene->tri_shader.free(); + dscene->tri_vnormal.free(); + dscene->tri_vindex.free(); + dscene->tri_patch.free(); + dscene->tri_patch_uv.free(); + dscene->curves.free(); + dscene->curve_keys.free(); + dscene->patches.free(); + dscene->attributes_map.free(); + dscene->attributes_float.free(); + dscene->attributes_float2.free(); + dscene->attributes_float3.free(); + dscene->attributes_uchar4.free(); + + /* Signal for shaders like displacement not to do ray tracing. */ + dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE; + +#ifdef WITH_OSL + OSLGlobals *og = (OSLGlobals *)device->osl_memory(); + + if (og) { + og->object_name_map.clear(); + og->attribute_map.clear(); + og->object_names.clear(); + } +#else + (void)device; +#endif +} + +void GeometryManager::tag_update(Scene *scene) +{ + need_update = true; + scene->object_manager->need_update = true; +} + +void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats) +{ + foreach (Geometry *geometry, scene->geometry) { + stats->mesh.geometry.add_entry( + NamedSizeEntry(string(geometry->name.c_str()), geometry->get_total_size_in_bytes())); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h new file mode 100644 index 00000000000..711da1c81e8 --- /dev/null +++ b/intern/cycles/render/geometry.h @@ -0,0 +1,202 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GEOMETRY_H__ +#define __GEOMETRY_H__ + +#include "graph/node.h" + +#include "bvh/bvh_params.h" + +#include "render/attribute.h" + +#include "util/util_boundbox.h" +#include "util/util_transform.h" +#include "util/util_set.h" +#include "util/util_types.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +class BVH; +class Device; +class DeviceScene; +class Mesh; +class Progress; +class RenderStats; +class Scene; +class SceneParams; +class Shader; + +/* Geometry + * + * Base class for geometric types like Mesh and Hair. */ + +class Geometry : public Node { + public: + NODE_ABSTRACT_DECLARE + + enum Type { + MESH, + HAIR, + }; + + Type type; + + /* Attributes */ + AttributeSet attributes; + + /* Shaders */ + vector<Shader *> used_shaders; + + /* Transform */ + BoundBox bounds; + bool transform_applied; + bool transform_negative_scaled; + Transform transform_normal; + + /* Motion Blur */ + uint motion_steps; + bool use_motion_blur; + + /* BVH */ + BVH *bvh; + size_t attr_map_offset; + size_t prim_offset; + size_t optix_prim_offset; + + /* Shader Properties */ + bool has_volume; /* Set in the device_update_flags(). */ + bool has_surface_bssrdf; /* Set in the device_update_flags(). */ + + /* Update Flags */ + bool need_update; + bool need_update_rebuild; + + /* Constructor/Destructor */ + explicit Geometry(const NodeType *node_type, const Type type); + virtual ~Geometry(); + + /* Geometry */ + virtual void clear(); + virtual void compute_bounds() = 0; + virtual void apply_transform(const Transform &tfm, const bool apply_to_motion) = 0; + + /* Attribute Requests */ + bool need_attribute(Scene *scene, AttributeStandard std); + bool need_attribute(Scene *scene, ustring name); + + /* UDIM */ + virtual void get_uv_tiles(ustring map, unordered_set<int> &tiles) = 0; + + /* Convert between normalized -1..1 motion time and index in the + * VERTEX_MOTION attribute. */ + float motion_time(int step) const; + int motion_step(float time) const; + + /* BVH */ + void compute_bvh(Device *device, + DeviceScene *dscene, + SceneParams *params, + Progress *progress, + int n, + int total); + + /* Check whether the geometry should have own BVH built separately. Briefly, + * own BVH is needed for geometry, if: + * + * - It is instanced multiple times, so each instance object should share the + * same BVH tree. + * - Special ray intersection is needed, for example to limit subsurface rays + * to only the geometry itself. + * - The BVH layout requires the top level to only contain instances. + */ + bool need_build_bvh(BVHLayout layout) const; + + /* Test if the geometry should be treated as instanced. */ + bool is_instanced() const; + + bool has_true_displacement() const; + bool has_motion_blur() const; + bool has_voxel_attributes() const; + + /* Updates */ + void tag_update(Scene *scene, bool rebuild); +}; + +/* Geometry Manager */ + +class GeometryManager { + public: + /* Update Flags */ + bool need_update; + bool need_flags_update; + + /* Constructor/Destructor */ + GeometryManager(); + ~GeometryManager(); + + /* Device Updates */ + void device_update_preprocess(Device *device, Scene *scene, Progress &progress); + void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); + void device_free(Device *device, DeviceScene *dscene); + + /* Updates */ + void tag_update(Scene *scene); + + /* Statistics */ + void collect_statistics(const Scene *scene, RenderStats *stats); + + protected: + bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress); + + void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress); + + /* Attributes */ + void update_osl_attributes(Device *device, + Scene *scene, + vector<AttributeRequestSet> &geom_attributes); + void update_svm_attributes(Device *device, + DeviceScene *dscene, + Scene *scene, + vector<AttributeRequestSet> &geom_attributes); + + /* Compute verts/triangles/curves offsets in global arrays. */ + void mesh_calc_offset(Scene *scene); + + void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); + + void device_update_mesh(Device *device, + DeviceScene *dscene, + Scene *scene, + bool for_displacement, + Progress &progress); + + void device_update_attributes(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress); + + void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); + + void device_update_displacement_images(Device *device, Scene *scene, Progress &progress); + + void device_update_volume_images(Device *device, Scene *scene, Progress &progress); +}; + +CCL_NAMESPACE_END + +#endif /* __GEOMETRY_H__ */ diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp new file mode 100644 index 00000000000..7220fe7093b --- /dev/null +++ b/intern/cycles/render/hair.cpp @@ -0,0 +1,487 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/curves.h" +#include "render/hair.h" +#include "render/scene.h" + +CCL_NAMESPACE_BEGIN + +/* Hair Curve */ + +void Hair::Curve::bounds_grow(const int k, + const float3 *curve_keys, + const float *curve_radius, + BoundBox &bounds) const +{ + float3 P[4]; + + P[0] = curve_keys[max(first_key + k - 1, first_key)]; + P[1] = curve_keys[first_key + k]; + P[2] = curve_keys[first_key + k + 1]; + P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]; + + float3 lower; + float3 upper; + + curvebounds(&lower.x, &upper.x, P, 0); + curvebounds(&lower.y, &upper.y, P, 1); + curvebounds(&lower.z, &upper.z, P, 2); + + float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]); + + bounds.grow(lower, mr); + bounds.grow(upper, mr); +} + +void Hair::Curve::bounds_grow(const int k, + const float3 *curve_keys, + const float *curve_radius, + const Transform &aligned_space, + BoundBox &bounds) const +{ + float3 P[4]; + + P[0] = curve_keys[max(first_key + k - 1, first_key)]; + P[1] = curve_keys[first_key + k]; + P[2] = curve_keys[first_key + k + 1]; + P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]; + + P[0] = transform_point(&aligned_space, P[0]); + P[1] = transform_point(&aligned_space, P[1]); + P[2] = transform_point(&aligned_space, P[2]); + P[3] = transform_point(&aligned_space, P[3]); + + float3 lower; + float3 upper; + + curvebounds(&lower.x, &upper.x, P, 0); + curvebounds(&lower.y, &upper.y, P, 1); + curvebounds(&lower.z, &upper.z, P, 2); + + float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]); + + bounds.grow(lower, mr); + bounds.grow(upper, mr); +} + +void Hair::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const +{ + float3 P[4] = { + float4_to_float3(keys[0]), + float4_to_float3(keys[1]), + float4_to_float3(keys[2]), + float4_to_float3(keys[3]), + }; + + float3 lower; + float3 upper; + + curvebounds(&lower.x, &upper.x, P, 0); + curvebounds(&lower.y, &upper.y, P, 1); + curvebounds(&lower.z, &upper.z, P, 2); + + float mr = max(keys[1].w, keys[2].w); + + bounds.grow(lower, mr); + bounds.grow(upper, mr); +} + +void Hair::Curve::motion_keys(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + float time, + size_t k0, + size_t k1, + float4 r_keys[2]) const +{ + /* Figure out which steps we need to fetch and their interpolation factor. */ + const size_t max_step = num_steps - 1; + const size_t step = min((int)(time * max_step), max_step - 1); + const float t = time * max_step - step; + /* Fetch vertex coordinates. */ + float4 curr_keys[2]; + float4 next_keys[2]; + keys_for_step( + curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys); + keys_for_step( + curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys); + /* Interpolate between steps. */ + r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0]; + r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1]; +} + +void Hair::Curve::cardinal_motion_keys(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + float time, + size_t k0, + size_t k1, + size_t k2, + size_t k3, + float4 r_keys[4]) const +{ + /* Figure out which steps we need to fetch and their interpolation factor. */ + const size_t max_step = num_steps - 1; + const size_t step = min((int)(time * max_step), max_step - 1); + const float t = time * max_step - step; + /* Fetch vertex coordinates. */ + float4 curr_keys[4]; + float4 next_keys[4]; + cardinal_keys_for_step(curve_keys, + curve_radius, + key_steps, + num_curve_keys, + num_steps, + step, + k0, + k1, + k2, + k3, + curr_keys); + cardinal_keys_for_step(curve_keys, + curve_radius, + key_steps, + num_curve_keys, + num_steps, + step + 1, + k0, + k1, + k2, + k3, + next_keys); + /* Interpolate between steps. */ + r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0]; + r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1]; + r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2]; + r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3]; +} + +void Hair::Curve::keys_for_step(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + size_t step, + size_t k0, + size_t k1, + float4 r_keys[2]) const +{ + k0 = max(k0, 0); + k1 = min(k1, num_keys - 1); + const size_t center_step = ((num_steps - 1) / 2); + if (step == center_step) { + /* Center step: regular key location. */ + /* TODO(sergey): Consider adding make_float4(float3, float) + * function. + */ + r_keys[0] = make_float4(curve_keys[first_key + k0].x, + curve_keys[first_key + k0].y, + curve_keys[first_key + k0].z, + curve_radius[first_key + k0]); + r_keys[1] = make_float4(curve_keys[first_key + k1].x, + curve_keys[first_key + k1].y, + curve_keys[first_key + k1].z, + curve_radius[first_key + k1]); + } + else { + /* Center step is not stored in this array. */ + if (step > center_step) { + step--; + } + const size_t offset = first_key + step * num_curve_keys; + r_keys[0] = make_float4(key_steps[offset + k0].x, + key_steps[offset + k0].y, + key_steps[offset + k0].z, + curve_radius[first_key + k0]); + r_keys[1] = make_float4(key_steps[offset + k1].x, + key_steps[offset + k1].y, + key_steps[offset + k1].z, + curve_radius[first_key + k1]); + } +} + +void Hair::Curve::cardinal_keys_for_step(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + size_t step, + size_t k0, + size_t k1, + size_t k2, + size_t k3, + float4 r_keys[4]) const +{ + k0 = max(k0, 0); + k3 = min(k3, num_keys - 1); + const size_t center_step = ((num_steps - 1) / 2); + if (step == center_step) { + /* Center step: regular key location. */ + r_keys[0] = make_float4(curve_keys[first_key + k0].x, + curve_keys[first_key + k0].y, + curve_keys[first_key + k0].z, + curve_radius[first_key + k0]); + r_keys[1] = make_float4(curve_keys[first_key + k1].x, + curve_keys[first_key + k1].y, + curve_keys[first_key + k1].z, + curve_radius[first_key + k1]); + r_keys[2] = make_float4(curve_keys[first_key + k2].x, + curve_keys[first_key + k2].y, + curve_keys[first_key + k2].z, + curve_radius[first_key + k2]); + r_keys[3] = make_float4(curve_keys[first_key + k3].x, + curve_keys[first_key + k3].y, + curve_keys[first_key + k3].z, + curve_radius[first_key + k3]); + } + else { + /* Center step is not stored in this array. */ + if (step > center_step) { + step--; + } + const size_t offset = first_key + step * num_curve_keys; + r_keys[0] = make_float4(key_steps[offset + k0].x, + key_steps[offset + k0].y, + key_steps[offset + k0].z, + curve_radius[first_key + k0]); + r_keys[1] = make_float4(key_steps[offset + k1].x, + key_steps[offset + k1].y, + key_steps[offset + k1].z, + curve_radius[first_key + k1]); + r_keys[2] = make_float4(key_steps[offset + k2].x, + key_steps[offset + k2].y, + key_steps[offset + k2].z, + curve_radius[first_key + k2]); + r_keys[3] = make_float4(key_steps[offset + k3].x, + key_steps[offset + k3].y, + key_steps[offset + k3].z, + curve_radius[first_key + k3]); + } +} + +/* Hair */ + +NODE_DEFINE(Hair) +{ + NodeType *type = NodeType::add("hair", create, NodeType::NONE, Geometry::node_base_type); + + SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>()); + SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>()); + SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>()); + SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>()); + + return type; +} + +Hair::Hair() : Geometry(node_type, Geometry::HAIR) +{ + curvekey_offset = 0; +} + +Hair::~Hair() +{ +} + +void Hair::resize_curves(int numcurves, int numkeys) +{ + curve_keys.resize(numkeys); + curve_radius.resize(numkeys); + curve_first_key.resize(numcurves); + curve_shader.resize(numcurves); + + attributes.resize(); +} + +void Hair::reserve_curves(int numcurves, int numkeys) +{ + curve_keys.reserve(numkeys); + curve_radius.reserve(numkeys); + curve_first_key.reserve(numcurves); + curve_shader.reserve(numcurves); + + attributes.resize(true); +} + +void Hair::clear() +{ + Geometry::clear(); + + curve_keys.clear(); + curve_radius.clear(); + curve_first_key.clear(); + curve_shader.clear(); + + attributes.clear(); +} + +void Hair::add_curve_key(float3 co, float radius) +{ + curve_keys.push_back_reserved(co); + curve_radius.push_back_reserved(radius); +} + +void Hair::add_curve(int first_key, int shader) +{ + curve_first_key.push_back_reserved(first_key); + curve_shader.push_back_reserved(shader); +} + +void Hair::copy_center_to_motion_step(const int motion_step) +{ + Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr_mP) { + float3 *keys = &curve_keys[0]; + size_t numkeys = curve_keys.size(); + memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys); + } +} + +void Hair::get_uv_tiles(ustring map, unordered_set<int> &tiles) +{ + Attribute *attr; + + if (map.empty()) { + attr = attributes.find(ATTR_STD_UV); + } + else { + attr = attributes.find(map); + } + + if (attr) { + attr->get_uv_tiles(this, ATTR_PRIM_GEOMETRY, tiles); + } +} + +void Hair::compute_bounds() +{ + BoundBox bnds = BoundBox::empty; + size_t curve_keys_size = curve_keys.size(); + + if (curve_keys_size > 0) { + for (size_t i = 0; i < curve_keys_size; i++) + bnds.grow(curve_keys[i], curve_radius[i]); + + Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (use_motion_blur && curve_attr) { + size_t steps_size = curve_keys.size() * (motion_steps - 1); + float3 *key_steps = curve_attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow(key_steps[i]); + } + + if (!bnds.valid()) { + bnds = BoundBox::empty; + + /* skip nan or inf coordinates */ + for (size_t i = 0; i < curve_keys_size; i++) + bnds.grow_safe(curve_keys[i], curve_radius[i]); + + if (use_motion_blur && curve_attr) { + size_t steps_size = curve_keys.size() * (motion_steps - 1); + float3 *key_steps = curve_attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow_safe(key_steps[i]); + } + } + } + + if (!bnds.valid()) { + /* empty mesh */ + bnds.grow(make_float3(0.0f, 0.0f, 0.0f)); + } + + bounds = bnds; +} + +void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion) +{ + /* compute uniform scale */ + float3 c0 = transform_get_column(&tfm, 0); + float3 c1 = transform_get_column(&tfm, 1); + float3 c2 = transform_get_column(&tfm, 2); + float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f); + + /* apply transform to curve keys */ + for (size_t i = 0; i < curve_keys.size(); i++) { + float3 co = transform_point(&tfm, curve_keys[i]); + float radius = curve_radius[i] * scalar; + + /* scale for curve radius is only correct for uniform scale */ + curve_keys[i] = co; + curve_radius[i] = radius; + } + + if (apply_to_motion) { + Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (curve_attr) { + /* apply transform to motion curve keys */ + size_t steps_size = curve_keys.size() * (motion_steps - 1); + float4 *key_steps = curve_attr->data_float4(); + + for (size_t i = 0; i < steps_size; i++) { + float3 co = transform_point(&tfm, float4_to_float3(key_steps[i])); + float radius = key_steps[i].w * scalar; + + /* scale for curve radius is only correct for uniform scale */ + key_steps[i] = float3_to_float4(co); + key_steps[i].w = radius; + } + } + } +} + +void Hair::pack_curves(Scene *scene, + float4 *curve_key_co, + float4 *curve_data, + size_t curvekey_offset) +{ + size_t curve_keys_size = curve_keys.size(); + + /* pack curve keys */ + if (curve_keys_size) { + float3 *keys_ptr = curve_keys.data(); + float *radius_ptr = curve_radius.data(); + + for (size_t i = 0; i < curve_keys_size; i++) + curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]); + } + + /* pack curve segments */ + size_t curve_num = num_curves(); + + for (size_t i = 0; i < curve_num; i++) { + Curve curve = get_curve(i); + int shader_id = curve_shader[i]; + Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] : + scene->default_surface; + shader_id = scene->shader_manager->get_shader_id(shader, false); + + curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset), + __int_as_float(curve.num_keys), + __int_as_float(shader_id), + 0.0f); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h new file mode 100644 index 00000000000..79f77a78753 --- /dev/null +++ b/intern/cycles/render/hair.h @@ -0,0 +1,151 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HAIR_H__ +#define __HAIR_H__ + +#include "render/geometry.h" + +CCL_NAMESPACE_BEGIN + +class Hair : public Geometry { + public: + NODE_DECLARE + + /* Hair Curve */ + struct Curve { + int first_key; + int num_keys; + + int num_segments() const + { + return num_keys - 1; + } + + void bounds_grow(const int k, + const float3 *curve_keys, + const float *curve_radius, + BoundBox &bounds) const; + void bounds_grow(float4 keys[4], BoundBox &bounds) const; + void bounds_grow(const int k, + const float3 *curve_keys, + const float *curve_radius, + const Transform &aligned_space, + BoundBox &bounds) const; + + void motion_keys(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + float time, + size_t k0, + size_t k1, + float4 r_keys[2]) const; + void cardinal_motion_keys(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + float time, + size_t k0, + size_t k1, + size_t k2, + size_t k3, + float4 r_keys[4]) const; + + void keys_for_step(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + size_t step, + size_t k0, + size_t k1, + float4 r_keys[2]) const; + void cardinal_keys_for_step(const float3 *curve_keys, + const float *curve_radius, + const float3 *key_steps, + size_t num_curve_keys, + size_t num_steps, + size_t step, + size_t k0, + size_t k1, + size_t k2, + size_t k3, + float4 r_keys[4]) const; + }; + + array<float3> curve_keys; + array<float> curve_radius; + array<int> curve_first_key; + array<int> curve_shader; + + /* BVH */ + size_t curvekey_offset; + + /* Constructor/Destructor */ + Hair(); + ~Hair(); + + /* Geometry */ + void clear() override; + + void resize_curves(int numcurves, int numkeys); + void reserve_curves(int numcurves, int numkeys); + void add_curve_key(float3 loc, float radius); + void add_curve(int first_key, int shader); + + void copy_center_to_motion_step(const int motion_step); + + void compute_bounds() override; + void apply_transform(const Transform &tfm, const bool apply_to_motion) override; + + /* Curves */ + Curve get_curve(size_t i) const + { + int first = curve_first_key[i]; + int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size(); + + Curve curve = {first, next_first - first}; + return curve; + } + + size_t num_keys() const + { + return curve_keys.size(); + } + + size_t num_curves() const + { + return curve_first_key.size(); + } + + size_t num_segments() const + { + return curve_keys.size() - curve_first_key.size(); + } + + /* UDIM */ + void get_uv_tiles(ustring map, unordered_set<int> &tiles) override; + + /* BVH */ + void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); +}; + +CCL_NAMESPACE_END + +#endif /* __HAIR_H__ */ diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 664217d6f26..509637aedd9 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -232,7 +232,10 @@ void LightManager::disable_ineffective_light(Scene *scene) bool LightManager::object_usable_as_light(Object *object) { - Mesh *mesh = object->mesh; + Geometry *geom = object->geometry; + if (geom->type != Geometry::MESH) { + return false; + } /* Skip objects with NaNs */ if (!object->bounds.valid()) { return false; @@ -243,10 +246,10 @@ bool LightManager::object_usable_as_light(Object *object) } /* Skip if we have no emission shaders. */ /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll - * iterate all mesh shaders twice (when counting and when calculating + * iterate all geometry shaders twice (when counting and when calculating * triangle area. */ - foreach (const Shader *shader, mesh->used_shaders) { + foreach (const Shader *shader, geom->used_shaders) { if (shader->use_mis && shader->has_surface_emission) { return true; } @@ -285,8 +288,9 @@ void LightManager::device_update_distribution(Device *, if (!object_usable_as_light(object)) { continue; } + /* Count triangles. */ - Mesh *mesh = object->mesh; + Mesh *mesh = static_cast<Mesh *>(object->geometry); size_t mesh_num_triangles = mesh->num_triangles(); for (size_t i = 0; i < mesh_num_triangles; i++) { int shader_index = mesh->shader[i]; @@ -320,7 +324,7 @@ void LightManager::device_update_distribution(Device *, continue; } /* Sum area. */ - Mesh *mesh = object->mesh; + Mesh *mesh = static_cast<Mesh *>(object->geometry); bool transform_applied = mesh->transform_applied; Transform tfm = object->tfm; int object_id = j; @@ -352,7 +356,7 @@ void LightManager::device_update_distribution(Device *, if (shader->use_mis && shader->has_surface_emission) { distribution[offset].totarea = totarea; - distribution[offset].prim = i + mesh->tri_offset; + distribution[offset].prim = i + mesh->prim_offset; distribution[offset].mesh_light.shader_flag = shader_flag; distribution[offset].mesh_light.object_id = object_id; offset++; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index d9e6d998ebd..e80e87f2980 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -17,19 +17,13 @@ #include "bvh/bvh.h" #include "bvh/bvh_build.h" -#include "render/camera.h" -#include "render/curves.h" #include "device/device.h" + #include "render/graph.h" -#include "render/shader.h" -#include "render/light.h" +#include "render/hair.h" #include "render/mesh.h" -#include "render/nodes.h" #include "render/object.h" #include "render/scene.h" -#include "render/stats.h" - -#include "kernel/osl/osl_globals.h" #include "subd/subd_split.h" #include "subd/subd_patch_table.h" @@ -39,10 +33,6 @@ #include "util/util_progress.h" #include "util/util_set.h" -#ifdef WITH_EMBREE -# include "bvh/bvh_embree.h" -#endif - CCL_NAMESPACE_BEGIN /* Triangle */ @@ -120,263 +110,6 @@ bool Mesh::Triangle::valid(const float3 *verts) const return isfinite3_safe(verts[v[0]]) && isfinite3_safe(verts[v[1]]) && isfinite3_safe(verts[v[2]]); } -/* Curve */ - -void Mesh::Curve::bounds_grow(const int k, - const float3 *curve_keys, - const float *curve_radius, - BoundBox &bounds) const -{ - float3 P[4]; - - P[0] = curve_keys[max(first_key + k - 1, first_key)]; - P[1] = curve_keys[first_key + k]; - P[2] = curve_keys[first_key + k + 1]; - P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]; - - float3 lower; - float3 upper; - - curvebounds(&lower.x, &upper.x, P, 0); - curvebounds(&lower.y, &upper.y, P, 1); - curvebounds(&lower.z, &upper.z, P, 2); - - float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]); - - bounds.grow(lower, mr); - bounds.grow(upper, mr); -} - -void Mesh::Curve::bounds_grow(const int k, - const float3 *curve_keys, - const float *curve_radius, - const Transform &aligned_space, - BoundBox &bounds) const -{ - float3 P[4]; - - P[0] = curve_keys[max(first_key + k - 1, first_key)]; - P[1] = curve_keys[first_key + k]; - P[2] = curve_keys[first_key + k + 1]; - P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]; - - P[0] = transform_point(&aligned_space, P[0]); - P[1] = transform_point(&aligned_space, P[1]); - P[2] = transform_point(&aligned_space, P[2]); - P[3] = transform_point(&aligned_space, P[3]); - - float3 lower; - float3 upper; - - curvebounds(&lower.x, &upper.x, P, 0); - curvebounds(&lower.y, &upper.y, P, 1); - curvebounds(&lower.z, &upper.z, P, 2); - - float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]); - - bounds.grow(lower, mr); - bounds.grow(upper, mr); -} - -void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const -{ - float3 P[4] = { - float4_to_float3(keys[0]), - float4_to_float3(keys[1]), - float4_to_float3(keys[2]), - float4_to_float3(keys[3]), - }; - - float3 lower; - float3 upper; - - curvebounds(&lower.x, &upper.x, P, 0); - curvebounds(&lower.y, &upper.y, P, 1); - curvebounds(&lower.z, &upper.z, P, 2); - - float mr = max(keys[1].w, keys[2].w); - - bounds.grow(lower, mr); - bounds.grow(upper, mr); -} - -void Mesh::Curve::motion_keys(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - float time, - size_t k0, - size_t k1, - float4 r_keys[2]) const -{ - /* Figure out which steps we need to fetch and their interpolation factor. */ - const size_t max_step = num_steps - 1; - const size_t step = min((int)(time * max_step), max_step - 1); - const float t = time * max_step - step; - /* Fetch vertex coordinates. */ - float4 curr_keys[2]; - float4 next_keys[2]; - keys_for_step( - curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys); - keys_for_step( - curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys); - /* Interpolate between steps. */ - r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0]; - r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1]; -} - -void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - float time, - size_t k0, - size_t k1, - size_t k2, - size_t k3, - float4 r_keys[4]) const -{ - /* Figure out which steps we need to fetch and their interpolation factor. */ - const size_t max_step = num_steps - 1; - const size_t step = min((int)(time * max_step), max_step - 1); - const float t = time * max_step - step; - /* Fetch vertex coordinates. */ - float4 curr_keys[4]; - float4 next_keys[4]; - cardinal_keys_for_step(curve_keys, - curve_radius, - key_steps, - num_curve_keys, - num_steps, - step, - k0, - k1, - k2, - k3, - curr_keys); - cardinal_keys_for_step(curve_keys, - curve_radius, - key_steps, - num_curve_keys, - num_steps, - step + 1, - k0, - k1, - k2, - k3, - next_keys); - /* Interpolate between steps. */ - r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0]; - r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1]; - r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2]; - r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3]; -} - -void Mesh::Curve::keys_for_step(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - size_t step, - size_t k0, - size_t k1, - float4 r_keys[2]) const -{ - k0 = max(k0, 0); - k1 = min(k1, num_keys - 1); - const size_t center_step = ((num_steps - 1) / 2); - if (step == center_step) { - /* Center step: regular key location. */ - /* TODO(sergey): Consider adding make_float4(float3, float) - * function. - */ - r_keys[0] = make_float4(curve_keys[first_key + k0].x, - curve_keys[first_key + k0].y, - curve_keys[first_key + k0].z, - curve_radius[first_key + k0]); - r_keys[1] = make_float4(curve_keys[first_key + k1].x, - curve_keys[first_key + k1].y, - curve_keys[first_key + k1].z, - curve_radius[first_key + k1]); - } - else { - /* Center step is not stored in this array. */ - if (step > center_step) { - step--; - } - const size_t offset = first_key + step * num_curve_keys; - r_keys[0] = make_float4(key_steps[offset + k0].x, - key_steps[offset + k0].y, - key_steps[offset + k0].z, - curve_radius[first_key + k0]); - r_keys[1] = make_float4(key_steps[offset + k1].x, - key_steps[offset + k1].y, - key_steps[offset + k1].z, - curve_radius[first_key + k1]); - } -} - -void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - size_t step, - size_t k0, - size_t k1, - size_t k2, - size_t k3, - float4 r_keys[4]) const -{ - k0 = max(k0, 0); - k3 = min(k3, num_keys - 1); - const size_t center_step = ((num_steps - 1) / 2); - if (step == center_step) { - /* Center step: regular key location. */ - r_keys[0] = make_float4(curve_keys[first_key + k0].x, - curve_keys[first_key + k0].y, - curve_keys[first_key + k0].z, - curve_radius[first_key + k0]); - r_keys[1] = make_float4(curve_keys[first_key + k1].x, - curve_keys[first_key + k1].y, - curve_keys[first_key + k1].z, - curve_radius[first_key + k1]); - r_keys[2] = make_float4(curve_keys[first_key + k2].x, - curve_keys[first_key + k2].y, - curve_keys[first_key + k2].z, - curve_radius[first_key + k2]); - r_keys[3] = make_float4(curve_keys[first_key + k3].x, - curve_keys[first_key + k3].y, - curve_keys[first_key + k3].z, - curve_radius[first_key + k3]); - } - else { - /* Center step is not stored in this array. */ - if (step > center_step) { - step--; - } - const size_t offset = first_key + step * num_curve_keys; - r_keys[0] = make_float4(key_steps[offset + k0].x, - key_steps[offset + k0].y, - key_steps[offset + k0].z, - curve_radius[first_key + k0]); - r_keys[1] = make_float4(key_steps[offset + k1].x, - key_steps[offset + k1].y, - key_steps[offset + k1].z, - curve_radius[first_key + k1]); - r_keys[2] = make_float4(key_steps[offset + k2].x, - key_steps[offset + k2].y, - key_steps[offset + k2].z, - curve_radius[first_key + k2]); - r_keys[3] = make_float4(key_steps[offset + k3].x, - key_steps[offset + k3].y, - key_steps[offset + k3].z, - curve_radius[first_key + k3]); - } -} - /* SubdFace */ float3 Mesh::SubdFace::normal(const Mesh *mesh) const @@ -392,60 +125,27 @@ float3 Mesh::SubdFace::normal(const Mesh *mesh) const NODE_DEFINE(Mesh) { - NodeType *type = NodeType::add("mesh", create); - - SOCKET_UINT(motion_steps, "Motion Steps", 3); - SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false); + NodeType *type = NodeType::add("mesh", create, NodeType::NONE, Geometry::node_base_type); SOCKET_INT_ARRAY(triangles, "Triangles", array<int>()); SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>()); SOCKET_INT_ARRAY(shader, "Shader", array<int>()); SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>()); - SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>()); - SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>()); - SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>()); - SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>()); - return type; } -Mesh::Mesh() : Node(node_type) +Mesh::Mesh() : Geometry(node_type, Geometry::MESH), subd_attributes(this, ATTR_PRIM_SUBD) { - need_update = true; - need_update_rebuild = false; - transform_applied = false; - transform_negative_scaled = false; - transform_normal = transform_identity(); - bounds = BoundBox::empty; - - bvh = NULL; - - tri_offset = 0; vert_offset = 0; - curve_offset = 0; - curvekey_offset = 0; - patch_offset = 0; face_offset = 0; corner_offset = 0; - attr_map_offset = 0; - - prim_offset = 0; - num_subd_verts = 0; - attributes.triangle_mesh = this; - curve_attributes.curve_mesh = this; - subd_attributes.subd_mesh = this; - - geometry_flags = GEOMETRY_NONE; - volume_isovalue = 0.001f; - has_volume = false; - has_surface_bssrdf = false; num_ngons = 0; @@ -457,7 +157,6 @@ Mesh::Mesh() : Node(node_type) Mesh::~Mesh() { - delete bvh; delete patch_table; delete subd_params; } @@ -493,26 +192,6 @@ void Mesh::reserve_mesh(int numverts, int numtris) attributes.resize(true); } -void Mesh::resize_curves(int numcurves, int numkeys) -{ - curve_keys.resize(numkeys); - curve_radius.resize(numkeys); - curve_first_key.resize(numcurves); - curve_shader.resize(numcurves); - - curve_attributes.resize(); -} - -void Mesh::reserve_curves(int numcurves, int numkeys) -{ - curve_keys.reserve(numkeys); - curve_radius.reserve(numkeys); - curve_first_key.reserve(numcurves); - curve_shader.reserve(numcurves); - - curve_attributes.resize(true); -} - void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners) { subd_faces.resize(numfaces); @@ -533,6 +212,8 @@ void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners) void Mesh::clear(bool preserve_voxel_data) { + Geometry::clear(); + /* clear all verts and triangles */ verts.clear(); triangles.clear(); @@ -542,11 +223,6 @@ void Mesh::clear(bool preserve_voxel_data) triangle_patch.clear(); vert_patch_uv.clear(); - curve_keys.clear(); - curve_radius.clear(); - curve_first_key.clear(); - curve_shader.clear(); - subd_faces.clear(); subd_face_corners.clear(); @@ -554,27 +230,21 @@ void Mesh::clear(bool preserve_voxel_data) subd_creases.clear(); - curve_attributes.clear(); subd_attributes.clear(); attributes.clear(preserve_voxel_data); - used_shaders.clear(); - vert_to_stitching_key_map.clear(); vert_stitching_map.clear(); - if (!preserve_voxel_data) { - geometry_flags = GEOMETRY_NONE; - } - - transform_applied = false; - transform_negative_scaled = false; - transform_normal = transform_identity(); - delete patch_table; patch_table = NULL; } +void Mesh::clear() +{ + clear(false); +} + void Mesh::add_vertex(float3 P) { verts.push_back_reserved(P); @@ -606,18 +276,6 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) } } -void Mesh::add_curve_key(float3 co, float radius) -{ - curve_keys.push_back_reserved(co); - curve_radius.push_back_reserved(radius); -} - -void Mesh::add_curve(int first_key, int shader) -{ - curve_first_key.push_back_reserved(first_key); - curve_shader.push_back_reserved(shader); -} - void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth_) { int start_corner = subd_face_corners.size(); @@ -637,47 +295,41 @@ void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth subd_faces.push_back_reserved(face); } -static void get_uv_tiles_from_attribute(Attribute *attr, int num, unordered_set<int> &tiles) +void Mesh::copy_center_to_motion_step(const int motion_step) { - if (attr == NULL) { - return; - } - - const float2 *uv = attr->data_float2(); - for (int i = 0; i < num; i++, uv++) { - float u = uv->x, v = uv->y; - int x = (int)u, y = (int)v; - - if (x < 0 || y < 0 || x >= 10) { - continue; - } + Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - /* Be conservative in corners - precisely touching the right or upper edge of a tile - * should not load its right/upper neighbor as well. */ - if (x > 0 && (u < x + 1e-6f)) { - x--; - } - if (y > 0 && (v < y + 1e-6f)) { - y--; - } + if (attr_mP) { + Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + Attribute *attr_N = attributes.find(ATTR_STD_VERTEX_NORMAL); + float3 *P = &verts[0]; + float3 *N = (attr_N) ? attr_N->data_float3() : NULL; + size_t numverts = verts.size(); - tiles.insert(1001 + 10 * y + x); + memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts); + if (attr_mN) + memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts); } } void Mesh::get_uv_tiles(ustring map, unordered_set<int> &tiles) { + Attribute *attr, *subd_attr; + if (map.empty()) { - get_uv_tiles_from_attribute(attributes.find(ATTR_STD_UV), num_triangles() * 3, tiles); - get_uv_tiles_from_attribute( - subd_attributes.find(ATTR_STD_UV), subd_face_corners.size() + num_ngons, tiles); - get_uv_tiles_from_attribute(curve_attributes.find(ATTR_STD_UV), num_curves(), tiles); + attr = attributes.find(ATTR_STD_UV); + subd_attr = subd_attributes.find(ATTR_STD_UV); } else { - get_uv_tiles_from_attribute(attributes.find(map), num_triangles() * 3, tiles); - get_uv_tiles_from_attribute( - subd_attributes.find(map), subd_face_corners.size() + num_ngons, tiles); - get_uv_tiles_from_attribute(curve_attributes.find(map), num_curves(), tiles); + attr = attributes.find(map); + subd_attr = subd_attributes.find(map); + } + + if (attr) { + attr->get_uv_tiles(this, ATTR_PRIM_GEOMETRY, tiles); + } + if (subd_attr) { + subd_attr->get_uv_tiles(this, ATTR_PRIM_SUBD, tiles); } } @@ -685,15 +337,11 @@ void Mesh::compute_bounds() { BoundBox bnds = BoundBox::empty; size_t verts_size = verts.size(); - size_t curve_keys_size = curve_keys.size(); - if (verts_size + curve_keys_size > 0) { + if (verts_size > 0) { for (size_t i = 0; i < verts_size; i++) bnds.grow(verts[i]); - for (size_t i = 0; i < curve_keys_size; i++) - bnds.grow(curve_keys[i], curve_radius[i]); - Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); @@ -703,15 +351,6 @@ void Mesh::compute_bounds() bnds.grow(vert_steps[i]); } - Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (use_motion_blur && curve_attr) { - size_t steps_size = curve_keys.size() * (motion_steps - 1); - float3 *key_steps = curve_attr->data_float3(); - - for (size_t i = 0; i < steps_size; i++) - bnds.grow(key_steps[i]); - } - if (!bnds.valid()) { bnds = BoundBox::empty; @@ -719,9 +358,6 @@ void Mesh::compute_bounds() for (size_t i = 0; i < verts_size; i++) bnds.grow_safe(verts[i]); - for (size_t i = 0; i < curve_keys_size; i++) - bnds.grow_safe(curve_keys[i], curve_radius[i]); - if (use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); float3 *vert_steps = attr->data_float3(); @@ -729,14 +365,6 @@ void Mesh::compute_bounds() for (size_t i = 0; i < steps_size; i++) bnds.grow_safe(vert_steps[i]); } - - if (use_motion_blur && curve_attr) { - size_t steps_size = curve_keys.size() * (motion_steps - 1); - float3 *key_steps = curve_attr->data_float3(); - - for (size_t i = 0; i < steps_size; i++) - bnds.grow_safe(key_steps[i]); - } } } @@ -748,6 +376,38 @@ void Mesh::compute_bounds() bounds = bnds; } +void Mesh::apply_transform(const Transform &tfm, const bool apply_to_motion) +{ + transform_normal = transform_transposed_inverse(tfm); + + /* apply to mesh vertices */ + for (size_t i = 0; i < verts.size(); i++) + verts[i] = transform_point(&tfm, verts[i]); + + if (apply_to_motion) { + Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr) { + size_t steps_size = verts.size() * (motion_steps - 1); + float3 *vert_steps = attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + vert_steps[i] = transform_point(&tfm, vert_steps[i]); + } + + Attribute *attr_N = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + + if (attr_N) { + Transform ntfm = transform_normal; + size_t steps_size = verts.size() * (motion_steps - 1); + float3 *normal_steps = attr_N->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i])); + } + } +} + void Mesh::add_face_normals() { /* don't compute if already there */ @@ -885,8 +545,7 @@ void Mesh::add_undisplaced() float3 *data = attr->data_float3(); /* copy verts */ - size_t size = attr->buffer_size( - this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD); + size_t size = attr->buffer_size(this, attrs.prim); /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will * be calculated later, we subtract them from size here so we don't have an overflow while @@ -975,39 +634,6 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index, } } -void Mesh::pack_curves(Scene *scene, - float4 *curve_key_co, - float4 *curve_data, - size_t curvekey_offset) -{ - size_t curve_keys_size = curve_keys.size(); - - /* pack curve keys */ - if (curve_keys_size) { - float3 *keys_ptr = curve_keys.data(); - float *radius_ptr = curve_radius.data(); - - for (size_t i = 0; i < curve_keys_size; i++) - curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]); - } - - /* pack curve segments */ - size_t curve_num = num_curves(); - - for (size_t i = 0; i < curve_num; i++) { - Curve curve = get_curve(i); - int shader_id = curve_shader[i]; - Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] : - scene->default_surface; - shader_id = scene->shader_manager->get_shader_id(shader, false); - - curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset), - __int_as_float(curve.num_keys), - __int_as_float(shader_id), - 0.0f); - } -} - void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset) { size_t num_faces = subd_faces.size(); @@ -1054,1391 +680,4 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui } } -void Mesh::compute_bvh( - Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total) -{ - if (progress->get_cancel()) - return; - - compute_bounds(); - - const BVHLayout bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout, - device->get_bvh_layout_mask()); - if (need_build_bvh(bvh_layout)) { - string msg = "Updating Mesh BVH "; - if (name.empty()) - msg += string_printf("%u/%u", (uint)(n + 1), (uint)total); - else - msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total); - - Object object; - object.mesh = this; - - vector<Mesh *> meshes; - meshes.push_back(this); - vector<Object *> objects; - objects.push_back(&object); - - if (bvh && !need_update_rebuild) { - progress->set_status(msg, "Refitting BVH"); - - bvh->meshes = meshes; - bvh->objects = objects; - - bvh->refit(*progress); - } - else { - progress->set_status(msg, "Building BVH"); - - BVHParams bparams; - bparams.use_spatial_split = params->use_bvh_spatial_split; - bparams.bvh_layout = bvh_layout; - bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && - params->use_bvh_unaligned_nodes; - bparams.num_motion_triangle_steps = params->num_bvh_time_steps; - bparams.num_motion_curve_steps = params->num_bvh_time_steps; - bparams.bvh_type = params->bvh_type; - bparams.curve_flags = dscene->data.curve.curveflags; - bparams.curve_subdivisions = dscene->data.curve.subdivisions; - - delete bvh; - bvh = BVH::create(bparams, meshes, objects); - MEM_GUARDED_CALL(progress, bvh->build, *progress); - } - } - - need_update = false; - need_update_rebuild = false; -} - -void Mesh::tag_update(Scene *scene, bool rebuild) -{ - need_update = true; - - if (rebuild) { - need_update_rebuild = true; - scene->light_manager->need_update = true; - } - else { - foreach (Shader *shader, used_shaders) - if (shader->has_surface_emission) - scene->light_manager->need_update = true; - } - - scene->mesh_manager->need_update = true; - scene->object_manager->need_update = true; -} - -bool Mesh::has_motion_blur() const -{ - return (use_motion_blur && (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) || - curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))); -} - -bool Mesh::has_true_displacement() const -{ - foreach (Shader *shader, used_shaders) { - if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) { - return true; - } - } - - return false; -} - -bool Mesh::has_voxel_attributes() const -{ - foreach (const Attribute &attr, attributes.attributes) { - if (attr.element == ATTR_ELEMENT_VOXEL) { - return true; - } - } - - return false; -} - -float Mesh::motion_time(int step) const -{ - return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; -} - -int Mesh::motion_step(float time) const -{ - if (motion_steps > 1) { - int attr_step = 0; - - for (int step = 0; step < motion_steps; step++) { - float step_time = motion_time(step); - if (step_time == time) { - return attr_step; - } - - /* Center step is stored in a separate attribute. */ - if (step != motion_steps / 2) { - attr_step++; - } - } - } - - return -1; -} - -bool Mesh::need_build_bvh(BVHLayout layout) const -{ - return !transform_applied || has_surface_bssrdf || layout == BVH_LAYOUT_OPTIX; -} - -bool Mesh::is_instanced() const -{ - /* Currently we treat subsurface objects as instanced. - * - * While it might be not very optimal for ray traversal, it avoids having - * duplicated BVH in the memory, saving quite some space. - */ - return !transform_applied || has_surface_bssrdf; -} - -/* Mesh Manager */ - -MeshManager::MeshManager() -{ - need_update = true; - need_flags_update = true; -} - -MeshManager::~MeshManager() -{ -} - -void MeshManager::update_osl_attributes(Device *device, - Scene *scene, - vector<AttributeRequestSet> &mesh_attributes) -{ -#ifdef WITH_OSL - /* for OSL, a hash map is used to lookup the attribute by name. */ - OSLGlobals *og = (OSLGlobals *)device->osl_memory(); - - og->object_name_map.clear(); - og->attribute_map.clear(); - og->object_names.clear(); - - og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES); - - for (size_t i = 0; i < scene->objects.size(); i++) { - /* set object name to object index map */ - Object *object = scene->objects[i]; - og->object_name_map[object->name] = i; - og->object_names.push_back(object->name); - - /* set object attributes */ - foreach (ParamValue &attr, object->attributes) { - OSLGlobals::Attribute osl_attr; - - osl_attr.type = attr.type(); - osl_attr.desc.element = ATTR_ELEMENT_OBJECT; - osl_attr.value = attr; - osl_attr.desc.offset = 0; - osl_attr.desc.flags = 0; - - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr; - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr; - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr; - } - - /* find mesh attributes */ - size_t j; - - for (j = 0; j < scene->meshes.size(); j++) - if (scene->meshes[j] == object->mesh) - break; - - AttributeRequestSet &attributes = mesh_attributes[j]; - - /* set object attributes */ - foreach (AttributeRequest &req, attributes.requests) { - OSLGlobals::Attribute osl_attr; - - if (req.triangle_desc.element != ATTR_ELEMENT_NONE) { - osl_attr.desc = req.triangle_desc; - - if (req.triangle_type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else if (req.triangle_type == TypeDesc::TypeMatrix) - osl_attr.type = TypeDesc::TypeMatrix; - else if (req.triangle_type == TypeFloat2) - osl_attr.type = TypeFloat2; - else if (req.triangle_type == TypeRGBA) - osl_attr.type = TypeRGBA; - else - osl_attr.type = TypeDesc::TypeColor; - - if (req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr; - } - else if (req.name != ustring()) { - /* add lookup by mesh attribute name */ - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr; - } - } - - if (req.curve_desc.element != ATTR_ELEMENT_NONE) { - osl_attr.desc = req.curve_desc; - - if (req.curve_type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else if (req.curve_type == TypeDesc::TypeMatrix) - osl_attr.type = TypeDesc::TypeMatrix; - else if (req.curve_type == TypeFloat2) - osl_attr.type = TypeFloat2; - else if (req.curve_type == TypeRGBA) - osl_attr.type = TypeRGBA; - else - osl_attr.type = TypeDesc::TypeColor; - - if (req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr; - } - else if (req.name != ustring()) { - /* add lookup by mesh attribute name */ - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr; - } - } - - if (req.subd_desc.element != ATTR_ELEMENT_NONE) { - osl_attr.desc = req.subd_desc; - - if (req.subd_type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else if (req.subd_type == TypeDesc::TypeMatrix) - osl_attr.type = TypeDesc::TypeMatrix; - else if (req.subd_type == TypeFloat2) - osl_attr.type = TypeFloat2; - else if (req.subd_type == TypeRGBA) - osl_attr.type = TypeRGBA; - else - osl_attr.type = TypeDesc::TypeColor; - - if (req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr; - } - else if (req.name != ustring()) { - /* add lookup by mesh attribute name */ - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr; - } - } - } - } -#else - (void)device; - (void)scene; - (void)mesh_attributes; -#endif -} - -void MeshManager::update_svm_attributes(Device *, - DeviceScene *dscene, - Scene *scene, - vector<AttributeRequestSet> &mesh_attributes) -{ - /* for SVM, the attributes_map table is used to lookup the offset of an - * attribute, based on a unique shader attribute id. */ - - /* compute array stride */ - int attr_map_size = 0; - - for (size_t i = 0; i < scene->meshes.size(); i++) { - Mesh *mesh = scene->meshes[i]; - mesh->attr_map_offset = attr_map_size; - attr_map_size += (mesh_attributes[i].size() + 1) * ATTR_PRIM_TYPES; - } - - if (attr_map_size == 0) - return; - - /* create attribute map */ - uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); - memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); - - for (size_t i = 0; i < scene->meshes.size(); i++) { - Mesh *mesh = scene->meshes[i]; - AttributeRequestSet &attributes = mesh_attributes[i]; - - /* set object attributes */ - int index = mesh->attr_map_offset; - - foreach (AttributeRequest &req, attributes.requests) { - uint id; - - if (req.std == ATTR_STD_NONE) - id = scene->shader_manager->get_attribute_id(req.name); - else - id = scene->shader_manager->get_attribute_id(req.std); - - if (mesh->num_triangles()) { - attr_map[index].x = id; - attr_map[index].y = req.triangle_desc.element; - attr_map[index].z = as_uint(req.triangle_desc.offset); - - if (req.triangle_type == TypeDesc::TypeFloat) - attr_map[index].w = NODE_ATTR_FLOAT; - else if (req.triangle_type == TypeDesc::TypeMatrix) - attr_map[index].w = NODE_ATTR_MATRIX; - else if (req.triangle_type == TypeFloat2) - attr_map[index].w = NODE_ATTR_FLOAT2; - else if (req.triangle_type == TypeRGBA) - attr_map[index].w = NODE_ATTR_RGBA; - else - attr_map[index].w = NODE_ATTR_FLOAT3; - - attr_map[index].w |= req.triangle_desc.flags << 8; - } - - index++; - - if (mesh->num_curves()) { - attr_map[index].x = id; - attr_map[index].y = req.curve_desc.element; - attr_map[index].z = as_uint(req.curve_desc.offset); - - if (req.curve_type == TypeDesc::TypeFloat) - attr_map[index].w = NODE_ATTR_FLOAT; - else if (req.curve_type == TypeDesc::TypeMatrix) - attr_map[index].w = NODE_ATTR_MATRIX; - else if (req.curve_type == TypeFloat2) - attr_map[index].w = NODE_ATTR_FLOAT2; - else - attr_map[index].w = NODE_ATTR_FLOAT3; - - attr_map[index].w |= req.curve_desc.flags << 8; - } - - index++; - - if (mesh->subd_faces.size()) { - attr_map[index].x = id; - attr_map[index].y = req.subd_desc.element; - attr_map[index].z = as_uint(req.subd_desc.offset); - - if (req.subd_type == TypeDesc::TypeFloat) - attr_map[index].w = NODE_ATTR_FLOAT; - else if (req.subd_type == TypeDesc::TypeMatrix) - attr_map[index].w = NODE_ATTR_MATRIX; - else if (req.subd_type == TypeFloat2) - attr_map[index].w = NODE_ATTR_FLOAT2; - else if (req.triangle_type == TypeRGBA) - attr_map[index].w = NODE_ATTR_RGBA; - else - attr_map[index].w = NODE_ATTR_FLOAT3; - - attr_map[index].w |= req.subd_desc.flags << 8; - } - - index++; - } - - /* terminator */ - for (int j = 0; j < ATTR_PRIM_TYPES; j++) { - attr_map[index].x = ATTR_STD_NONE; - attr_map[index].y = 0; - attr_map[index].z = 0; - attr_map[index].w = 0; - - index++; - } - } - - /* copy to device */ - dscene->attributes_map.copy_to_device(); -} - -static void update_attribute_element_size(Mesh *mesh, - Attribute *mattr, - AttributePrimitive prim, - size_t *attr_float_size, - size_t *attr_float2_size, - size_t *attr_float3_size, - size_t *attr_uchar4_size) -{ - if (mattr) { - size_t size = mattr->element_size(mesh, prim); - - if (mattr->element == ATTR_ELEMENT_VOXEL) { - /* pass */ - } - else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { - *attr_uchar4_size += size; - } - else if (mattr->type == TypeDesc::TypeFloat) { - *attr_float_size += size; - } - else if (mattr->type == TypeFloat2) { - *attr_float2_size += size; - } - else if (mattr->type == TypeDesc::TypeMatrix) { - *attr_float3_size += size * 4; - } - else { - *attr_float3_size += size; - } - } -} - -static void update_attribute_element_offset(Mesh *mesh, - device_vector<float> &attr_float, - size_t &attr_float_offset, - device_vector<float2> &attr_float2, - size_t &attr_float2_offset, - device_vector<float4> &attr_float3, - size_t &attr_float3_offset, - device_vector<uchar4> &attr_uchar4, - size_t &attr_uchar4_offset, - Attribute *mattr, - AttributePrimitive prim, - TypeDesc &type, - AttributeDescriptor &desc) -{ - if (mattr) { - /* store element and type */ - desc.element = mattr->element; - desc.flags = mattr->flags; - type = mattr->type; - - /* store attribute data in arrays */ - size_t size = mattr->element_size(mesh, prim); - - AttributeElement &element = desc.element; - int &offset = desc.offset; - - if (mattr->element == ATTR_ELEMENT_VOXEL) { - /* store slot in offset value */ - VoxelAttribute *voxel_data = mattr->data_voxel(); - offset = voxel_data->slot; - } - else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { - uchar4 *data = mattr->data_uchar4(); - offset = attr_uchar4_offset; - - assert(attr_uchar4.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_uchar4[offset + k] = data[k]; - } - attr_uchar4_offset += size; - } - else if (mattr->type == TypeDesc::TypeFloat) { - float *data = mattr->data_float(); - offset = attr_float_offset; - - assert(attr_float.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float[offset + k] = data[k]; - } - attr_float_offset += size; - } - else if (mattr->type == TypeFloat2) { - float2 *data = mattr->data_float2(); - offset = attr_float2_offset; - - assert(attr_float2.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float2[offset + k] = data[k]; - } - attr_float2_offset += size; - } - else if (mattr->type == TypeDesc::TypeMatrix) { - Transform *tfm = mattr->data_transform(); - offset = attr_float3_offset; - - assert(attr_float3.size() >= offset + size * 3); - for (size_t k = 0; k < size * 3; k++) { - attr_float3[offset + k] = (&tfm->x)[k]; - } - attr_float3_offset += size * 3; - } - else { - float4 *data = mattr->data_float4(); - offset = attr_float3_offset; - - assert(attr_float3.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float3[offset + k] = data[k]; - } - attr_float3_offset += size; - } - - /* mesh vertex/curve index is global, not per object, so we sneak - * a correction for that in here */ - if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && - desc.flags & ATTR_SUBDIVIDED) { - /* indices for subdivided attributes are retrieved - * from patch table so no need for correction here*/ - } - else if (element == ATTR_ELEMENT_VERTEX) - offset -= mesh->vert_offset; - else if (element == ATTR_ELEMENT_VERTEX_MOTION) - offset -= mesh->vert_offset; - else if (element == ATTR_ELEMENT_FACE) { - if (prim == ATTR_PRIM_TRIANGLE) - offset -= mesh->tri_offset; - else - offset -= mesh->face_offset; - } - else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) { - if (prim == ATTR_PRIM_TRIANGLE) - offset -= 3 * mesh->tri_offset; - else - offset -= mesh->corner_offset; - } - else if (element == ATTR_ELEMENT_CURVE) - offset -= mesh->curve_offset; - else if (element == ATTR_ELEMENT_CURVE_KEY) - offset -= mesh->curvekey_offset; - else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) - offset -= mesh->curvekey_offset; - } - else { - /* attribute not found */ - desc.element = ATTR_ELEMENT_NONE; - desc.offset = 0; - } -} - -void MeshManager::device_update_attributes(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress) -{ - progress.set_status("Updating Mesh", "Computing attributes"); - - /* gather per mesh requested attributes. as meshes may have multiple - * shaders assigned, this merges the requested attributes that have - * been set per shader by the shader manager */ - vector<AttributeRequestSet> mesh_attributes(scene->meshes.size()); - - for (size_t i = 0; i < scene->meshes.size(); i++) { - Mesh *mesh = scene->meshes[i]; - - scene->need_global_attributes(mesh_attributes[i]); - - foreach (Shader *shader, mesh->used_shaders) { - mesh_attributes[i].add(shader->attributes); - } - } - - /* mesh attribute are stored in a single array per data type. here we fill - * those arrays, and set the offset and element type to create attribute - * maps next */ - - /* Pre-allocate attributes to avoid arrays re-allocation which would - * take 2x of overall attribute memory usage. - */ - size_t attr_float_size = 0; - size_t attr_float2_size = 0; - size_t attr_float3_size = 0; - size_t attr_uchar4_size = 0; - for (size_t i = 0; i < scene->meshes.size(); i++) { - Mesh *mesh = scene->meshes[i]; - AttributeRequestSet &attributes = mesh_attributes[i]; - foreach (AttributeRequest &req, attributes.requests) { - Attribute *triangle_mattr = mesh->attributes.find(req); - Attribute *curve_mattr = mesh->curve_attributes.find(req); - Attribute *subd_mattr = mesh->subd_attributes.find(req); - - update_attribute_element_size(mesh, - triangle_mattr, - ATTR_PRIM_TRIANGLE, - &attr_float_size, - &attr_float2_size, - &attr_float3_size, - &attr_uchar4_size); - update_attribute_element_size(mesh, - curve_mattr, - ATTR_PRIM_CURVE, - &attr_float_size, - &attr_float2_size, - &attr_float3_size, - &attr_uchar4_size); - update_attribute_element_size(mesh, - subd_mattr, - ATTR_PRIM_SUBD, - &attr_float_size, - &attr_float2_size, - &attr_float3_size, - &attr_uchar4_size); - } - } - - dscene->attributes_float.alloc(attr_float_size); - dscene->attributes_float2.alloc(attr_float2_size); - dscene->attributes_float3.alloc(attr_float3_size); - dscene->attributes_uchar4.alloc(attr_uchar4_size); - - size_t attr_float_offset = 0; - size_t attr_float2_offset = 0; - size_t attr_float3_offset = 0; - size_t attr_uchar4_offset = 0; - - /* Fill in attributes. */ - for (size_t i = 0; i < scene->meshes.size(); i++) { - Mesh *mesh = scene->meshes[i]; - AttributeRequestSet &attributes = mesh_attributes[i]; - - /* todo: we now store std and name attributes from requests even if - * they actually refer to the same mesh attributes, optimize */ - foreach (AttributeRequest &req, attributes.requests) { - Attribute *triangle_mattr = mesh->attributes.find(req); - Attribute *curve_mattr = mesh->curve_attributes.find(req); - Attribute *subd_mattr = mesh->subd_attributes.find(req); - - update_attribute_element_offset(mesh, - dscene->attributes_float, - attr_float_offset, - dscene->attributes_float2, - attr_float2_offset, - dscene->attributes_float3, - attr_float3_offset, - dscene->attributes_uchar4, - attr_uchar4_offset, - triangle_mattr, - ATTR_PRIM_TRIANGLE, - req.triangle_type, - req.triangle_desc); - - update_attribute_element_offset(mesh, - dscene->attributes_float, - attr_float_offset, - dscene->attributes_float2, - attr_float2_offset, - dscene->attributes_float3, - attr_float3_offset, - dscene->attributes_uchar4, - attr_uchar4_offset, - curve_mattr, - ATTR_PRIM_CURVE, - req.curve_type, - req.curve_desc); - - update_attribute_element_offset(mesh, - dscene->attributes_float, - attr_float_offset, - dscene->attributes_float2, - attr_float2_offset, - dscene->attributes_float3, - attr_float3_offset, - dscene->attributes_uchar4, - attr_uchar4_offset, - subd_mattr, - ATTR_PRIM_SUBD, - req.subd_type, - req.subd_desc); - - if (progress.get_cancel()) - return; - } - } - - /* create attribute lookup maps */ - if (scene->shader_manager->use_osl()) - update_osl_attributes(device, scene, mesh_attributes); - - update_svm_attributes(device, dscene, scene, mesh_attributes); - - if (progress.get_cancel()) - return; - - /* copy to device */ - progress.set_status("Updating Mesh", "Copying Attributes to device"); - - if (dscene->attributes_float.size()) { - dscene->attributes_float.copy_to_device(); - } - if (dscene->attributes_float2.size()) { - dscene->attributes_float2.copy_to_device(); - } - if (dscene->attributes_float3.size()) { - dscene->attributes_float3.copy_to_device(); - } - if (dscene->attributes_uchar4.size()) { - dscene->attributes_uchar4.copy_to_device(); - } - - if (progress.get_cancel()) - return; - - /* After mesh attributes and patch tables have been copied to device memory, - * we need to update offsets in the objects. */ - scene->object_manager->device_update_mesh_offsets(device, dscene, scene); -} - -void MeshManager::mesh_calc_offset(Scene *scene) -{ - size_t vert_size = 0; - size_t tri_size = 0; - - size_t curve_key_size = 0; - size_t curve_size = 0; - - size_t patch_size = 0; - size_t face_size = 0; - size_t corner_size = 0; - - size_t prim_size = 0; - - foreach (Mesh *mesh, scene->meshes) { - mesh->vert_offset = vert_size; - mesh->tri_offset = tri_size; - - mesh->curvekey_offset = curve_key_size; - mesh->curve_offset = curve_size; - - mesh->patch_offset = patch_size; - mesh->face_offset = face_size; - mesh->corner_offset = corner_size; - - vert_size += mesh->verts.size(); - tri_size += mesh->num_triangles(); - - curve_key_size += mesh->curve_keys.size(); - curve_size += mesh->num_curves(); - - if (mesh->subd_faces.size()) { - Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1]; - patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; - - /* patch tables are stored in same array so include them in patch_size */ - if (mesh->patch_table) { - mesh->patch_table_offset = patch_size; - patch_size += mesh->patch_table->total_size(); - } - } - face_size += mesh->subd_faces.size(); - corner_size += mesh->subd_face_corners.size(); - - mesh->prim_offset = prim_size; - prim_size += mesh->num_primitives(); - } -} - -void MeshManager::device_update_mesh( - Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress) -{ - /* Count. */ - size_t vert_size = 0; - size_t tri_size = 0; - - size_t curve_key_size = 0; - size_t curve_size = 0; - - size_t patch_size = 0; - - foreach (Mesh *mesh, scene->meshes) { - vert_size += mesh->verts.size(); - tri_size += mesh->num_triangles(); - - curve_key_size += mesh->curve_keys.size(); - curve_size += mesh->num_curves(); - - if (mesh->subd_faces.size()) { - Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1]; - patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; - - /* patch tables are stored in same array so include them in patch_size */ - if (mesh->patch_table) { - mesh->patch_table_offset = patch_size; - patch_size += mesh->patch_table->total_size(); - } - } - } - - /* Create mapping from triangle to primitive triangle array. */ - vector<uint> tri_prim_index(tri_size); - if (for_displacement) { - /* For displacement kernels we do some trickery to make them believe - * we've got all required data ready. However, that data is different - * from final render kernels since we don't have BVH yet, so can't - * really use same semantic of arrays. - */ - foreach (Mesh *mesh, scene->meshes) { - for (size_t i = 0; i < mesh->num_triangles(); ++i) { - tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset); - } - } - } - else { - for (size_t i = 0; i < dscene->prim_index.size(); ++i) { - if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { - tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i]; - } - } - } - - /* Fill in all the arrays. */ - if (tri_size != 0) { - /* normals */ - progress.set_status("Updating Mesh", "Computing normals"); - - uint *tri_shader = dscene->tri_shader.alloc(tri_size); - float4 *vnormal = dscene->tri_vnormal.alloc(vert_size); - uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size); - uint *tri_patch = dscene->tri_patch.alloc(tri_size); - float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); - - foreach (Mesh *mesh, scene->meshes) { - mesh->pack_shaders(scene, &tri_shader[mesh->tri_offset]); - mesh->pack_normals(&vnormal[mesh->vert_offset]); - mesh->pack_verts(tri_prim_index, - &tri_vindex[mesh->tri_offset], - &tri_patch[mesh->tri_offset], - &tri_patch_uv[mesh->vert_offset], - mesh->vert_offset, - mesh->tri_offset); - if (progress.get_cancel()) - return; - } - - /* vertex coordinates */ - progress.set_status("Updating Mesh", "Copying Mesh to device"); - - dscene->tri_shader.copy_to_device(); - dscene->tri_vnormal.copy_to_device(); - dscene->tri_vindex.copy_to_device(); - dscene->tri_patch.copy_to_device(); - dscene->tri_patch_uv.copy_to_device(); - } - - if (curve_size != 0) { - progress.set_status("Updating Mesh", "Copying Strands to device"); - - float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); - float4 *curves = dscene->curves.alloc(curve_size); - - foreach (Mesh *mesh, scene->meshes) { - mesh->pack_curves(scene, - &curve_keys[mesh->curvekey_offset], - &curves[mesh->curve_offset], - mesh->curvekey_offset); - if (progress.get_cancel()) - return; - } - - dscene->curve_keys.copy_to_device(); - dscene->curves.copy_to_device(); - } - - if (patch_size != 0) { - progress.set_status("Updating Mesh", "Copying Patches to device"); - - uint *patch_data = dscene->patches.alloc(patch_size); - - foreach (Mesh *mesh, scene->meshes) { - mesh->pack_patches(&patch_data[mesh->patch_offset], - mesh->vert_offset, - mesh->face_offset, - mesh->corner_offset); - - if (mesh->patch_table) { - mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], - mesh->patch_table_offset); - } - - if (progress.get_cancel()) - return; - } - - dscene->patches.copy_to_device(); - } - - if (for_displacement) { - float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3); - foreach (Mesh *mesh, scene->meshes) { - for (size_t i = 0; i < mesh->num_triangles(); ++i) { - Mesh::Triangle t = mesh->get_triangle(i); - size_t offset = 3 * (i + mesh->tri_offset); - prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]); - prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]); - prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]); - } - } - dscene->prim_tri_verts.copy_to_device(); - } -} - -void MeshManager::device_update_bvh(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress) -{ - /* bvh build */ - progress.set_status("Updating Scene BVH", "Building"); - - BVHParams bparams; - bparams.top_level = true; - bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, - device->get_bvh_layout_mask()); - bparams.use_spatial_split = scene->params.use_bvh_spatial_split; - bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && - scene->params.use_bvh_unaligned_nodes; - bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps; - bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps; - bparams.bvh_type = scene->params.bvh_type; - bparams.curve_flags = dscene->data.curve.curveflags; - bparams.curve_subdivisions = dscene->data.curve.subdivisions; - - VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; - -#ifdef WITH_EMBREE - if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { - if (dscene->data.bvh.scene) { - BVHEmbree::destroy(dscene->data.bvh.scene); - } - } -#endif - - BVH *bvh = BVH::create(bparams, scene->meshes, scene->objects); - bvh->build(progress, &device->stats); - - if (progress.get_cancel()) { -#ifdef WITH_EMBREE - if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { - if (dscene->data.bvh.scene) { - BVHEmbree::destroy(dscene->data.bvh.scene); - } - } -#endif - delete bvh; - return; - } - - /* copy to device */ - progress.set_status("Updating Scene BVH", "Copying BVH to device"); - - PackedBVH &pack = bvh->pack; - - if (pack.nodes.size()) { - dscene->bvh_nodes.steal_data(pack.nodes); - dscene->bvh_nodes.copy_to_device(); - } - if (pack.leaf_nodes.size()) { - dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes); - dscene->bvh_leaf_nodes.copy_to_device(); - } - if (pack.object_node.size()) { - dscene->object_node.steal_data(pack.object_node); - dscene->object_node.copy_to_device(); - } - if (pack.prim_tri_index.size()) { - dscene->prim_tri_index.steal_data(pack.prim_tri_index); - dscene->prim_tri_index.copy_to_device(); - } - if (pack.prim_tri_verts.size()) { - dscene->prim_tri_verts.steal_data(pack.prim_tri_verts); - dscene->prim_tri_verts.copy_to_device(); - } - if (pack.prim_type.size()) { - dscene->prim_type.steal_data(pack.prim_type); - dscene->prim_type.copy_to_device(); - } - if (pack.prim_visibility.size()) { - dscene->prim_visibility.steal_data(pack.prim_visibility); - dscene->prim_visibility.copy_to_device(); - } - if (pack.prim_index.size()) { - dscene->prim_index.steal_data(pack.prim_index); - dscene->prim_index.copy_to_device(); - } - if (pack.prim_object.size()) { - dscene->prim_object.steal_data(pack.prim_object); - dscene->prim_object.copy_to_device(); - } - if (pack.prim_time.size()) { - dscene->prim_time.steal_data(pack.prim_time); - dscene->prim_time.copy_to_device(); - } - - dscene->data.bvh.root = pack.root_index; - dscene->data.bvh.bvh_layout = bparams.bvh_layout; - dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); - - bvh->copy_to_device(progress, dscene); - - delete bvh; -} - -void MeshManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) -{ - if (!need_update && !need_flags_update) { - return; - } - - progress.set_status("Updating Meshes Flags"); - - /* Update flags. */ - bool volume_images_updated = false; - - foreach (Mesh *mesh, scene->meshes) { - mesh->has_volume = false; - - foreach (const Shader *shader, mesh->used_shaders) { - if (shader->has_volume) { - mesh->has_volume = true; - } - if (shader->has_surface_bssrdf) { - mesh->has_surface_bssrdf = true; - } - } - - if (need_update && mesh->has_volume) { - /* Create volume meshes if there is voxel data. */ - if (mesh->has_voxel_attributes()) { - if (!volume_images_updated) { - progress.set_status("Updating Meshes Volume Bounds"); - device_update_volume_images(device, scene, progress); - volume_images_updated = true; - } - - create_volume_mesh(scene, mesh, progress); - } - } - } - - need_flags_update = false; -} - -void MeshManager::device_update_displacement_images(Device *device, - Scene *scene, - Progress &progress) -{ - progress.set_status("Updating Displacement Images"); - TaskPool pool; - ImageManager *image_manager = scene->image_manager; - set<int> bump_images; - foreach (Mesh *mesh, scene->meshes) { - if (mesh->need_update) { - foreach (Shader *shader, mesh->used_shaders) { - if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { - continue; - } - foreach (ShaderNode *node, shader->graph->nodes) { - if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { - continue; - } - - ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); - foreach (int slot, image_node->slots) { - if (slot != -1) { - bump_images.insert(slot); - } - } - } - } - } - } - foreach (int slot, bump_images) { - pool.push(function_bind( - &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress)); - } - pool.wait_work(); -} - -void MeshManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress) -{ - progress.set_status("Updating Volume Images"); - TaskPool pool; - ImageManager *image_manager = scene->image_manager; - set<int> volume_images; - - foreach (Mesh *mesh, scene->meshes) { - if (!mesh->need_update) { - continue; - } - - foreach (Attribute &attr, mesh->attributes.attributes) { - if (attr.element != ATTR_ELEMENT_VOXEL) { - continue; - } - - VoxelAttribute *voxel = attr.data_voxel(); - - if (voxel->slot != -1) { - volume_images.insert(voxel->slot); - } - } - } - - foreach (int slot, volume_images) { - pool.push(function_bind( - &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress)); - } - pool.wait_work(); -} - -void MeshManager::device_update(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress) -{ - if (!need_update) - return; - - VLOG(1) << "Total " << scene->meshes.size() << " meshes."; - - bool true_displacement_used = false; - size_t total_tess_needed = 0; - - foreach (Mesh *mesh, scene->meshes) { - foreach (Shader *shader, mesh->used_shaders) { - if (shader->need_update_mesh) - mesh->need_update = true; - } - - if (mesh->need_update) { - /* Update normals. */ - mesh->add_face_normals(); - mesh->add_vertex_normals(); - - if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) { - mesh->add_undisplaced(); - } - - /* Test if we need tessellation. */ - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 && - mesh->subd_params) { - total_tess_needed++; - } - - /* Test if we need displacement. */ - if (mesh->has_true_displacement()) { - true_displacement_used = true; - } - - if (progress.get_cancel()) - return; - } - } - - /* Tessellate meshes that are using subdivision */ - if (total_tess_needed) { - Camera *dicing_camera = scene->dicing_camera; - dicing_camera->update(scene); - - size_t i = 0; - foreach (Mesh *mesh, scene->meshes) { - if (mesh->need_update && mesh->subdivision_type != Mesh::SUBDIVISION_NONE && - mesh->num_subd_verts == 0 && mesh->subd_params) { - string msg = "Tessellating "; - if (mesh->name == "") - msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed); - else - msg += string_printf( - "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed); - - progress.set_status("Updating Mesh", msg); - - mesh->subd_params->camera = dicing_camera; - DiagSplit dsplit(*mesh->subd_params); - mesh->tessellate(&dsplit); - - i++; - - if (progress.get_cancel()) - return; - } - } - } - - /* Update images needed for true displacement. */ - bool old_need_object_flags_update = false; - if (true_displacement_used) { - VLOG(1) << "Updating images used for true displacement."; - device_update_displacement_images(device, scene, progress); - old_need_object_flags_update = scene->object_manager->need_flags_update; - scene->object_manager->device_update_flags(device, dscene, scene, progress, false); - } - - /* Device update. */ - device_free(device, dscene); - - mesh_calc_offset(scene); - if (true_displacement_used) { - device_update_mesh(device, dscene, scene, true, progress); - } - if (progress.get_cancel()) - return; - - device_update_attributes(device, dscene, scene, progress); - if (progress.get_cancel()) - return; - - /* Update displacement. */ - bool displacement_done = false; - size_t num_bvh = 0; - BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, - device->get_bvh_layout_mask()); - - foreach (Mesh *mesh, scene->meshes) { - if (mesh->need_update) { - if (displace(device, dscene, scene, mesh, progress)) { - displacement_done = true; - } - - if (mesh->need_build_bvh(bvh_layout)) { - num_bvh++; - } - } - - if (progress.get_cancel()) - return; - } - - /* Device re-update after displacement. */ - if (displacement_done) { - device_free(device, dscene); - - device_update_attributes(device, dscene, scene, progress); - if (progress.get_cancel()) - return; - } - - TaskPool pool; - - size_t i = 0; - foreach (Mesh *mesh, scene->meshes) { - if (mesh->need_update) { - pool.push(function_bind( - &Mesh::compute_bvh, mesh, device, dscene, &scene->params, &progress, i, num_bvh)); - if (mesh->need_build_bvh(bvh_layout)) { - i++; - } - } - } - - TaskPool::Summary summary; - pool.wait_work(&summary); - VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report(); - - foreach (Shader *shader, scene->shaders) { - shader->need_update_mesh = false; - } - - Scene::MotionType need_motion = scene->need_motion(); - bool motion_blur = need_motion == Scene::MOTION_BLUR; - - /* Update objects. */ - vector<Object *> volume_objects; - foreach (Object *object, scene->objects) { - object->compute_bounds(motion_blur); - } - - if (progress.get_cancel()) - return; - - device_update_bvh(device, dscene, scene, progress); - if (progress.get_cancel()) - return; - - device_update_mesh(device, dscene, scene, false, progress); - if (progress.get_cancel()) - return; - - need_update = false; - - if (true_displacement_used) { - /* Re-tag flags for update, so they're re-evaluated - * for meshes with correct bounding boxes. - * - * This wouldn't cause wrong results, just true - * displacement might be less optimal ot calculate. - */ - scene->object_manager->need_flags_update = old_need_object_flags_update; - } -} - -void MeshManager::device_free(Device *device, DeviceScene *dscene) -{ - dscene->bvh_nodes.free(); - dscene->bvh_leaf_nodes.free(); - dscene->object_node.free(); - dscene->prim_tri_verts.free(); - dscene->prim_tri_index.free(); - dscene->prim_type.free(); - dscene->prim_visibility.free(); - dscene->prim_index.free(); - dscene->prim_object.free(); - dscene->prim_time.free(); - dscene->tri_shader.free(); - dscene->tri_vnormal.free(); - dscene->tri_vindex.free(); - dscene->tri_patch.free(); - dscene->tri_patch_uv.free(); - dscene->curves.free(); - dscene->curve_keys.free(); - dscene->patches.free(); - dscene->attributes_map.free(); - dscene->attributes_float.free(); - dscene->attributes_float2.free(); - dscene->attributes_float3.free(); - dscene->attributes_uchar4.free(); - - /* Signal for shaders like displacement not to do ray tracing. */ - dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE; - -#ifdef WITH_OSL - OSLGlobals *og = (OSLGlobals *)device->osl_memory(); - - if (og) { - og->object_name_map.clear(); - og->attribute_map.clear(); - og->object_names.clear(); - } -#else - (void)device; -#endif -} - -void MeshManager::tag_update(Scene *scene) -{ - need_update = true; - scene->object_manager->need_update = true; -} - -void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats) -{ - foreach (Mesh *mesh, scene->meshes) { - stats->mesh.geometry.add_entry( - NamedSizeEntry(string(mesh->name.c_str()), mesh->get_total_size_in_bytes())); - } -} - -bool Mesh::need_attribute(Scene *scene, AttributeStandard std) -{ - if (std == ATTR_STD_NONE) - return false; - - if (scene->need_global_attribute(std)) - return true; - - foreach (Shader *shader, used_shaders) - if (shader->attributes.find(std)) - return true; - - return false; -} - -bool Mesh::need_attribute(Scene * /*scene*/, ustring name) -{ - if (name == ustring()) - return false; - - foreach (Shader *shader, used_shaders) - if (shader->attributes.find(name)) - return true; - - return false; -} - CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index c5be0ba60b9..5583e9c0400 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -21,6 +21,7 @@ #include "bvh/bvh_params.h" #include "render/attribute.h" +#include "render/geometry.h" #include "render/shader.h" #include "util/util_array.h" @@ -29,7 +30,6 @@ #include "util/util_map.h" #include "util/util_param.h" #include "util/util_set.h" -#include "util/util_transform.h" #include "util/util_types.h" #include "util/util_vector.h" @@ -51,7 +51,7 @@ struct PackedPatchTable; /* Mesh */ -class Mesh : public Node { +class Mesh : public Geometry { public: NODE_DECLARE @@ -91,94 +91,6 @@ class Mesh : public Node { return triangles.size() / 3; } - /* Mesh Curve */ - struct Curve { - int first_key; - int num_keys; - - int num_segments() const - { - return num_keys - 1; - } - - void bounds_grow(const int k, - const float3 *curve_keys, - const float *curve_radius, - BoundBox &bounds) const; - void bounds_grow(float4 keys[4], BoundBox &bounds) const; - void bounds_grow(const int k, - const float3 *curve_keys, - const float *curve_radius, - const Transform &aligned_space, - BoundBox &bounds) const; - - void motion_keys(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - float time, - size_t k0, - size_t k1, - float4 r_keys[2]) const; - void cardinal_motion_keys(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - float time, - size_t k0, - size_t k1, - size_t k2, - size_t k3, - float4 r_keys[4]) const; - - void keys_for_step(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - size_t step, - size_t k0, - size_t k1, - float4 r_keys[2]) const; - void cardinal_keys_for_step(const float3 *curve_keys, - const float *curve_radius, - const float3 *key_steps, - size_t num_curve_keys, - size_t num_steps, - size_t step, - size_t k0, - size_t k1, - size_t k2, - size_t k3, - float4 r_keys[4]) const; - }; - - Curve get_curve(size_t i) const - { - int first = curve_first_key[i]; - int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size(); - - Curve curve = {first, next_first - first}; - return curve; - } - - size_t num_curves() const - { - return curve_first_key.size(); - } - - size_t num_segments() const - { - return curve_keys.size() - curve_first_key.size(); - } - - size_t num_primitives() const - { - return num_triangles() + num_segments(); - } - /* Mesh SubdFace */ struct SubdFace { int start_corner; @@ -212,14 +124,6 @@ class Mesh : public Node { SubdivisionType subdivision_type; /* Mesh Data */ - enum GeometryFlags { - GEOMETRY_NONE = 0, - GEOMETRY_TRIANGLES = (1 << 0), - GEOMETRY_CURVES = (1 << 1), - }; - int geometry_flags; /* used to distinguish meshes with no verts - and meshed for which geometry is not created */ - array<int> triangles; array<float3> verts; array<int> shader; @@ -230,13 +134,6 @@ class Mesh : public Node { array<float2> vert_patch_uv; float volume_isovalue; - bool has_volume; /* Set in the device_update_flags(). */ - bool has_surface_bssrdf; /* Set in the device_update_flags(). */ - - array<float3> curve_keys; - array<float> curve_radius; - array<int> curve_first_key; - array<int> curve_shader; array<SubdFace> subd_faces; array<int> subd_face_corners; @@ -246,42 +143,18 @@ class Mesh : public Node { SubdParams *subd_params; - vector<Shader *> used_shaders; - AttributeSet attributes; - AttributeSet curve_attributes; AttributeSet subd_attributes; - BoundBox bounds; - bool transform_applied; - bool transform_negative_scaled; - Transform transform_normal; - PackedPatchTable *patch_table; - uint motion_steps; - bool use_motion_blur; - - /* Update Flags */ - bool need_update; - bool need_update_rebuild; - /* BVH */ - BVH *bvh; - size_t tri_offset; size_t vert_offset; - size_t curve_offset; - size_t curvekey_offset; - size_t patch_offset; size_t patch_table_offset; size_t face_offset; size_t corner_offset; - size_t attr_map_offset; - - size_t prim_offset; - size_t num_subd_verts; private: @@ -289,7 +162,7 @@ class Mesh : public Node { unordered_multimap<int, int> vert_stitching_map; /* stitching index -> multiple real vert indices */ friend class DiagSplit; - friend class MeshManager; + friend class GeometryManager; public: /* Functions */ @@ -298,24 +171,24 @@ class Mesh : public Node { void resize_mesh(int numverts, int numfaces); void reserve_mesh(int numverts, int numfaces); - void resize_curves(int numcurves, int numkeys); - void reserve_curves(int numcurves, int numkeys); void resize_subd_faces(int numfaces, int num_ngons, int numcorners); void reserve_subd_faces(int numfaces, int num_ngons, int numcorners); - void clear(bool preserve_voxel_data = false); + void clear(bool preserve_voxel_data); + void clear() override; void add_vertex(float3 P); void add_vertex_slow(float3 P); void add_triangle(int v0, int v1, int v2, int shader, bool smooth); - void add_curve_key(float3 loc, float radius); - void add_curve(int first_key, int shader); void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_); - void compute_bounds(); + void copy_center_to_motion_step(const int motion_step); + + void compute_bounds() override; + void apply_transform(const Transform &tfm, const bool apply_to_motion) override; void add_face_normals(); void add_vertex_normals(); void add_undisplaced(); - void get_uv_tiles(ustring map, unordered_set<int> &tiles); + void get_uv_tiles(ustring map, unordered_set<int> &tiles) override; void pack_shaders(Scene *scene, uint *shader); void pack_normals(float4 *vnormal); @@ -325,103 +198,11 @@ class Mesh : public Node { float2 *tri_patch_uv, size_t vert_offset, size_t tri_offset); - void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset); - void compute_bvh(Device *device, - DeviceScene *dscene, - SceneParams *params, - Progress *progress, - int n, - int total); - - bool need_attribute(Scene *scene, AttributeStandard std); - bool need_attribute(Scene *scene, ustring name); - - void tag_update(Scene *scene, bool rebuild); - - bool has_motion_blur() const; - bool has_true_displacement() const; - bool has_voxel_attributes() const; - - /* Convert between normalized -1..1 motion time and index - * in the VERTEX_MOTION attribute. */ - float motion_time(int step) const; - int motion_step(float time) const; - - /* Check whether the mesh should have own BVH built separately. Briefly, - * own BVH is needed for mesh, if: - * - * - It is instanced multiple times, so each instance object should share the - * same BVH tree. - * - Special ray intersection is needed, for example to limit subsurface rays - * to only the mesh itself. - * - The BVH layout requires the top level to only contain instances. - */ - bool need_build_bvh(BVHLayout layout) const; - - /* Check if the mesh should be treated as instanced. */ - bool is_instanced() const; - void tessellate(DiagSplit *split); }; -/* Mesh Manager */ - -class MeshManager { - public: - bool need_update; - bool need_flags_update; - - MeshManager(); - ~MeshManager(); - - bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress); - - /* attributes */ - void update_osl_attributes(Device *device, - Scene *scene, - vector<AttributeRequestSet> &mesh_attributes); - void update_svm_attributes(Device *device, - DeviceScene *dscene, - Scene *scene, - vector<AttributeRequestSet> &mesh_attributes); - - void device_update_preprocess(Device *device, Scene *scene, Progress &progress); - void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - - void device_free(Device *device, DeviceScene *dscene); - - void tag_update(Scene *scene); - - void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress); - - void collect_statistics(const Scene *scene, RenderStats *stats); - - protected: - /* Calculate verts/triangles/curves offsets in global arrays. */ - void mesh_calc_offset(Scene *scene); - - void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - - void device_update_mesh(Device *device, - DeviceScene *dscene, - Scene *scene, - bool for_displacement, - Progress &progress); - - void device_update_attributes(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress); - - void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - - void device_update_displacement_images(Device *device, Scene *scene, Progress &progress); - - void device_update_volume_images(Device *device, Scene *scene, Progress &progress); -}; - CCL_NAMESPACE_END #endif /* __MESH_H__ */ diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp index 6a6c2fbb3eb..467810f9273 100644 --- a/intern/cycles/render/mesh_displace.cpp +++ b/intern/cycles/render/mesh_displace.cpp @@ -43,7 +43,7 @@ static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts) return norm / normlen; } -bool MeshManager::displace( +bool GeometryManager::displace( Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress) { /* verify if we have a displacement shader */ @@ -58,7 +58,7 @@ bool MeshManager::displace( size_t object_index = OBJECT_NONE; for (size_t i = 0; i < scene->objects.size(); i++) { - if (scene->objects[i]->mesh == mesh) { + if (scene->objects[i]->geometry == mesh) { object_index = i; break; } @@ -91,7 +91,7 @@ bool MeshManager::displace( /* set up object, primitive and barycentric coordinates */ int object = object_index; - int prim = mesh->tri_offset + i; + int prim = mesh->prim_offset + i; float u, v; switch (j) { diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp index f451b58e92a..74c6a7759a6 100644 --- a/intern/cycles/render/mesh_volume.cpp +++ b/intern/cycles/render/mesh_volume.cpp @@ -362,7 +362,7 @@ struct VoxelAttributeGrid { int channels; }; -void MeshManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress) +void GeometryManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress) { string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str()); progress.set_status("Updating Mesh", msg); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 00f4a7283bb..75e21e00dcf 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -333,10 +333,10 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph) /* TODO(lukas): This is quite inefficient. A fairly simple improvement would * be to have a cache in each mesh that is indexed by attribute. * Additionally, building a graph-to-meshes list once could help. */ - foreach (Mesh *mesh, scene->meshes) { - foreach (Shader *shader, mesh->used_shaders) { + foreach (Geometry *geom, scene->geometry) { + foreach (Shader *shader, geom->used_shaders) { if (shader->graph == graph) { - mesh->get_uv_tiles(attribute, used_tiles); + geom->get_uv_tiles(attribute, used_tiles); } } } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 849329a086d..4987b6089d7 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -16,6 +16,7 @@ #include "render/camera.h" #include "device/device.h" +#include "render/hair.h" #include "render/light.h" #include "render/mesh.h" #include "render/curves.h" @@ -87,7 +88,7 @@ NODE_DEFINE(Object) { NodeType *type = NodeType::add("object", create); - SOCKET_NODE(mesh, "Mesh", &Mesh::node_type); + SOCKET_NODE(geometry, "Geometry", &Geometry::node_base_type); SOCKET_TRANSFORM(tfm, "Transform", transform_identity()); SOCKET_UINT(visibility, "Visibility", ~0); SOCKET_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); @@ -152,7 +153,7 @@ void Object::update_motion() void Object::compute_bounds(bool motion_blur) { - BoundBox mbounds = mesh->bounds; + BoundBox mbounds = geometry->bounds; if (motion_blur && use_motion()) { array<DecomposedTransform> decomp(motion.size()); @@ -172,7 +173,7 @@ void Object::compute_bounds(bool motion_blur) } else { /* No motion blur case. */ - if (mesh->transform_applied) { + if (geometry->transform_applied) { bounds = mbounds; } else { @@ -183,89 +184,18 @@ void Object::compute_bounds(bool motion_blur) void Object::apply_transform(bool apply_to_motion) { - if (!mesh || tfm == transform_identity()) + if (!geometry || tfm == transform_identity()) return; - /* triangles */ - if (mesh->verts.size()) { - /* store matrix to transform later. when accessing these as attributes we - * do not want the transform to be applied for consistency between static - * and dynamic BVH, so we do it on packing. */ - mesh->transform_normal = transform_transposed_inverse(tfm); - - /* apply to mesh vertices */ - for (size_t i = 0; i < mesh->verts.size(); i++) - mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); - - if (apply_to_motion) { - Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (attr) { - size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1); - float3 *vert_steps = attr->data_float3(); - - for (size_t i = 0; i < steps_size; i++) - vert_steps[i] = transform_point(&tfm, vert_steps[i]); - } - - Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); - - if (attr_N) { - Transform ntfm = mesh->transform_normal; - size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1); - float3 *normal_steps = attr_N->data_float3(); - - for (size_t i = 0; i < steps_size; i++) - normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i])); - } - } - } - - /* curves */ - if (mesh->curve_keys.size()) { - /* compute uniform scale */ - float3 c0 = transform_get_column(&tfm, 0); - float3 c1 = transform_get_column(&tfm, 1); - float3 c2 = transform_get_column(&tfm, 2); - float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f); - - /* apply transform to curve keys */ - for (size_t i = 0; i < mesh->curve_keys.size(); i++) { - float3 co = transform_point(&tfm, mesh->curve_keys[i]); - float radius = mesh->curve_radius[i] * scalar; - - /* scale for curve radius is only correct for uniform scale */ - mesh->curve_keys[i] = co; - mesh->curve_radius[i] = radius; - } - - if (apply_to_motion) { - Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (curve_attr) { - /* apply transform to motion curve keys */ - size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1); - float4 *key_steps = curve_attr->data_float4(); - - for (size_t i = 0; i < steps_size; i++) { - float3 co = transform_point(&tfm, float4_to_float3(key_steps[i])); - float radius = key_steps[i].w * scalar; - - /* scale for curve radius is only correct for uniform scale */ - key_steps[i] = float3_to_float4(co); - key_steps[i].w = radius; - } - } - } - } + geometry->apply_transform(tfm, apply_to_motion); /* we keep normals pointing in same direction on negative scale, notify - * mesh about this in it (re)calculates normals */ + * geometry about this in it (re)calculates normals */ if (transform_negative_scale(tfm)) - mesh->transform_negative_scaled = true; + geometry->transform_negative_scaled = true; if (bounds.valid()) { - mesh->compute_bounds(); + geometry->compute_bounds(); compute_bounds(false); } @@ -275,11 +205,11 @@ void Object::apply_transform(bool apply_to_motion) void Object::tag_update(Scene *scene) { - if (mesh) { - if (mesh->transform_applied) - mesh->need_update = true; + if (geometry) { + if (geometry->transform_applied) + geometry->need_update = true; - foreach (Shader *shader, mesh->used_shaders) { + foreach (Shader *shader, geometry->used_shaders) { if (shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; } @@ -287,7 +217,7 @@ void Object::tag_update(Scene *scene) scene->camera->need_flags_update = true; scene->curve_system_manager->need_update = true; - scene->mesh_manager->need_update = true; + scene->geometry_manager->need_update = true; scene->object_manager->need_update = true; } @@ -353,32 +283,22 @@ ObjectManager::~ObjectManager() { } -void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob) +static float object_surface_area(UpdateObjectTransformState *state, + const Transform &tfm, + Geometry *geom) { - KernelObject &kobject = state->objects[ob->index]; - Transform *object_motion_pass = state->object_motion_pass; - - Mesh *mesh = ob->mesh; - uint flag = 0; - - /* Compute transformations. */ - Transform tfm = ob->tfm; - Transform itfm = transform_inverse(tfm); + if (geom->type != Geometry::MESH) { + return 0.0f; + } /* Compute surface area. for uniform scale we can do avoid the many * transform calls and share computation for instances. * * TODO(brecht): Correct for displacement, and move to a better place. */ - float uniform_scale; + Mesh *mesh = static_cast<Mesh *>(geom); float surface_area = 0.0f; - float3 color = ob->color; - float pass_id = ob->pass_id; - float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF); - int particle_index = (ob->particle_system) ? - ob->particle_index + state->particle_offset[ob->particle_system] : - 0; - + float uniform_scale; if (transform_uniform_scale(tfm, uniform_scale)) { map<Mesh *, float>::iterator it; @@ -424,9 +344,31 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s } } + return surface_area; +} + +void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob) +{ + KernelObject &kobject = state->objects[ob->index]; + Transform *object_motion_pass = state->object_motion_pass; + + Geometry *geom = ob->geometry; + uint flag = 0; + + /* Compute transformations. */ + Transform tfm = ob->tfm; + Transform itfm = transform_inverse(tfm); + + float3 color = ob->color; + float pass_id = ob->pass_id; + float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF); + int particle_index = (ob->particle_system) ? + ob->particle_index + state->particle_offset[ob->particle_system] : + 0; + kobject.tfm = tfm; kobject.itfm = itfm; - kobject.surface_area = surface_area; + kobject.surface_area = object_surface_area(state, tfm, geom); kobject.color[0] = color.x; kobject.color[1] = color.y; kobject.color[2] = color.z; @@ -435,11 +377,16 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.particle_index = particle_index; kobject.motion_offset = 0; - if (mesh->use_motion_blur) { + if (geom->use_motion_blur) { state->have_motion = true; } - if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { - flag |= SD_OBJECT_HAS_VERTEX_MOTION; + + if (geom->type == Geometry::MESH) { + /* TODO: why only mesh? */ + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { + flag |= SD_OBJECT_HAS_VERTEX_MOTION; + } } if (state->need_motion == Scene::MOTION_PASS) { @@ -460,7 +407,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s /* Motion transformations, is world/object space depending if mesh * comes with deformed position in object space, or if we transform * the shading point in world space. */ - if (!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { + if (!(flag & SD_OBJECT_HAS_VERTEX_MOTION)) { tfm_pre = tfm_pre * itfm; tfm_post = tfm_post * itfm; } @@ -485,12 +432,13 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.dupli_generated[0] = ob->dupli_generated[0]; kobject.dupli_generated[1] = ob->dupli_generated[1]; kobject.dupli_generated[2] = ob->dupli_generated[2]; - kobject.numkeys = mesh->curve_keys.size(); + kobject.numkeys = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom)->curve_keys.size() : + 0; kobject.dupli_uv[0] = ob->dupli_uv[0]; kobject.dupli_uv[1] = ob->dupli_uv[1]; - int totalsteps = mesh->motion_steps; + int totalsteps = geom->motion_steps; kobject.numsteps = (totalsteps - 1) / 2; - kobject.numverts = mesh->verts.size(); + kobject.numverts = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom)->verts.size() : 0; kobject.patch_map_offset = 0; kobject.attribute_map_offset = 0; uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0); @@ -505,7 +453,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s state->object_flag[ob->index] = flag; /* Have curves. */ - if (mesh->num_curves()) { + if (geom->type == Geometry::HAIR) { state->have_curves = true; } } @@ -681,7 +629,7 @@ void ObjectManager::device_update_flags( vector<Object *> volume_objects; bool has_volume_objects = false; foreach (Object *object, scene->objects) { - if (object->mesh->has_volume) { + if (object->geometry->has_volume) { if (bounds_valid) { volume_objects.push_back(object); } @@ -690,11 +638,11 @@ void ObjectManager::device_update_flags( } foreach (Object *object, scene->objects) { - if (object->mesh->has_volume) { + if (object->geometry->has_volume) { object_flag[object->index] |= SD_OBJECT_HAS_VOLUME; object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES; - foreach (Attribute &attr, object->mesh->attributes.attributes) { + foreach (Attribute &attr, object->geometry->attributes.attributes) { if (attr.element == ATTR_ELEMENT_VOXEL) { object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES; } @@ -744,21 +692,24 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc bool update = false; foreach (Object *object, scene->objects) { - Mesh *mesh = object->mesh; - - if (mesh->patch_table) { - uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() - - mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - - mesh->patch_offset; - - if (kobjects[object->index].patch_map_offset != patch_map_offset) { - kobjects[object->index].patch_map_offset = patch_map_offset; - update = true; + Geometry *geom = object->geometry; + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->patch_table) { + uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() - + mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - + mesh->patch_offset; + + if (kobjects[object->index].patch_map_offset != patch_map_offset) { + kobjects[object->index].patch_map_offset = patch_map_offset; + update = true; + } } } - if (kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) { - kobjects[object->index].attribute_map_offset = mesh->attr_map_offset; + if (kobjects[object->index].attribute_map_offset != geom->attr_map_offset) { + kobjects[object->index].attribute_map_offset = geom->attr_map_offset; update = true; } } @@ -779,10 +730,10 @@ void ObjectManager::device_free(Device *, DeviceScene *dscene) void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) { /* todo: normals and displacement should be done before applying transform! */ - /* todo: create objects/meshes in right order! */ + /* todo: create objects/geometry in right order! */ - /* counter mesh users */ - map<Mesh *, int> mesh_users; + /* counter geometry users */ + map<Geometry *, int> geometry_users; Scene::MotionType need_motion = scene->need_motion(); bool motion_blur = need_motion == Scene::MOTION_BLUR; bool apply_to_motion = need_motion != Scene::MOTION_PASS; @@ -790,10 +741,10 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P bool have_instancing = false; foreach (Object *object, scene->objects) { - map<Mesh *, int>::iterator it = mesh_users.find(object->mesh); + map<Geometry *, int>::iterator it = geometry_users.find(object->geometry); - if (it == mesh_users.end()) - mesh_users[object->mesh] = 1; + if (it == geometry_users.end()) + geometry_users[object->geometry] = 1; else it->second++; } @@ -803,27 +754,34 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P uint *object_flag = dscene->object_flag.data(); - /* apply transforms for objects with single user meshes */ + /* apply transforms for objects with single user geometry */ foreach (Object *object, scene->objects) { /* Annoying feedback loop here: we can't use is_instanced() because * it'll use uninitialized transform_applied flag. * - * Could be solved by moving reference counter to Mesh. + * Could be solved by moving reference counter to Geometry. */ - if ((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) && - !object->mesh->has_true_displacement() && - object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { + Geometry *geom = object->geometry; + bool apply = (geometry_users[geom] == 1) && !geom->has_surface_bssrdf && + !geom->has_true_displacement(); + + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); + apply = apply && mesh->subdivision_type == Mesh::SUBDIVISION_NONE; + } + + if (apply) { if (!(motion_blur && object->use_motion())) { - if (!object->mesh->transform_applied) { + if (!geom->transform_applied) { object->apply_transform(apply_to_motion); - object->mesh->transform_applied = true; + geom->transform_applied = true; if (progress.get_cancel()) return; } object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED; - if (object->mesh->transform_negative_scaled) + if (geom->transform_negative_scaled) object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED; } else @@ -842,7 +800,7 @@ void ObjectManager::tag_update(Scene *scene) { need_update = true; scene->curve_system_manager->need_update = true; - scene->mesh_manager->need_update = true; + scene->geometry_manager->need_update = true; scene->light_manager->need_update = true; } diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index cbbff0d4c6d..c5d878ec938 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -32,7 +32,7 @@ CCL_NAMESPACE_BEGIN class Device; class DeviceScene; -class Mesh; +class Geometry; class ParticleSystem; class Progress; class Scene; @@ -46,7 +46,7 @@ class Object : public Node { public: NODE_DECLARE - Mesh *mesh; + Geometry *geometry; Transform tfm; BoundBox bounds; uint random_id; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 1e75fa0f99b..24469620840 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -94,7 +94,7 @@ Scene::Scene(const SceneParams ¶ms_, Device *device) film = new Film(); background = new Background(); light_manager = new LightManager(); - mesh_manager = new MeshManager(); + geometry_manager = new GeometryManager(); object_manager = new ObjectManager(); integrator = new Integrator(); image_manager = new ImageManager(device->info); @@ -118,8 +118,8 @@ void Scene::free_memory(bool final) { foreach (Shader *s, shaders) delete s; - foreach (Mesh *m, meshes) - delete m; + foreach (Geometry *g, geometry) + delete g; foreach (Object *o, objects) delete o; foreach (Light *l, lights) @@ -128,7 +128,7 @@ void Scene::free_memory(bool final) delete p; shaders.clear(); - meshes.clear(); + geometry.clear(); objects.clear(); lights.clear(); particle_systems.clear(); @@ -140,7 +140,7 @@ void Scene::free_memory(bool final) integrator->device_free(device, &dscene); object_manager->device_free(device, &dscene); - mesh_manager->device_free(device, &dscene); + geometry_manager->device_free(device, &dscene); shader_manager->device_free(device, &dscene, this); light_manager->device_free(device, &dscene); @@ -165,7 +165,7 @@ void Scene::free_memory(bool final) delete background; delete integrator; delete object_manager; - delete mesh_manager; + delete geometry_manager; delete shader_manager; delete light_manager; delete particle_system_manager; @@ -211,7 +211,7 @@ void Scene::device_update(Device *device_, Progress &progress) if (progress.get_cancel() || device->have_error()) return; - mesh_manager->device_update_preprocess(device, this, progress); + geometry_manager->device_update_preprocess(device, this, progress); if (progress.get_cancel() || device->have_error()) return; @@ -235,7 +235,7 @@ void Scene::device_update(Device *device_, Progress &progress) return; progress.set_status("Updating Meshes"); - mesh_manager->device_update(device, &dscene, this, progress); + geometry_manager->device_update(device, &dscene, this, progress); if (progress.get_cancel() || device->have_error()) return; @@ -356,8 +356,8 @@ bool Scene::need_update() bool Scene::need_data_update() { return (background->need_update || image_manager->need_update || object_manager->need_update || - mesh_manager->need_update || light_manager->need_update || lookup_tables->need_update || - integrator->need_update || shader_manager->need_update || + geometry_manager->need_update || light_manager->need_update || + lookup_tables->need_update || integrator->need_update || shader_manager->need_update || particle_system_manager->need_update || curve_system_manager->need_update || bake_manager->need_update || film->need_update); } @@ -379,7 +379,7 @@ void Scene::reset() background->tag_update(this); integrator->tag_update(this); object_manager->tag_update(this); - mesh_manager->tag_update(this); + geometry_manager->tag_update(this); light_manager->tag_update(this); particle_system_manager->tag_update(this); curve_system_manager->tag_update(this); @@ -392,7 +392,7 @@ void Scene::device_free() void Scene::collect_statistics(RenderStats *stats) { - mesh_manager->collect_statistics(this, stats); + geometry_manager->collect_statistics(this, stats); image_manager->collect_statistics(stats); } diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index f99510d2d42..ab30aaa1f43 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -44,8 +44,8 @@ class Integrator; class Light; class LightManager; class LookupTables; -class Mesh; -class MeshManager; +class Geometry; +class GeometryManager; class Object; class ObjectManager; class ParticleSystemManager; @@ -213,7 +213,7 @@ class Scene { /* data lists */ vector<Object *> objects; - vector<Mesh *> meshes; + vector<Geometry *> geometry; vector<Shader *> shaders; vector<Light *> lights; vector<ParticleSystem *> particle_systems; @@ -222,7 +222,7 @@ class Scene { ImageManager *image_manager; LightManager *light_manager; ShaderManager *shader_manager; - MeshManager *mesh_manager; + GeometryManager *geometry_manager; ObjectManager *object_manager; ParticleSystemManager *particle_system_manager; CurveSystemManager *curve_system_manager; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index c77a20787f5..dac7fbac806 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -701,23 +701,26 @@ DeviceRequestedFeatures Session::get_requested_device_features() requested_features.use_object_motion = false; requested_features.use_camera_motion = use_motion && scene->camera->use_motion(); foreach (Object *object, scene->objects) { - Mesh *mesh = object->mesh; - if (mesh->num_curves()) { - requested_features.use_hair = true; - } + Geometry *geom = object->geometry; if (use_motion) { - requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur; - requested_features.use_camera_motion |= mesh->use_motion_blur; - } -#ifdef WITH_OPENSUBDIV - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { - requested_features.use_patch_evaluation = true; + requested_features.use_object_motion |= object->use_motion() | geom->use_motion_blur; + requested_features.use_camera_motion |= geom->use_motion_blur; } -#endif if (object->is_shadow_catcher) { requested_features.use_shadow_tricks = true; } - requested_features.use_true_displacement |= mesh->has_true_displacement(); + if (geom->type == Geometry::MESH) { + Mesh *mesh = static_cast<Mesh *>(geom); +#ifdef WITH_OPENSUBDIV + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + requested_features.use_patch_evaluation = true; + } +#endif + requested_features.use_true_displacement |= mesh->has_true_displacement(); + } + else if (geom->type == Geometry::HAIR) { + requested_features.use_hair = true; + } } requested_features.use_background_light = scene->light_manager->has_background_light(scene); diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 661208c6463..60f38aa14da 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -214,7 +214,7 @@ Shader::Shader() : Node(node_type) used = false; need_update = true; - need_update_mesh = true; + need_update_geometry = true; need_sync_object = false; } @@ -288,7 +288,7 @@ void Shader::set_graph(ShaderGraph *graph_) const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : ""; if (strcmp(old_hash, new_hash) != 0) { - need_update_mesh = true; + need_update_geometry = true; } } @@ -347,14 +347,14 @@ void Shader::tag_update(Scene *scene) } /* compare if the attributes changed, mesh manager will check - * need_update_mesh, update the relevant meshes and clear it. */ + * need_update_geometry, update the relevant meshes and clear it. */ if (attributes.modified(prev_attributes)) { - need_update_mesh = true; - scene->mesh_manager->need_update = true; + need_update_geometry = true; + scene->geometry_manager->need_update = true; } if (has_volume != prev_has_volume) { - scene->mesh_manager->need_flags_update = true; + scene->geometry_manager->need_flags_update = true; scene->object_manager->need_flags_update = true; } } @@ -489,8 +489,8 @@ void ShaderManager::device_update_shaders_used(Scene *scene) if (scene->background->shader) scene->background->shader->used = true; - foreach (Mesh *mesh, scene->meshes) - foreach (Shader *shader, mesh->used_shaders) + foreach (Geometry *geom, scene->geometry) + foreach (Shader *shader, geom->used_shaders) shader->used = true; foreach (Light *light, scene->lights) diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index f74204df355..c6f40bb7833 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -95,7 +95,7 @@ class Shader : public Node { /* synchronization */ bool need_update; - bool need_update_mesh; + bool need_update_geometry; bool need_sync_object; /* If the shader has only volume components, the surface is assumed to diff --git a/intern/mantaflow/CMakeLists.txt b/intern/mantaflow/CMakeLists.txt index c7b3c56c3c2..2d49f96a451 100644 --- a/intern/mantaflow/CMakeLists.txt +++ b/intern/mantaflow/CMakeLists.txt @@ -27,6 +27,7 @@ add_definitions(-DWITH_FLUID=1) if(WITH_OPENVDB) add_definitions(-DOPENVDB=1) + add_definitions(-DOPENVDB_STATICLIB) endif() set(INC @@ -47,6 +48,35 @@ set(INC_SYS ${ZLIB_INCLUDE_DIRS} ) +if(WITH_TBB) + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + +if(WITH_OPENVDB) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ${OPENEXR_INCLUDE_DIRS} + ${OPENVDB_INCLUDE_DIRS} + ) + list(APPEND LIB + ${OPENVDB_LIBRARIES} + ${OPENEXR_LIBRARIES} + ${ZLIB_LIBRARIES} + ${BOOST_LIBRARIES} + ) + if(WITH_OPENVDB_BLOSC) + list(APPEND LIB + ${BLOSC_LIBRARIES} + ${ZLIB_LIBRARIES} + ) + endif() +endif() + set(SRC intern/manta_python_API.cpp intern/manta_fluid_API.cpp diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h index 8dc2cf1805a..4ebedeb5e38 100644 --- a/intern/mantaflow/extern/manta_fluid_API.h +++ b/intern/mantaflow/extern/manta_fluid_API.h @@ -55,6 +55,8 @@ int manta_update_mesh_structures(struct MANTA *fluid, struct FluidModifierData * int manta_update_particle_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); +int manta_update_smoke_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); +int manta_update_noise_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_data(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index 7f6ff9094c6..2cbf058d8de 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -27,6 +27,10 @@ #include <iomanip> #include <zlib.h> +#if OPENVDB == 1 +# include "openvdb/openvdb.h" +#endif + #include "MANTA_main.h" #include "manta.h" #include "Python.h" @@ -1168,6 +1172,244 @@ int MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) return 1; } +int MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) +{ + if (MANTA::with_debug) + std::cout << "MANTA::updateGridStructures()" << std::endl; + + mSmokeFromFile = false; + + if (!mUsingSmoke) + return 0; + if (BLI_path_is_rel(mmd->domain->cache_directory)) + return 0; + + int result = 0; + int expected = 0; /* Expected number of read successes for this frame. */ + + std::ostringstream ss; + char cacheDir[FILE_MAX], targetFile[FILE_MAX]; + cacheDir[0] = '\0'; + targetFile[0] = '\0'; + + std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + BLI_path_join( + cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); + + expected += 1; + ss.str(""); + ss << "density_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mDensity); + + expected += 1; + ss.str(""); + ss << "shadow_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mShadow); + + if (mUsingHeat) { + expected += 1; + ss.str(""); + ss << "heat_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mHeat); + } + + if (mUsingColors) { + expected += 3; + ss.str(""); + ss << "color_r_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorR); + + ss.str(""); + ss << "color_g_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorG); + + ss.str(""); + ss << "color_b_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorB); + } + + if (mUsingFire) { + expected += 3; + ss.str(""); + ss << "flame_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mFlame); + + ss.str(""); + ss << "fuel_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mFuel); + + ss.str(""); + ss << "react_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mReact); + } + + mSmokeFromFile = true; + return (result == expected) ? 1 : 0; +} + +int MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) +{ + if (MANTA::with_debug) + std::cout << "MANTA::updateNoiseStructures()" << std::endl; + + mNoiseFromFile = false; + + if (!mUsingSmoke || !mUsingNoise) + return 0; + if (BLI_path_is_rel(mmd->domain->cache_directory)) + return 0; + + int result = 0; + int expected = 0; /* Expected number of read successes for this frame. */ + + std::ostringstream ss; + char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX], targetFile[FILE_MAX]; + cacheDirData[0] = '\0'; + cacheDirNoise[0] = '\0'; + targetFile[0] = '\0'; + + std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + BLI_path_join(cacheDirData, + sizeof(cacheDirData), + mmd->domain->cache_directory, + FLUID_DOMAIN_DIR_DATA, + nullptr); + BLI_path_join(cacheDirNoise, + sizeof(cacheDirNoise), + mmd->domain->cache_directory, + FLUID_DOMAIN_DIR_NOISE, + nullptr); + + expected += 1; + ss.str(""); + ss << "density_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mDensityHigh); + + expected += 1; + ss.str(""); + ss << "shadow_####" << dformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirData, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mShadow); + + if (mUsingColors) { + expected += 3; + ss.str(""); + ss << "color_r_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorRHigh); + + ss.str(""); + ss << "color_g_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorGHigh); + + ss.str(""); + ss << "color_b_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mColorBHigh); + } + + if (mUsingFire) { + expected += 3; + ss.str(""); + ss << "flame_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mFlameHigh); + + ss.str(""); + ss << "fuel_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mFuelHigh); + + ss.str(""); + ss << "react_noise_####" << nformat; + BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str()); + BLI_path_frame(targetFile, framenr, 0); + if (!BLI_exists(targetFile)) { + return 0; + } + result += updateGridFromFile(targetFile, mReactHigh); + } + + mNoiseFromFile = true; + return (result == expected) ? 1 : 0; +} + /* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */ static std::string escapeSlashes(std::string const &s) { @@ -1194,7 +1436,7 @@ int MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) cacheDir[0] = '\0'; targetFile[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + std::string dformat = ".uni"; BLI_path_join( cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_CONFIG, nullptr); @@ -1287,7 +1529,7 @@ int MANTA::readConfiguration(FluidModifierData *mmd, int framenr) targetFile[0] = '\0'; float dummy; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + std::string dformat = ".uni"; BLI_path_join( cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_CONFIG, nullptr); @@ -1932,6 +2174,7 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) bool floater = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; bool tracer = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS; bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; @@ -1968,6 +2211,8 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) manta_script += fluid_alloc_guiding; if (obstacle) manta_script += fluid_alloc_obstacle; + if (fractions) + manta_script += fluid_alloc_fractions; if (invel) manta_script += fluid_alloc_invel; @@ -2533,6 +2778,179 @@ void MANTA::updateParticlesFromUni(const char *filename, bool isSecondarySys, bo gzclose(gzf); } +int MANTA::updateGridFromFile(const char *filename, float *grid) +{ + if (with_debug) + std::cout << "MANTA::updateGridFromFile()" << std::endl; + + if (!grid) { + std::cout << "MANTA::updateGridFromFile(): cannot read into uninitialized grid, grid is null" + << std::endl; + return 0; + } + + std::string fname(filename); + std::string::size_type idx; + + idx = fname.rfind('.'); + if (idx != std::string::npos) { + std::string extension = fname.substr(idx + 1); + + if (extension.compare("uni") == 0) + return updateGridFromUni(filename, grid); +#ifdef WITH_OPENVDB + else if (extension.compare("vdb") == 0) + return updateGridFromVDB(filename, grid); +#endif + else if (extension.compare("raw") == 0) + return updateGridFromRaw(filename, grid); + else + std::cerr << "MANTA::updateGridFromFile(): invalid file extension in file: " << filename + << std::endl; + return 0; + } + else { + std::cerr << "MANTA::updateGridFromFile(): unable to open file: " << filename << std::endl; + return 0; + } +} + +int MANTA::updateGridFromUni(const char *filename, float *grid) +{ + if (with_debug) + std::cout << "MANTA::updateGridFromUni()" << std::endl; + + gzFile gzf; + int ibuffer[4]; + + gzf = (gzFile)BLI_gzopen(filename, "rb1"); + if (!gzf) { + std::cout << "MANTA::updateGridFromUni(): unable to open file" << std::endl; + return 0; + } + + char ID[5] = {0, 0, 0, 0, 0}; + gzread(gzf, ID, 4); + + if (!strcmp(ID, "DDF2")) { + std::cout << "MANTA::updateGridFromUni(): grid uni file format DDF2 not supported anymore" + << std::endl; + return 0; + } + if (!strcmp(ID, "MNT1")) { + std::cout << "MANTA::updateGridFromUni(): grid uni file format MNT1 not supported anymore" + << std::endl; + return 0; + } + if (!strcmp(ID, "MNT2")) { + std::cout << "MANTA::updateGridFromUni(): grid uni file format MNT2 not supported anymore" + << std::endl; + return 0; + } + + // grid uni header + const int STR_LEN_GRID = 252; + int elementType, bytesPerElement; // data type info + char info[STR_LEN_GRID]; // mantaflow build information + int dimT; // optionally store forth dimension for 4d grids + unsigned long long timestamp; // creation time + + // read grid header + gzread(gzf, &ibuffer, sizeof(int) * 4); // dimX, dimY, dimZ, gridType + gzread(gzf, &elementType, sizeof(int)); + gzread(gzf, &bytesPerElement, sizeof(int)); + gzread(gzf, &info, sizeof(info)); + gzread(gzf, &dimT, sizeof(int)); + gzread(gzf, ×tamp, sizeof(unsigned long long)); + + if (with_debug) + std::cout << "read " << ibuffer[3] << " grid type in file: " << filename << std::endl; + + // Sanity checks + if (ibuffer[0] != mResX || ibuffer[1] != mResY || ibuffer[2] != mResZ) { + std::cout << "grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] << ", " + << ibuffer[2] << ") vs setup: (" << mResX << ", " << mResY << ", " << mResZ << ")" + << std::endl; + return 0; + } + + // Actual data reading + if (!strcmp(ID, "MNT3")) { + gzread(gzf, grid, sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]); + } + + if (with_debug) + std::cout << "read successfully: " << filename << std::endl; + + gzclose(gzf); + return 1; +} + +#ifdef WITH_OPENVDB +int MANTA::updateGridFromVDB(const char *filename, float *grid) +{ + if (with_debug) + std::cout << "MANTA::updateGridFromVDB()" << std::endl; + + openvdb::initialize(); + openvdb::io::File file(filename); + try { + file.open(); + } + catch (const openvdb::IoError &) { + std::cout << "MANTA::updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename + << std::endl; + return 0; + } + + openvdb::GridBase::Ptr baseGrid; + for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName(); + ++nameIter) { + baseGrid = file.readGrid(nameIter.gridName()); + break; + } + file.close(); + openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid); + openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor(); + + size_t index = 0; + for (int z = 0; z < mResZ; ++z) { + for (int y = 0; y < mResY; ++y) { + for (int x = 0; x < mResX; ++x, ++index) { + openvdb::Coord xyz(x, y, z); + float v = accessor.getValue(xyz); + grid[index] = v; + } + } + } + return 1; +} +#endif + +int MANTA::updateGridFromRaw(const char *filename, float *grid) +{ + if (with_debug) + std::cout << "MANTA::updateGridFromRaw()" << std::endl; + + gzFile gzf; + int expectedBytes, readBytes; + + gzf = (gzFile)BLI_gzopen(filename, "rb"); + if (!gzf) { + std::cout << "MANTA::updateGridFromRaw(): unable to open file" << std::endl; + return 0; + } + + expectedBytes = sizeof(float) * mResX * mResY * mResZ; + readBytes = gzread(gzf, grid, expectedBytes); + + assert(expectedBytes == readBytes); + (void)readBytes; // Unused in release. + + gzclose(gzf); + return 1; +} + void MANTA::updatePointers() { if (with_debug) @@ -2660,7 +3078,9 @@ void MANTA::updatePointers() callPythonFunction("pLifeSnd" + parts_ext, func)); } - mFlipFromFile = true; + mFlipFromFile = false; mMeshFromFile = false; mParticlesFromFile = false; + mSmokeFromFile = false; + mNoiseFromFile = false; } diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index f8d94e2631c..c1c2c042a73 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -93,6 +93,8 @@ struct MANTA { int updateMeshStructures(FluidModifierData *mmd, int framenr); int updateFlipStructures(FluidModifierData *mmd, int framenr); int updateParticleStructures(FluidModifierData *mmd, int framenr); + int updateSmokeStructures(FluidModifierData *mmd, int framenr); + int updateNoiseStructures(FluidModifierData *mmd, int framenr); void updateVariables(FluidModifierData *mmd); // Bake cache @@ -742,6 +744,8 @@ struct MANTA { bool mFlipFromFile; bool mMeshFromFile; bool mParticlesFromFile; + bool mSmokeFromFile; + bool mNoiseFromFile; int mResX; int mResY; @@ -852,8 +856,12 @@ struct MANTA { void updateMeshFromObj(const char *filename); void updateMeshFromUni(const char *filename); void updateParticlesFromUni(const char *filename, bool isSecondarySys, bool isVelData); + int updateGridFromUni(const char *filename, float *grid); + int updateGridFromVDB(const char *filename, float *grid); + int updateGridFromRaw(const char *filename, float *grid); void updateMeshFromFile(const char *filename); void updateParticlesFromFile(const char *filename, bool isSecondarySys, bool isVelData); + int updateGridFromFile(const char *filename, float *grid); }; #endif diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp index 35f2ebbaf44..82bfed7cf61 100644 --- a/intern/mantaflow/intern/manta_fluid_API.cpp +++ b/intern/mantaflow/intern/manta_fluid_API.cpp @@ -143,6 +143,20 @@ int manta_update_particle_structures(MANTA *fluid, FluidModifierData *mmd, int f return fluid->updateParticleStructures(mmd, framenr); } +int manta_update_smoke_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) +{ + if (!fluid || !mmd) + return 0; + return fluid->updateSmokeStructures(mmd, framenr); +} + +int manta_update_noise_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) +{ + if (!fluid || !mmd) + return 0; + return fluid->updateNoiseStructures(mmd, framenr); +} + int manta_bake_data(MANTA *fluid, FluidModifierData *mmd, int framenr) { if (!fluid || !mmd) diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index 442b09b5a8a..9a494a1cb6a 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -181,7 +181,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\ phi_s$ID$.join(phiIn_s$ID$)\n\ \n\ if using_obstacle_s$ID$:\n\ - phi_s$ID$.subtract(phiObsIn_s$ID$)\n\ + phi_s$ID$.subtract(o=phiObsIn_s$ID$, flags=flags_s$ID$, subtractType=FlagObstacle)\n\ \n\ if using_outflow_s$ID$:\n\ phiOut_s$ID$.join(phiOutIn_s$ID$)\n\ diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 74afb3ed35e3271b2609feaf67bea6b8bdffe7c +Subproject 34d98762cef85b9c065f21a051d1dbe3bf2979b diff --git a/release/scripts/addons b/release/scripts/addons -Subproject ad6928706de2fa8f44fa35a275453c716d65e77 +Subproject cbcf507f3045e867c4b2d8e0976b76e1753dc49 diff --git a/release/scripts/presets/keyconfig/blender.py b/release/scripts/presets/keyconfig/blender.py index 11cd76335f1..73be645d037 100644 --- a/release/scripts/presets/keyconfig/blender.py +++ b/release/scripts/presets/keyconfig/blender.py @@ -108,6 +108,38 @@ class Prefs(bpy.types.KeyConfigPreferences): update=update_fn, ) + v3d_mmb_action: EnumProperty( + name="MMB Action", + items=( + ('ORBIT', "Orbit", + "Orbit", + 0), + ('PAN', "Pan", + "Set the view axis where each mouse direction always maps to the same axis", + 1), + ), + description=( + "The action when Middle-Mouse dragging in the viewport. Shift-Middle-Mouse is used for the other action" + ), + update=update_fn, + ) + + v3d_alt_mmb_drag_action: EnumProperty( + name="Alt-MMB Drag Action", + items=( + ('RELATIVE', "Relative", + "Set the view axis where each mouse direction maps to an axis relative to the current orientation", + 0), + ('ABSOLUTE', "Absolute", + "Set the view axis where each mouse direction always maps to the same axis", + 1), + ), + description=( + "Action when Alt-MMB dragging in the 3D viewport" + ), + update=update_fn, + ) + # Developer note, this is an experemental option. use_pie_click_drag: BoolProperty( name="Pie Menu on Drag", @@ -149,10 +181,14 @@ class Prefs(bpy.types.KeyConfigPreferences): col = split.column() col.prop(self, "use_v3d_tab_menu") col.prop(self, "use_pie_click_drag") + col.prop(self, "use_v3d_shade_ex_pie") col = split.column() col.label(text="Tilde Action:") col.row().prop(self, "v3d_tilde_action", expand=True) - col.prop(self, "use_v3d_shade_ex_pie") + col.label(text="Middle Mouse Action:") + col.row().prop(self, "v3d_mmb_action", expand=True) + col.label(text="Alt Middle Mouse Drag Action:") + col.row().prop(self, "v3d_alt_mmb_drag_action", expand=True) blender_default = bpy.utils.execfile(os.path.join(DIRNAME, "keymap_data", "blender_default.py")) @@ -176,6 +212,8 @@ def load(): ), spacebar_action=kc_prefs.spacebar_action, v3d_tilde_action=kc_prefs.v3d_tilde_action, + use_v3d_mmb_pan=(kc_prefs.v3d_mmb_action == 'PAN'), + v3d_alt_mmb_drag_action=kc_prefs.v3d_alt_mmb_drag_action, use_select_all_toggle=kc_prefs.use_select_all_toggle, use_v3d_tab_menu=kc_prefs.use_v3d_tab_menu, use_v3d_shade_ex_pie=kc_prefs.use_v3d_shade_ex_pie, diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 5a64f4470e1..89ac155b79c 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -50,9 +50,13 @@ class Params: "use_v3d_tab_menu", # Use extended pie menu for shading. "use_v3d_shade_ex_pie", + # Swap orbit/pan keys (for 2D workflows). + "use_v3d_mmb_pan", # Experimental option. "use_pie_click_drag", "v3d_tilde_action", + # Alt-MMB axis switching 'RELATIVE' or 'ABSOLUTE' axis switching. + "v3d_alt_mmb_drag_action", ) def __init__( @@ -68,8 +72,10 @@ class Params: use_gizmo_drag=True, use_v3d_tab_menu=False, use_v3d_shade_ex_pie=False, + use_v3d_mmb_pan=False, use_pie_click_drag=False, v3d_tilde_action='VIEW', + v3d_alt_mmb_drag_action='RELATIVE', ): from sys import platform self.apple = (platform == 'darwin') @@ -116,7 +122,9 @@ class Params: self.use_select_all_toggle = use_select_all_toggle self.use_v3d_tab_menu = use_v3d_tab_menu self.use_v3d_shade_ex_pie = use_v3d_shade_ex_pie + self.use_v3d_mmb_pan = use_v3d_mmb_pan self.v3d_tilde_action = v3d_tilde_action + self.v3d_alt_mmb_drag_action = v3d_alt_mmb_drag_action self.use_pie_click_drag = use_pie_click_drag if not use_pie_click_drag: @@ -945,8 +953,13 @@ def km_view3d(params): ("view3d.localview", {"type": 'MOUSESMARTZOOM', "value": 'ANY'}, None), ("view3d.localview_remove_from", {"type": 'M', "value": 'PRESS'}, None), # Navigation. - ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None), - ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None), + *(( + ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None), + ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None), + ) if params.use_v3d_mmb_pan else ( + ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None), + ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None), + )), ("view3d.zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None), ("view3d.dolly", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("view3d.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS', "ctrl": True}, @@ -1043,14 +1056,25 @@ def km_view3d(params): {"properties": [("type", 'LEFT'), ("align_active", True)]}), ("view3d.view_axis", {"type": 'NUMPAD_7', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("type", 'BOTTOM'), ("align_active", True)]}), - ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True}, - {"properties": [("type", 'TOP'), ("relative", True)]}), - ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True}, - {"properties": [("type", 'BOTTOM'), ("relative", True)]}), - ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True}, - {"properties": [("type", 'RIGHT'), ("relative", True)]}), - ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True}, - {"properties": [("type", 'LEFT'), ("relative", True)]}), + *(( + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True}, + {"properties": [("type", 'TOP'), ("relative", True)]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True}, + {"properties": [("type", 'BOTTOM'), ("relative", True)]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True}, + {"properties": [("type", 'RIGHT'), ("relative", True)]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True}, + {"properties": [("type", 'LEFT'), ("relative", True)]}), + ) if params.v3d_alt_mmb_drag_action == 'RELATIVE' else ( + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True}, + {"properties": [("type", 'TOP')]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True}, + {"properties": [("type", 'BOTTOM')]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True}, + {"properties": [("type", 'RIGHT')]}), + ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True}, + {"properties": [("type", 'LEFT')]}), + )), ("view3d.view_center_pick", {"type": 'MIDDLEMOUSE', "value": 'CLICK', "alt": True}, None), ("view3d.ndof_orbit_zoom", {"type": 'NDOF_MOTION', "value": 'ANY'}, None), ("view3d.ndof_orbit", {"type": 'NDOF_MOTION', "value": 'ANY', "ctrl": True}, None), diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 28c9895f53b..cdd6a31aeda 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -680,7 +680,7 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel): domain = context.fluid.domain_settings # Deactivate UI if guides are enabled but not baked yet. - layout.active = domain.use_noise and not self.check_domain_has_unbaked_guide(domain) + layout.enabled = domain.use_noise and not self.check_domain_has_unbaked_guide(domain) is_baking_any = domain.is_cache_baking_any has_baked_noise = domain.has_cache_baked_noise @@ -746,7 +746,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel): domain = context.fluid.domain_settings # Deactivate UI if guides are enabled but not baked yet. - layout.active = domain.use_mesh and not self.check_domain_has_unbaked_guide(domain) + layout.enabled = domain.use_mesh and not self.check_domain_has_unbaked_guide(domain) is_baking_any = domain.is_cache_baking_any has_baked_mesh = domain.has_cache_baked_mesh @@ -818,7 +818,7 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel): domain = context.fluid.domain_settings # Deactivate UI if guides are enabled but not baked yet. - layout.active = not self.check_domain_has_unbaked_guide(domain) + layout.enabled = not self.check_domain_has_unbaked_guide(domain) is_baking_any = domain.is_cache_baking_any has_baked_particles = domain.has_cache_baked_particles @@ -1072,7 +1072,10 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): domain = context.fluid.domain_settings is_baking_any = domain.is_cache_baking_any - has_baked_any = domain.has_cache_baked_any + has_baked_data = domain.has_cache_baked_data + has_baked_noise = domain.has_cache_baked_noise + has_baked_mesh = domain.has_cache_baked_mesh + has_baked_particles = domain.has_cache_baked_particles col = layout.column() col.prop(domain, "cache_directory", text="") @@ -1096,18 +1099,24 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): col.separator() col = flow.column() - col.enabled = not is_baking_any and not has_baked_any + col.enabled = not is_baking_any and not has_baked_data col.prop(domain, "cache_data_format", text="Data File Format") if md.domain_settings.domain_type in {'GAS'}: if domain.use_noise: + col = flow.column() + col.enabled = not is_baking_any and not has_baked_noise col.prop(domain, "cache_noise_format", text="Noise File Format") if md.domain_settings.domain_type in {'LIQUID'}: # File format for all particle systemes (FLIP and secondary) + col = flow.column() + col.enabled = not is_baking_any and not has_baked_particles col.prop(domain, "cache_particle_format", text="Particle File Format") if domain.use_mesh: + col = flow.column() + col.enabled = not is_baking_any and not has_baked_mesh col.prop(domain, "cache_mesh_format", text="Mesh File Format") if domain.cache_type == 'FINAL': @@ -1132,7 +1141,8 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): - if not PhysicButtonsPanel.poll_fluid_domain(context): + # Only show the advanced panel to advanced users who know Mantaflow's birthday :) + if not PhysicButtonsPanel.poll_fluid_domain(context) or bpy.app.debug_value != 3001: return False return (context.engine in cls.COMPAT_ENGINES) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 405b052f477..d389b557503 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -87,7 +87,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt); void fcurve_free_driver(struct FCurve *fcu); struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); -void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list); +void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars); void BKE_driver_target_matrix_to_rot_channels( float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); @@ -280,7 +280,7 @@ struct FCurve *rna_get_fcurve_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, - struct AnimData **r_adt, + struct AnimData **r_animdata, struct bAction **r_action, bool *r_driven, bool *r_special); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 65c3725d994..93840db49c9 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -77,6 +77,7 @@ typedef struct Global { * * 799: Enable some mysterious new depsgraph behavior (05/2015). * * 1112: Disable new Cloth internal springs handling (09/2014). * * 1234: Disable new dyntopo code fixing skinny faces generation (04/2015). + * * 3001: Enable additional Fluid modifier (Mantaflow) options (02/2020). * * 16384 and above: Reserved for python (add-ons) usage. */ short debug_value; diff --git a/source/blender/blenkernel/BKE_library_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h index 0285699dea3..d95f32b162a 100644 --- a/source/blender/blenkernel/BKE_library_idmap.h +++ b/source/blender/blenkernel/BKE_main_idmap.h @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_LIBRARY_IDMAP_H__ -#define __BKE_LIBRARY_IDMAP_H__ +#ifndef __BKE_MAIN_IDMAP_H__ +#define __BKE_MAIN_IDMAP_H__ /** \file * \ingroup bke @@ -42,4 +42,4 @@ struct ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_typemap, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); -#endif /* __BKE_LIBRARY_IDMAP_H__ */ +#endif /* __BKE_MAIN_IDMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 570541eb990..d6934e8a7da 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -91,9 +91,7 @@ struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap( float (*vertexCos)[3], const struct Mesh *me_settings); -int poly_find_loop_from_vert(const struct MPoly *poly, - const struct MLoop *loopstart, - unsigned vert); +int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert); int poly_get_adj_loops_from_vert(const struct MPoly *poly, const struct MLoop *mloop, unsigned int vert, diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b599e1e1b2c..1c479c92ef5 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -387,7 +387,8 @@ struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntre void ntreeUserIncrefID(struct bNodeTree *ntree); void ntreeUserDecrefID(struct bNodeTree *ntree); -struct bNodeTree *ntreeFromID(const struct ID *id); +struct bNodeTree **BKE_ntree_ptr_from_id(struct ID *id); +struct bNodeTree *ntreeFromID(struct ID *id); struct ID *BKE_node_tree_find_owner_ID(struct Main *bmain, struct bNodeTree *ntree); void ntreeMakeLocal(struct Main *bmain, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index dd7931cfe0e..b7bb8434613 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -204,10 +204,7 @@ bool paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, in bool paint_is_bmesh_face_hidden(struct BMFace *f); /* paint masks */ -float paint_grid_paint_mask(const struct GridPaintMask *gpm, - unsigned level, - unsigned x, - unsigned y); +float paint_grid_paint_mask(const struct GridPaintMask *gpm, uint level, uint x, uint y); /* stroke related */ bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0aa4f0fe677..2f839aafa2c 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -136,7 +136,6 @@ set(SRC intern/layer.c intern/layer_utils.c intern/library.c - intern/library_idmap.c intern/library_override.c intern/library_query.c intern/library_remap.c @@ -144,6 +143,7 @@ set(SRC intern/lightprobe.c intern/linestyle.c intern/main.c + intern/main_idmap.c intern/mask.c intern/mask_evaluate.c intern/mask_rasterize.c @@ -299,7 +299,6 @@ set(SRC BKE_lattice.h BKE_layer.h BKE_library.h - BKE_library_idmap.h BKE_library_override.h BKE_library_query.h BKE_library_remap.h @@ -307,6 +306,7 @@ set(SRC BKE_lightprobe.h BKE_linestyle.h BKE_main.h + BKE_main_idmap.h BKE_mask.h BKE_material.h BKE_mball.h diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a17a09297c5..708d0600e91 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4557,9 +4557,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase MovieTracking *tracking; MovieTrackingTrack *track; MovieTrackingObject *tracking_object; - - Object *camob_eval = DEG_get_evaluated_object(depsgraph, - data->camera ? data->camera : scene->camera); + Object *camob = data->camera ? data->camera : scene->camera; float ctime = DEG_get_ctime(depsgraph); float framenr; @@ -4568,7 +4566,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase clip = scene->clip; } - if (!clip || !data->track[0] || !camob_eval) { + if (!clip || !data->track[0] || !camob) { return; } @@ -4602,7 +4600,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { float imat[4][4]; - copy_m4_m4(mat, camob_eval->obmat); + copy_m4_m4(mat, camob->obmat); BKE_tracking_camera_get_reconstructed_interpolate( tracking, tracking_object, framenr, imat); @@ -4613,7 +4611,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } else { - BKE_tracking_get_camera_object_matrix(cob->scene, camob_eval, mat); + BKE_tracking_get_camera_object_matrix(cob->scene, camob, mat); mul_m4_m4m4(cob->matrix, obmat, mat); translate_m4( @@ -4626,7 +4624,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); float len, d; - BKE_object_where_is_calc_mat4(camob_eval, mat); + BKE_object_where_is_calc_mat4(camob, mat); /* camera axis */ vec[0] = 0.0f; @@ -4694,7 +4692,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase } BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, camob_eval); + BKE_camera_params_from_object(¶ms, camob); if (params.is_ortho) { vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx); @@ -4708,9 +4706,9 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase vec[0] *= aspect; } - mul_v3_m4v3(disp, camob_eval->obmat, vec); + mul_v3_m4v3(disp, camob->obmat, vec); - copy_m4_m4(rmat, camob_eval->obmat); + copy_m4_m4(rmat, camob->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4730,10 +4728,10 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase vec[0] *= aspect; } - mul_v3_m4v3(disp, camob_eval->obmat, vec); + mul_v3_m4v3(disp, camob->obmat, vec); /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob_eval->obmat); + copy_m4_m4(rmat, camob->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4751,7 +4749,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase invert_m4_m4(imat, depth_ob->obmat); - mul_v3_m4v3(ray_start, imat, camob_eval->obmat[3]); + mul_v3_m4v3(ray_start, imat, camob->obmat[3]); mul_v3_m4v3(ray_end, imat, cob->matrix[3]); sub_v3_v3v3(ray_nor, ray_end, ray_start); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 833b8409f7d..5708cb0379b 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -204,29 +204,31 @@ FCurve *id_data_find_fcurve( RNA_pointer_create(id, type, data, &ptr); prop = RNA_struct_find_property(&ptr, prop_name); + if (prop == NULL) { + return NULL; + } - if (prop) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - /* animation takes priority over drivers */ - if ((adt->action) && (adt->action->curves.first)) { - fcu = list_find_fcurve(&adt->action->curves, path, index); - } + path = RNA_path_from_ID_to_property(&ptr, prop); + if (path == NULL) { + return NULL; + } - /* if not animated, check if driven */ - if ((fcu == NULL) && (adt->drivers.first)) { - fcu = list_find_fcurve(&adt->drivers, path, index); - if (fcu && r_driven) { - *r_driven = true; - } - fcu = NULL; - } + /* animation takes priority over drivers */ + if (adt->action && adt->action->curves.first) { + fcu = list_find_fcurve(&adt->action->curves, path, index); + } - MEM_freeN(path); + /* if not animated, check if driven */ + if (fcu == NULL && adt->drivers.first) { + fcu = list_find_fcurve(&adt->drivers, path, index); + if (fcu && r_driven) { + *r_driven = true; } + fcu = NULL; } + MEM_freeN(path); + return fcu; } @@ -309,26 +311,28 @@ int list_find_data_fcurves(ListBase *dst, /* search each F-Curve one by one */ for (fcu = src->first; fcu; fcu = fcu->next) { /* check if quoted string matches the path */ - if ((fcu->rna_path) && strstr(fcu->rna_path, dataPrefix)) { - char *quotedName = BLI_str_quoted_substrN(fcu->rna_path, dataPrefix); + if (fcu->rna_path == NULL || !strstr(fcu->rna_path, dataPrefix)) { + continue; + } - if (quotedName) { - /* check if the quoted name matches the required name */ - if (STREQ(quotedName, dataName)) { - LinkData *ld = MEM_callocN(sizeof(LinkData), __func__); + char *quotedName = BLI_str_quoted_substrN(fcu->rna_path, dataPrefix); + if (quotedName == NULL) { + continue; + } - ld->data = fcu; - BLI_addtail(dst, ld); + /* check if the quoted name matches the required name */ + if (STREQ(quotedName, dataName)) { + LinkData *ld = MEM_callocN(sizeof(LinkData), __func__); - matches++; - } + ld->data = fcu; + BLI_addtail(dst, ld); - /* always free the quoted string, since it needs freeing */ - MEM_freeN(quotedName); - } + matches++; } - } + /* always free the quoted string, since it needs freeing */ + MEM_freeN(quotedName); + } /* return the number of matches */ return matches; } @@ -397,53 +401,58 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, /* Standard F-Curve - Animation (Action) or Drivers */ while (adt && step--) { - if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { - /* XXX this function call can become a performance bottleneck */ - if (step) { - path = RNA_path_from_ID_to_property(&tptr, prop); - } + if ((adt->action == NULL || adt->action->curves.first == NULL) && + (adt->drivers.first == NULL)) { + continue; + } - // XXX: the logic here is duplicated with a function up above - if (path) { - /* animation takes priority over drivers */ - if (adt->action && adt->action->curves.first) { - fcu = list_find_fcurve(&adt->action->curves, path, rnaindex); + /* XXX this function call can become a performance bottleneck */ + if (step) { + path = RNA_path_from_ID_to_property(&tptr, prop); + } + if (path == NULL) { + continue; + } - if (fcu && r_action) { - *r_action = adt->action; - } - } + // XXX: the logic here is duplicated with a function up above + /* animation takes priority over drivers */ + if (adt->action && adt->action->curves.first) { + fcu = list_find_fcurve(&adt->action->curves, path, rnaindex); - /* if not animated, check if driven */ - if (!fcu && (adt->drivers.first)) { - fcu = list_find_fcurve(&adt->drivers, path, rnaindex); + if (fcu && r_action) { + *r_action = adt->action; + } + } - if (fcu) { - if (r_animdata) { - *r_animdata = adt; - } - *r_driven = true; - } - } + /* if not animated, check if driven */ + if (!fcu && (adt->drivers.first)) { + fcu = list_find_fcurve(&adt->drivers, path, rnaindex); - if (fcu && r_action) { - if (r_animdata) { - *r_animdata = adt; - } - *r_action = adt->action; - break; - } - else if (step) { - char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path); - if (tpath && tpath != path) { - MEM_freeN(path); - path = tpath; - adt = BKE_animdata_from_id(tptr.owner_id); - } - else { - adt = NULL; - } + if (fcu) { + if (r_animdata) { + *r_animdata = adt; } + *r_driven = true; + } + } + + if (fcu && r_action) { + if (r_animdata) { + *r_animdata = adt; + } + *r_action = adt->action; + break; + } + + if (step) { + char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path); + if (tpath && tpath != path) { + MEM_freeN(path); + path = tpath; + adt = BKE_animdata_from_id(tptr.owner_id); + } + else { + adt = NULL; } } } @@ -476,29 +485,28 @@ static int binarysearch_bezt_index_ex( CLOG_WARN(&LOG, "encountered invalid array"); return 0; } - else { - /* check whether to add before/after/on */ - float framenum; - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum = array[0].vec[1][0]; - if (IS_EQT(frame, framenum, threshold)) { - *r_replace = true; - return 0; - } - else if (frame < framenum) { - return 0; - } + /* check whether to add before/after/on */ + float framenum; - /* 'Last' Keyframe */ - framenum = array[(arraylen - 1)].vec[1][0]; - if (IS_EQT(frame, framenum, threshold)) { - *r_replace = true; - return (arraylen - 1); - } - else if (frame > framenum) { - return arraylen; - } + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum = array[0].vec[1][0]; + if (IS_EQT(frame, framenum, threshold)) { + *r_replace = true; + return 0; + } + if (frame < framenum) { + return 0; + } + + /* 'Last' Keyframe */ + framenum = array[(arraylen - 1)].vec[1][0]; + if (IS_EQT(frame, framenum, threshold)) { + *r_replace = true; + return (arraylen - 1); + } + if (frame > framenum) { + return arraylen; } /* most of the time, this loop is just to find where to put it @@ -1171,41 +1179,42 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha */ void sort_time_fcurve(FCurve *fcu) { + if (fcu->bezt == NULL) { + return; + } /* keep adjusting order of beztriples until nothing moves (bubble-sort) */ - if (fcu->bezt) { - BezTriple *bezt; - uint a; - - bool ok = true; - while (ok) { - ok = 0; - /* currently, will only be needed when there are beztriples */ - - /* loop over ALL points to adjust position in array and recalculate handles */ - for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { - /* check if thee's a next beztriple which we could try to swap with current */ - if (a < (fcu->totvert - 1)) { - /* swap if one is after the other (and indicate that order has changed) */ - if (bezt->vec[1][0] > (bezt + 1)->vec[1][0]) { - SWAP(BezTriple, *bezt, *(bezt + 1)); - ok = 1; - } + BezTriple *bezt; + uint a; + + bool ok = true; + while (ok) { + ok = 0; + /* currently, will only be needed when there are beztriples */ + + /* loop over ALL points to adjust position in array and recalculate handles */ + for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { + /* check if thee's a next beztriple which we could try to swap with current */ + if (a < (fcu->totvert - 1)) { + /* swap if one is after the other (and indicate that order has changed) */ + if (bezt->vec[1][0] > (bezt + 1)->vec[1][0]) { + SWAP(BezTriple, *bezt, *(bezt + 1)); + ok = 1; } } } + } - for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { - /* if either one of both of the points exceeds crosses over the keyframe time... */ - if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) { - /* swap handles if they have switched sides for some reason */ - swap_v2_v2(bezt->vec[0], bezt->vec[2]); - } - else { - /* clamp handles */ - CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]); - CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]); - } + for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { + /* if either one of both of the points exceeds crosses over the keyframe time... */ + if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) { + /* swap handles if they have switched sides for some reason */ + swap_v2_v2(bezt->vec[0], bezt->vec[2]); + } + else { + /* clamp handles */ + CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]); + CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]); } } } @@ -2539,11 +2548,10 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o) if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { return 1; } - else { - return 0; - } + return 0; } - else if (d == 0.0) { + + if (d == 0.0) { t = sqrt3d(-q); o[0] = (float)(2 * t - a); @@ -2555,87 +2563,78 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o) if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { return nr + 1; } - else { - return nr; - } + return nr; } - else { - phi = acos(-q / sqrt(-(p * p * p))); - t = sqrt(-p); - p = cos(phi / 3); - q = sqrt(3 - 3 * p * p); - o[0] = (float)(2 * t * p - a); - if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { - nr++; - } - o[nr] = (float)(-t * (p + q) - a); + phi = acos(-q / sqrt(-(p * p * p))); + t = sqrt(-p); + p = cos(phi / 3); + q = sqrt(3 - 3 * p * p); + o[0] = (float)(2 * t * p - a); - if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { - nr++; - } - o[nr] = (float)(-t * (p - q) - a); + if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { + nr++; + } + o[nr] = (float)(-t * (p + q) - a); - if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { - return nr + 1; - } - else { - return nr; - } + if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { + nr++; } - } - else { - a = c2; - b = c1; - c = c0; + o[nr] = (float)(-t * (p - q) - a); - if (a != 0.0) { - /* discriminant */ - p = b * b - 4 * a * c; + if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { + return nr + 1; + } + return nr; + } + a = c2; + b = c1; + c = c0; - if (p > 0) { - p = sqrt(p); - o[0] = (float)((-b - p) / (2 * a)); + if (a != 0.0) { + /* discriminant */ + p = b * b - 4 * a * c; - if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { - nr++; - } - o[nr] = (float)((-b + p) / (2 * a)); + if (p > 0) { + p = sqrt(p); + o[0] = (float)((-b - p) / (2 * a)); - if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { - return nr + 1; - } - else { - return nr; - } + if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { + nr++; } - else if (p == 0) { - o[0] = (float)(-b / (2 * a)); - if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { - return 1; - } - else { - return 0; - } + o[nr] = (float)((-b + p) / (2 * a)); + + if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) { + return nr + 1; } + return nr; } - else if (b != 0.0) { - o[0] = (float)(-c / b); + if (p == 0) { + o[0] = (float)(-b / (2 * a)); if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { return 1; } - else { - return 0; - } } - else if (c == 0.0) { - o[0] = 0.0; + + return 0; + } + + if (b != 0.0) { + o[0] = (float)(-c / b); + + if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) { return 1; } - return 0; } + + if (c == 0.0) { + o[0] = 0.0; + return 1; + } + + return 0; } static void berekeny(float f1, float f2, float f3, float f4, float *o, int b) @@ -3244,19 +3243,18 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) /* only calculate + set curval (overriding the existing value) if curve has * any data which warrants this... */ - if (!BKE_fcurve_is_empty(fcu)) { - /* calculate and set curval (evaluates driver too if necessary) */ - float curval; - if (fcu->driver) { - curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime); - } - else { - curval = evaluate_fcurve(fcu, evaltime); - } - fcu->curval = curval; /* debug display only, not thread safe! */ - return curval; + if (BKE_fcurve_is_empty(fcu)) { + return 0.0f; + } + + /* calculate and set curval (evaluates driver too if necessary) */ + float curval; + if (fcu->driver) { + curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime); } else { - return 0.0f; + curval = evaluate_fcurve(fcu, evaltime); } + fcu->curval = curval; /* debug display only, not thread safe! */ + return curval; } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index f35aebbae16..8b959e30aff 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3505,10 +3505,14 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } - has_noise = manta_read_noise(mds->fluid, mmd, noise_frame); + if (!baking_data && !baking_noise && !mode_replay) { + has_data = manta_update_noise_structures(mds->fluid, mmd, noise_frame); + } + else { + has_noise = manta_read_noise(mds->fluid, mmd, noise_frame); + } - /* In case of using the adaptive domain, copy all data that was read to a new fluid object. - */ + /* When using the adaptive domain, copy all data that was read to a new fluid object. */ if (with_adaptive && baking_noise) { /* Adaptive domain needs to know about current state, so save it, then copy. */ copy_v3_v3_int(o_res, mds->res); @@ -3521,7 +3525,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift); } } - has_data = manta_read_data(mds->fluid, mmd, data_frame); + if (!baking_data && !baking_noise && !mode_replay) { + /* There is no need to call manta_update_smoke_structures() here. + * The noise cache has already been read with manta_update_noise_structures(). */ + } + else { + has_data = manta_read_data(mds->fluid, mmd, data_frame); + } } /* Read data cache only */ else { @@ -3532,7 +3542,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, BKE_fluid_reallocate_fluid(mds, mds->res, 1); } /* Read data cache */ - has_data = manta_read_data(mds->fluid, mmd, data_frame); + if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) { + has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame); + } + else { + has_data = manta_read_data(mds->fluid, mmd, data_frame); + } } if (with_liquid) { if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) { diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 243c63a8f03..a09e97d4fed 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -783,7 +783,7 @@ void curve_deform_verts(Object *cuOb, if (cu->flag & CU_DEFORM_BOUNDS_OFF) { for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { - const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : + const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { @@ -800,7 +800,7 @@ void curve_deform_verts(Object *cuOb, INIT_MINMAX(cd.dmin, cd.dmax); for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { - const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : + const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { mul_m4_v3(cd.curvespace, vert_coords[a]); @@ -809,7 +809,7 @@ void curve_deform_verts(Object *cuOb, } for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { - const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : + const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) : defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { @@ -899,8 +899,9 @@ static void lattice_deform_vert_task(void *__restrict userdata, const LatticeDeformUserdata *data = userdata; if (data->dvert != NULL) { - const float weight = data->invert_vgroup? 1.0f - defvert_find_weight(data->dvert + index, data->defgrp_index) : - defvert_find_weight(data->dvert + index, data->defgrp_index); + const float weight = data->invert_vgroup ? + 1.0f - defvert_find_weight(data->dvert + index, data->defgrp_index) : + defvert_find_weight(data->dvert + index, data->defgrp_index); if (weight > 0.0f) { calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac); } diff --git a/source/blender/blenkernel/intern/library_idmap.c b/source/blender/blenkernel/intern/main_idmap.c index ab0ff5b0096..a210961b212 100644 --- a/source/blender/blenkernel/intern/library_idmap.c +++ b/source/blender/blenkernel/intern/main_idmap.c @@ -26,8 +26,8 @@ #include "DNA_ID.h" #include "BKE_idcode.h" -#include "BKE_library_idmap.h" /* own include */ #include "BKE_main.h" +#include "BKE_main_idmap.h" /* own include */ /** \file * \ingroup bke diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index f4f93fcb698..cb8b3b5ecc9 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -198,7 +198,7 @@ float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, float (*BKE_mask_spline_differentiate( MaskSpline *spline, int width, int height, unsigned int *tot_diff_point))[2] { - int unsigned resol = BKE_mask_spline_resolution(spline, width, height); + uint resol = BKE_mask_spline_resolution(spline, width, height); return BKE_mask_spline_differentiate_with_resolution(spline, tot_diff_point, resol); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 3835e405630..098da997d8f 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1200,7 +1200,7 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth) * Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ -int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, unsigned vert) +int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, uint vert) { int j; for (j = 0; j < poly->totloop; j++, loopstart++) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 75e0d044c7c..94c06e46cb9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2242,27 +2242,37 @@ void ntreeSetOutput(bNodeTree *ntree) * might be different for editor or for "real" use... */ } -/* Returns the private NodeTree object of the datablock, if it has one. */ -bNodeTree *ntreeFromID(const ID *id) +/** Get address of potential nodetree pointer of given ID. + * + * \warning Using this function directly is potentially dangerous, if you don't know or are not + * sure, please use `ntreeFromID()` instead. */ +bNodeTree **BKE_ntree_ptr_from_id(ID *id) { switch (GS(id->name)) { case ID_MA: - return ((const Material *)id)->nodetree; + return &((Material *)id)->nodetree; case ID_LA: - return ((const Light *)id)->nodetree; + return &((Light *)id)->nodetree; case ID_WO: - return ((const World *)id)->nodetree; + return &((World *)id)->nodetree; case ID_TE: - return ((const Tex *)id)->nodetree; + return &((Tex *)id)->nodetree; case ID_SCE: - return ((const Scene *)id)->nodetree; + return &((Scene *)id)->nodetree; case ID_LS: - return ((const FreestyleLineStyle *)id)->nodetree; + return &((FreestyleLineStyle *)id)->nodetree; default: return NULL; } } +/* Returns the private NodeTree object of the datablock, if it has one. */ +bNodeTree *ntreeFromID(ID *id) +{ + bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); + return (nodetree != NULL) ? *nodetree : NULL; +} + /* Finds and returns the datablock that privately owns the given tree, or NULL. */ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 5e30c7c5e96..42e4921795c 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1065,7 +1065,7 @@ bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *m /* returns non-zero if any of the corners of the grid * face whose inner corner is at (x, y) are hidden, * zero otherwise */ -bool paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y) +bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y) { /* skip face if any of its corners are hidden */ return (BLI_BITMAP_TEST(grid_hidden, y * gridsize + x) || @@ -1090,7 +1090,7 @@ bool paint_is_bmesh_face_hidden(BMFace *f) return false; } -float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, unsigned x, unsigned y) +float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y) { int factor = BKE_ccg_factor(level, gpm->level); int gridsize = BKE_ccg_gridsize(gpm->level); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 7a352f8c9f8..d68c7a947ae 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3638,12 +3638,14 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } } - /* clear modifier */ + /* Clear modifier, skip empty ones. */ psmd = psys_get_modifier(ob, psys); - BLI_remlink(&ob->modifiers, psmd); - modifier_free((ModifierData *)psmd); + if (psmd) { + BLI_remlink(&ob->modifiers, psmd); + modifier_free((ModifierData *)psmd); + } - /* clear particle system */ + /* Clear particle system. */ BLI_remlink(&ob->particlesystem, psys); if (psys->part) { id_us_min(&psys->part->id); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index ec520e188f1..141e93183fb 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1410,7 +1410,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int * while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_UpdateNormals) { - for (unsigned i = 0; i < node->totprim; i++) { + for (uint i = 0; i < node->totprim; i++) { void *face = bvh->gridfaces[node->prim_indices[i]]; BLI_gset_add(face_set, face); } diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 9008348ed3b..4a69fcfa9d0 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -56,17 +56,6 @@ static int last_studiolight_id = 0; #define STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * 2) #define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse" #define STUDIOLIGHT_PASSNAME_SPECULAR "specular" -/* - * The method to calculate the irradiance buffers - * The irradiance buffer is only shown in the background when in LookDev. - * - * STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE is very slow, but very accurate - * STUDIOLIGHT_IRRADIANCE_METHOD_SPHERICAL_HARMONICS is faster but has artifacts - * Cannot have both enabled at the same time!!! - */ -// #define STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE -#define STUDIOLIGHT_IRRADIANCE_METHOD_SPHERICAL_HARMONICS - /* Temporarily disabled due to the creation of textures with -nan(ind)s */ #define STUDIOLIGHT_SH_WINDOWING 0.0f /* 0.0 is disabled */ @@ -1024,40 +1013,6 @@ BLI_INLINE void studiolight_evaluate_specular_radiance_buffer(ImBuf *radiance_bu madd_v3_v3fl(color, accum, 1.0f / accum_weight); } -#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE -static void studiolight_irradiance_eval(StudioLight *sl, float color[3], const float normal[3]) -{ - copy_v3_fl(color, 0.0f); - - /* XXX: This is madness, iterating over all cubemap pixels for each destination pixels - * even if their weight is 0.0f. - * It should use hemisphere, cosine sampling at least. */ - - /* back */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, 0, 2, 1, 1); - /* front */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, 0, 2, 1, -1); - - /* left */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, 1, 2, 0, 1); - /* right */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, 1, 2, 0, -1); - - /* top */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, 0, 1, 2, 1); - /* bottom */ - studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, 0, 1, 2, -1); - - mul_v3_fl(color, 1.0 / M_PI); -} -#endif - static float brdf_approx(float spec_color, float roughness, float NV) { /* Very rough own approx. We don't need it to be correct, just fast. @@ -1185,11 +1140,7 @@ static bool studiolight_load_spherical_harmonics_coefficients(StudioLight *sl) static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { -#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED); -#else BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED); -#endif float *colbuf = MEM_mallocN(STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH * STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * sizeof(float[4]), @@ -1202,11 +1153,7 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl) STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT) { float dir[3]; equirect_to_direction(dir, x, y); -#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE - studiolight_irradiance_eval(sl, pixel, dir); -#else studiolight_spherical_harmonics_eval(sl, pixel, dir); -#endif pixel[3] = 1.0f; } ITER_PIXELS_END; @@ -1217,15 +1164,6 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl) STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT, 4); MEM_freeN(colbuf); - -#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE - /* - * Only store cached files when using STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE - */ - if (sl->flag & STUDIOLIGHT_USER_DEFINED) { - IMB_saveiff(sl->equirect_irradiance_buffer, sl->path_irr_cache, IB_rectfloat); - } -#endif } sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED; } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 1e7b3af53d5..86fb2ab58bc 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -80,9 +80,7 @@ static struct { /* Free the whole list of tracks, list's head and tail are set to NULL. */ static void tracking_tracks_free(ListBase *tracks) { - MovieTrackingTrack *track; - - for (track = tracks->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) { BKE_tracking_track_free(track); } @@ -92,9 +90,7 @@ static void tracking_tracks_free(ListBase *tracks) /* Free the whole list of plane tracks, list's head and tail are set to NULL. */ static void tracking_plane_tracks_free(ListBase *plane_tracks) { - MovieTrackingPlaneTrack *plane_track; - - for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) { + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks) { BKE_tracking_plane_track_free(plane_track); } @@ -128,10 +124,8 @@ static void tracking_object_free(MovieTrackingObject *object) /* Free list of tracking objects, list's head and tail is set to NULL. */ static void tracking_objects_free(ListBase *objects) { - MovieTrackingObject *object; - /* Free objects contents. */ - for (object = objects->first; object; object = object->next) { + LISTBASE_FOREACH (MovieTrackingObject *, object, objects) { tracking_object_free(object); } @@ -191,13 +185,11 @@ static void tracking_tracks_copy(ListBase *tracks_dst, GHash *tracks_mapping, const int flag) { - MovieTrackingTrack *track_dst, *track_src; - BLI_listbase_clear(tracks_dst); BLI_ghash_clear(tracks_mapping, NULL, NULL); - for (track_src = tracks_src->first; track_src != NULL; track_src = track_src->next) { - track_dst = MEM_dupallocN(track_src); + LISTBASE_FOREACH (MovieTrackingTrack *, track_src, tracks_src) { + MovieTrackingTrack *track_dst = MEM_dupallocN(track_src); if (track_src->markers) { track_dst->markers = MEM_dupallocN(track_src->markers); } @@ -217,13 +209,10 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_list_dst, GHash *tracks_mapping, const int flag) { - MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src; - BLI_listbase_clear(plane_tracks_list_dst); - for (plane_track_src = plane_tracks_list_src->first; plane_track_src != NULL; - plane_track_src = plane_track_src->next) { - plane_track_dst = MEM_dupallocN(plane_track_src); + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track_src, plane_tracks_list_src) { + MovieTrackingPlaneTrack *plane_track_dst = MEM_dupallocN(plane_track_src); if (plane_track_src->markers) { plane_track_dst->markers = MEM_dupallocN(plane_track_src->markers); } @@ -278,12 +267,10 @@ static void tracking_objects_copy(ListBase *objects_dst, GHash *tracks_mapping, const int flag) { - MovieTrackingObject *object_dst, *object_src; - BLI_listbase_clear(objects_dst); - for (object_src = objects_src->first; object_src != NULL; object_src = object_src->next) { - object_dst = MEM_mallocN(sizeof(*object_dst), __func__); + LISTBASE_FOREACH (MovieTrackingObject *, object_src, objects_src) { + MovieTrackingObject *object_dst = MEM_mallocN(sizeof(*object_dst), __func__); tracking_object_copy(object_dst, object_src, tracks_mapping, flag); BLI_addtail(objects_dst, object_dst); } @@ -844,7 +831,7 @@ void BKE_tracking_tracks_join(MovieTracking *tracking, MovieTrackingMarker *marker_a, *marker_b; int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; - int j, inverse = 0; + int inverse = 0; inverse = (b == 0) || (dst_track->markers[b - 1].flag & MARKER_DISABLED) || (dst_track->markers[b - 1].framenr != frame - 1); @@ -872,7 +859,7 @@ void BKE_tracking_tracks_join(MovieTracking *tracking, b = start_b; /* linear interpolation for intersecting frames */ - for (j = 0; j < len; j++) { + for (int j = 0; j < len; j++) { float fac = 0.5f; if (len > 1) { @@ -1180,9 +1167,7 @@ void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area) void BKE_tracking_tracks_deselect_all(ListBase *tracksbase) { - MovieTrackingTrack *track; - - for (track = tracksbase->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { if ((track->flag & TRACK_HIDDEN) == 0) { BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT); } @@ -1269,13 +1254,12 @@ void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr) void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) { - int a; float pat_min[2], pat_max[2]; BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); if (event == CLAMP_PAT_DIM) { - for (a = 0; a < 2; a++) { + for (int a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]); marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]); @@ -1286,23 +1270,22 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) sub_v2_v2v2(dim, pat_max, pat_min); - for (a = 0; a < 2; a++) { - int b; + for (int a = 0; a < 2; a++) { /* pattern shouldn't be moved outside of search */ if (pat_min[a] < marker->search_min[a]) { - for (b = 0; b < 4; b++) { + for (int b = 0; b < 4; b++) { marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; } } if (pat_max[a] > marker->search_max[a]) { - for (b = 0; b < 4; b++) { + for (int b = 0; b < 4; b++) { marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; } } } } else if (event == CLAMP_SEARCH_DIM) { - for (a = 0; a < 2; a++) { + for (int a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]); marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]); @@ -1313,7 +1296,7 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) sub_v2_v2v2(dim, marker->search_max, marker->search_min); - for (a = 0; a < 2; a++) { + for (int a = 0; a < 2; a++) { /* search shouldn't be moved inside pattern */ if (marker->search_min[a] > pat_min[a]) { marker->search_min[a] = pat_min[a]; @@ -1457,15 +1440,14 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, { MovieTrackingPlaneTrack *plane_track; MovieTrackingPlaneMarker plane_marker; - MovieTrackingTrack *track; float tracks_min[2], tracks_max[2]; - int track_index, num_selected_tracks = 0; + int num_selected_tracks = 0; (void)tracking; /* Ignored. */ /* Use bounding box of selected markers as an initial size of plane. */ INIT_MINMAX2(tracks_min, tracks_max); - for (track = tracks->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) { if (TRACK_SELECTED(track)) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); float pattern_min[2], pattern_max[2]; @@ -1493,7 +1475,8 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, /* Use selected tracks from given list as a plane. */ plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array"); - for (track = tracks->first, track_index = 0; track; track = track->next) { + int track_index = 0; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) { if (TRACK_SELECTED(track)) { plane_track->point_tracks[track_index] = track; track_index++; @@ -1552,9 +1535,8 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *track const char *name) { ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object); - MovieTrackingPlaneTrack *plane_track; - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { if (STREQ(plane_track->name, name)) { return plane_track; } @@ -1565,13 +1547,11 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *track MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking) { - ListBase *plane_tracks_base; - if (tracking->act_plane_track == NULL) { return NULL; } - plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); /* Check that active track is in current plane tracks list */ if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) != -1) { @@ -1583,9 +1563,7 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTrackin void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base) { - MovieTrackingPlaneTrack *plane_track; - - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { plane_track->flag &= ~SELECT; } } @@ -1593,8 +1571,7 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base) bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track, MovieTrackingTrack *track) { - int i; - for (i = 0; i < plane_track->point_tracksnr; i++) { + for (int i = 0; i < plane_track->point_tracksnr; i++) { if (plane_track->point_tracks[i] == track) { return true; } @@ -1605,17 +1582,14 @@ bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_tra bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track, MovieTrackingTrack *track) { - int i, track_index; - MovieTrackingTrack **new_point_tracks; - if (plane_track->point_tracksnr <= 4) { return false; } - new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), - "new point tracks array"); + MovieTrackingTrack **new_point_tracks = MEM_mallocN( + sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), "new point tracks array"); - for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { + for (int i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { if (plane_track->point_tracks[i] != track) { new_point_tracks[track_index++] = plane_track->point_tracks[i]; } @@ -1631,10 +1605,8 @@ bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_ void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking, MovieTrackingTrack *track) { - MovieTrackingPlaneTrack *plane_track, *next_plane_track; ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); - for (plane_track = plane_tracks_base->first; plane_track; plane_track = next_plane_track) { - next_plane_track = plane_track->next; + LISTBASE_FOREACH_MUTABLE (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { if (BKE_tracking_plane_track_has_point_track(plane_track, track)) { if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) { /* Delete planes with less than 3 point tracks in it. */ @@ -1649,8 +1621,7 @@ void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane MovieTrackingTrack *old_track, MovieTrackingTrack *new_track) { - int i; - for (i = 0; i < plane_track->point_tracksnr; i++) { + for (int i = 0; i < plane_track->point_tracksnr; i++) { if (plane_track->point_tracks[i] == old_track) { plane_track->point_tracks[i] = new_track; break; @@ -1662,9 +1633,8 @@ void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking, MovieTrackingTrack *old_track, MovieTrackingTrack *new_track) { - MovieTrackingPlaneTrack *plane_track; ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) { BKE_tracking_plane_track_replace_point_track(plane_track, old_track, new_track); } @@ -1838,23 +1808,22 @@ void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *pla { MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, (int)framenr); MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1); - int i; if (marker != marker_last) { MovieTrackingPlaneMarker *marker_next = marker + 1; if (marker_next->framenr == marker->framenr + 1) { float fac = (framenr - (int)framenr) / (marker_next->framenr - marker->framenr); - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { interp_v2_v2v2(corners[i], marker->corners[i], marker_next->corners[i], fac); } } else { - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { copy_v2_v2(corners[i], marker->corners[i]); } } } else { - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { copy_v2_v2(corners[i], marker->corners[i]); } } @@ -2399,7 +2368,6 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, bool undistort, float delta[2]) { - int a; float pos[2], warped_pos[2]; const int coord_delta = 5; void (*apply_distortion)(MovieTracking * tracking, const float pos[2], float out[2]); @@ -2413,7 +2381,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, delta[0] = delta[1] = -FLT_MAX; - for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) { + for (int a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) { if (a > rect->xmax) { a = rect->xmax; } @@ -2441,7 +2409,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, } } - for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) { + for (int a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) { if (a > rect->ymax) { a = rect->ymax; } @@ -2515,9 +2483,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, * fractional part of offset */ if (from_anchor) { - int a; - - for (a = 0; a < 5; a++) { + for (int a = 0; a < 5; a++) { src_pixel_x[a] += (double)((track->offset[0] * frame_width) - ((int)(track->offset[0] * frame_width))); src_pixel_y[a] += (double)((track->offset[1] * frame_height) - @@ -2664,9 +2630,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, void BKE_tracking_disable_channels( ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale) { - int x, y; - float scale; - if (!disable_red && !disable_green && !disable_blue && !grayscale) { return; } @@ -2674,11 +2637,11 @@ void BKE_tracking_disable_channels( /* if only some components are selected, it's important to rescale the result * appropriately so that e.g. if only blue is selected, it's not zeroed out. */ - scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) + - (disable_blue ? 0.0f : 0.0722f); + float scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) + + (disable_blue ? 0.0f : 0.0722f); - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { + for (int y = 0; y < ibuf->y; y++) { + for (int x = 0; x < ibuf->x; x++) { int pixel = ibuf->x * y + x; if (ibuf->rect_float) { @@ -2916,7 +2879,6 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking) { MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; - MovieTrackingTrack *track; MovieTrackingReconstruction *reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); @@ -2924,9 +2886,7 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking) bool sel_only = (dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY) != 0; bool show_hidden = (dopesheet->flag & TRACKING_DOPE_SHOW_HIDDEN) != 0; - for (track = tracksbase->first; track; track = track->next) { - MovieTrackingDopesheetChannel *channel; - + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { if (!show_hidden && (track->flag & TRACK_HIDDEN) != 0) { continue; } @@ -2935,7 +2895,8 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking) continue; } - channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), "tracking dopesheet channel"); + MovieTrackingDopesheetChannel *channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), + "tracking dopesheet channel"); channel->track = track; if (reconstruction->flag & TRACKING_RECONSTRUCTED) { @@ -3012,13 +2973,12 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking) MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - MovieTrackingTrack *track; int frames, start_frame = INT_MAX, end_frame = -INT_MAX; int *per_frame_counter; int prev_coverage, last_segment_frame; /* find frame boundaries */ - for (track = tracksbase->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { start_frame = min_ii(start_frame, track->markers[0].framenr); end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr); } @@ -3029,7 +2989,7 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking) per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter"); /* find per-frame markers count */ - for (track = tracksbase->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { for (int i = 0; i < track->markersnr; i++) { MovieTrackingMarker *marker = &track->markers[i]; diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index fad928c12fe..9d8395defcd 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -127,13 +127,12 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track, libmv_Marker *libmv_marker) { const int frame_dimensions[2] = {frame_width, frame_height}; - int i; libmv_marker->clip = clip; libmv_marker->frame = marker->framenr; libmv_marker->track = track_index; normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center); - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { normalized_relative_to_libmv_frame( marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]); } @@ -183,11 +182,10 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker, MovieTrackingMarker *marker) { const int frame_dimensions[2] = {frame_width, frame_height}; - int i; marker->framenr = libmv_marker->frame; libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos); - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { libmv_frame_to_normalized_relative(libmv_marker->patch[i], libmv_marker->center, frame_dimensions, @@ -260,7 +258,7 @@ static void fill_autotrack_tracks(const int frame_width, { /* Count number of markers to be put to a context. */ size_t num_trackable_markers = 0; - for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { for (int i = 0; i < track->markersnr; i++) { const MovieTrackingMarker *marker = track->markers + i; if ((marker->flag & MARKER_DISABLED) == 0) { @@ -277,7 +275,7 @@ static void fill_autotrack_tracks(const int frame_width, "libmv markers array"); /* Fill in markers array. */ int track_index = 0, num_filled_libmv_markers = 0; - for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { for (int i = 0; i < track->markersnr; i++) { MovieTrackingMarker *marker = track->markers + i; if ((marker->flag & MARKER_DISABLED) != 0) { @@ -307,7 +305,7 @@ static void create_per_track_tracking_options(const MovieClip *clip, AutoTrackContext *context) { /* Count number of trackable tracks. */ - for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { if (check_track_trackable(clip, track, user)) { context->num_tracks++; } @@ -317,7 +315,7 @@ static void create_per_track_tracking_options(const MovieClip *clip, "auto track options"); /* Fill in all the settings. */ int i = 0, track_index = 0; - for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { if (!check_track_trackable(clip, track, user)) { track_index++; continue; @@ -461,17 +459,16 @@ bool BKE_autotrack_context_step(AutoTrackContext *context) void BKE_autotrack_context_sync(AutoTrackContext *context) { int newframe, frame_delta = context->backwards ? -1 : 1; - int frame; BLI_spin_lock(&context->spin_lock); newframe = context->user.framenr; - for (frame = context->sync_frame; frame != (context->backwards ? newframe - 1 : newframe + 1); + for (int frame = context->sync_frame; + frame != (context->backwards ? newframe - 1 : newframe + 1); frame += frame_delta) { MovieTrackingMarker marker; libmv_Marker libmv_marker; int clip = 0; - int track; - for (track = 0; track < context->num_tracks; track++) { + for (int track = 0; track < context->num_tracks; track++) { AutoTrackOptions *options = &context->options[track]; int track_frame = BKE_movieclip_remap_scene_to_clip_frame( context->clips[options->clip_index], frame); @@ -522,17 +519,13 @@ void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *u void BKE_autotrack_context_finish(AutoTrackContext *context) { - int clip_index; - - for (clip_index = 0; clip_index < context->num_clips; clip_index++) { + for (int clip_index = 0; clip_index < context->num_clips; clip_index++) { MovieClip *clip = context->clips[clip_index]; ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - MovieTrackingPlaneTrack *plane_track; - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { - int track; - for (track = 0; track < context->num_tracks; track++) { + for (int track = 0; track < context->num_tracks; track++) { if (BKE_tracking_plane_track_has_point_track(plane_track, context->options[track].track)) { BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame); diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c index ec044f14fa8..08719161e1a 100644 --- a/source/blender/blenkernel/intern/tracking_detect.c +++ b/source/blender/blenkernel/intern/tracking_detect.c @@ -38,7 +38,6 @@ /* Check whether point is inside grease pencil stroke. */ static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y) { - int i, prev; int count = 0; bGPDspoint *points = stroke->points; @@ -50,9 +49,7 @@ static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y) * work, but such situation is crappy anyway. */ - prev = stroke->totpoints - 1; - - for (i = 0; i < stroke->totpoints; i++) { + for (int i = 0, prev = stroke->totpoints - 1; i < stroke->totpoints; prev = i, i++) { if ((points[i].y < y && points[prev].y >= y) || (points[prev].y < y && points[i].y >= y)) { float fac = (y - points[i].y) / (points[prev].y - points[i].y); @@ -60,8 +57,6 @@ static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y) count++; } } - - prev = i; } return (count % 2) ? true : false; diff --git a/source/blender/blenkernel/intern/tracking_plane_tracker.c b/source/blender/blenkernel/intern/tracking_plane_tracker.c index 602243a7d50..e0e8a68bb1e 100644 --- a/source/blender/blenkernel/intern/tracking_plane_tracker.c +++ b/source/blender/blenkernel/intern/tracking_plane_tracker.c @@ -39,13 +39,13 @@ typedef double Vec2[2]; static int point_markers_correspondences_on_both_image( MovieTrackingPlaneTrack *plane_track, int frame1, int frame2, Vec2 **x1_r, Vec2 **x2_r) { - int i, correspondence_index; Vec2 *x1, *x2; *x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1"); *x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2"); - for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) { + int correspondence_index = 0; + for (int i = 0; i < plane_track->point_tracksnr; i++) { MovieTrackingTrack *point_track = plane_track->point_tracks[i]; MovieTrackingMarker *point_marker1, *point_marker2; @@ -77,11 +77,11 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac start_frame); MovieTrackingPlaneMarker *keyframe_plane_marker = NULL; MovieTrackingPlaneMarker new_plane_marker; - int current_frame, frame_delta = direction > 0 ? 1 : -1; + int frame_delta = direction > 0 ? 1 : -1; if (plane_track->flag & PLANE_TRACK_AUTOKEY) { /* Find a keyframe in given direction. */ - for (current_frame = start_frame;; current_frame += frame_delta) { + for (int current_frame = start_frame;; current_frame += frame_delta) { MovieTrackingPlaneMarker *next_plane_marker = BKE_tracking_plane_marker_get_exact( plane_track, current_frame + frame_delta); @@ -102,11 +102,10 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac new_plane_marker = *start_plane_marker; new_plane_marker.flag |= PLANE_MARKER_TRACKED; - for (current_frame = start_frame;; current_frame += frame_delta) { + for (int current_frame = start_frame;; current_frame += frame_delta) { MovieTrackingPlaneMarker *next_plane_marker = BKE_tracking_plane_marker_get_exact( plane_track, current_frame + frame_delta); Vec2 *x1, *x2; - int i, num_correspondences; double H_double[3][3]; float H[3][3]; @@ -118,13 +117,11 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac } } - num_correspondences = point_markers_correspondences_on_both_image( + const int num_correspondences = point_markers_correspondences_on_both_image( plane_track, current_frame, current_frame + frame_delta, &x1, &x2); - if (num_correspondences < 4) { MEM_freeN(x1); MEM_freeN(x2); - break; } @@ -132,7 +129,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac copy_m3_m3d(H, H_double); - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { float vec[3] = {0.0f, 0.0f, 1.0f}, vec2[3]; copy_v2_v2(vec, new_plane_marker.corners[i]); @@ -155,7 +152,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac fac = 3 * fac * fac - 2 * fac * fac * fac; - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { interp_v2_v2v2(new_plane_marker.corners[i], new_plane_marker.corners[i], next_plane_marker->corners[i], diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index 1d6bb88c3f4..967642c03a8 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -50,9 +50,7 @@ static void float_rgba_to_gray(const float *rgba, float weight_green, float weight_blue) { - int i; - - for (i = 0; i < num_pixels; i++) { + for (int i = 0; i < num_pixels; i++) { const float *pixel = rgba + 4 * i; gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]; @@ -66,9 +64,7 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba, float weight_green, float weight_blue) { - int i; - - for (i = 0; i < num_pixels; i++) { + for (int i = 0; i < num_pixels; i++) { const unsigned char *pixel = rgba + i * 4; gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index ab741eed410..527a2f59491 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -90,13 +90,10 @@ static struct libmv_Tracks *libmv_tracks_new(MovieClip *clip, track = tracksbase->first; while (track) { - FCurve *weight_fcurve; - int a = 0; - - weight_fcurve = id_data_find_fcurve( + FCurve *weight_fcurve = id_data_find_fcurve( &clip->id, track, &RNA_MovieTrackingTrack, "weight", 0, NULL); - for (a = 0; a < track->markersnr; a++) { + for (int a = 0; a < track->markersnr; a++) { MovieTrackingMarker *marker = &track->markers[a]; if ((marker->flag & MARKER_DISABLED) == 0) { @@ -149,7 +146,7 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieReconstructedCamera *reconstructed; MovieTrackingTrack *track; ListBase *tracksbase = NULL; - int tracknr = 0, a; + int tracknr = 0; bool ok = true; bool origin_set = false; int sfra = context->sfra, efra = context->efra; @@ -200,16 +197,16 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, reconstructed = MEM_callocN((efra - sfra + 1) * sizeof(MovieReconstructedCamera), "temp reconstructed camera"); - for (a = sfra; a <= efra; a++) { + for (int a = sfra; a <= efra; a++) { double matd[4][4]; if (libmv_reprojectionCameraForImage(libmv_reconstruction, a, matd)) { - int i, j; float mat[4][4]; float error = libmv_reprojectionErrorForImage(libmv_reconstruction, a); - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { + /* TODO(sergey): Use transpose utility. */ + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { mat[i][j] = matd[i][j]; } } @@ -591,21 +588,19 @@ static void tracking_scale_reconstruction(ListBase *tracksbase, MovieTrackingReconstruction *reconstruction, const float scale[3]) { - MovieTrackingTrack *track; - int i; float first_camera_delta[3] = {0.0f, 0.0f, 0.0f}; if (reconstruction->camnr > 0) { mul_v3_v3v3(first_camera_delta, reconstruction->cameras[0].mat[3], scale); } - for (i = 0; i < reconstruction->camnr; i++) { + for (int i = 0; i < reconstruction->camnr; i++) { MovieReconstructedCamera *camera = &reconstruction->cameras[i]; mul_v3_v3(camera->mat[3], scale); sub_v3_v3(camera->mat[3], first_camera_delta); } - for (track = tracksbase->first; track; track = track->next) { + for (MovieTrackingTrack *track = tracksbase->first; track; track = track->next) { if (track->flag & TRACK_HAS_BUNDLE) { mul_v3_v3(track->bundle_pos, scale); sub_v3_v3(track->bundle_pos, first_camera_delta); @@ -618,14 +613,10 @@ static void tracking_scale_reconstruction(ListBase *tracksbase, */ void BKE_tracking_reconstruction_scale(MovieTracking *tracking, float scale[3]) { - MovieTrackingObject *object; - - for (object = tracking->objects.first; object; object = object->next) { - ListBase *tracksbase; - MovieTrackingReconstruction *reconstruction; - - tracksbase = BKE_tracking_object_get_tracks(tracking, object); - reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingReconstruction *reconstruction = BKE_tracking_object_get_reconstruction(tracking, + object); tracking_scale_reconstruction(tracksbase, reconstruction, scale); } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 2c270f10908..b5b33353ed7 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -34,6 +34,7 @@ #include "BLI_sort_utils.h" #include "BLI_ghash.h" #include "BLI_math_vector.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_task.h" @@ -332,8 +333,7 @@ static void find_next_working_frames(StabContext *ctx, int *next_lower, int *next_higher) { - for (MovieTrackingTrack *track = ctx->tracking->tracks.first; track != NULL; - track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &ctx->tracking->tracks) { if (is_usable_for_stabilization(ctx, track)) { int startpoint = search_closest_marker_index(track, framenr); retrieve_next_higher_usable_frame(ctx, track, startpoint, framenr, next_higher); @@ -545,7 +545,6 @@ static bool average_track_contributions(StabContext *ctx, { bool ok; float weight_sum; - MovieTrackingTrack *track; MovieTracking *tracking = ctx->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; float ref_pos[2]; @@ -559,7 +558,7 @@ static bool average_track_contributions(StabContext *ctx, ok = false; weight_sum = 0.0f; - for (track = tracking->tracks.first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { if (!is_init_for_stabilization(ctx, track)) { continue; } @@ -597,7 +596,7 @@ static bool average_track_contributions(StabContext *ctx, ok = false; weight_sum = 0.0f; - for (track = tracking->tracks.first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { if (!is_init_for_stabilization(ctx, track)) { continue; } @@ -652,12 +651,11 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_ { bool ok = false; float weight_sum; - MovieTrackingTrack *track; MovieTracking *tracking = ctx->tracking; zero_v2(r_ref_pos); weight_sum = 0.0f; - for (track = tracking->tracks.first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { if (track->flag & TRACK_USE_2D_STAB) { float weight = 0.0f; MovieTrackingMarker *marker = get_tracking_data_point(ctx, track, framenr, &weight); @@ -680,7 +678,7 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_ int next_lower = MINAFRAME; int next_higher = MAXFRAME; use_values_from_fcurves(ctx, true); - for (track = tracking->tracks.first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { /* Note: we deliberately do not care if this track * is already initialized for stabilization. */ if (track->flag & TRACK_USE_2D_STAB) { @@ -771,11 +769,10 @@ static bool interpolate_averaged_track_contributions(StabContext *ctx, static int establish_track_initialization_order(StabContext *ctx, TrackInitOrder *order) { size_t tracknr = 0; - MovieTrackingTrack *track; MovieTracking *tracking = ctx->tracking; int anchor_frame = tracking->stabilization.anchor_frame; - for (track = tracking->tracks.first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { MovieTrackingMarker *marker; order[tracknr].data = track; marker = get_closest_marker(ctx, track, anchor_frame); @@ -880,10 +877,9 @@ static void initialize_track_for_stabilization(StabContext *ctx, static void initialize_all_tracks(StabContext *ctx, float aspect) { - size_t i, track_len = 0; + size_t track_len = 0; MovieClip *clip = ctx->clip; MovieTracking *tracking = ctx->tracking; - MovieTrackingTrack *track; TrackInitOrder *order; /* Attempt to start initialization at anchor_frame. @@ -896,7 +892,7 @@ static void initialize_all_tracks(StabContext *ctx, float aspect) zero_v2(pivot); /* Initialize private working data. */ - for (track = tracking->tracks.first; track != NULL; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { TrackStabilizationBase *local_data = access_stabilization_baseline_data(ctx, track); if (!local_data) { local_data = MEM_callocN(sizeof(TrackStabilizationBase), @@ -927,8 +923,8 @@ static void initialize_all_tracks(StabContext *ctx, float aspect) average_marker_positions(ctx, reference_frame, average_pos); setup_pivot(average_pos, pivot); - for (i = 0; i < track_len; i++) { - track = order[i].data; + for (int i = 0; i < track_len; i++) { + MovieTrackingTrack *track = order[i].data; if (reference_frame != order[i].reference_frame) { reference_frame = order[i].reference_frame; average_track_contributions(ctx, @@ -1142,12 +1138,11 @@ static float calculate_autoscale_factor(StabContext *ctx, int size, float aspect float pixel_aspect = ctx->tracking->camera.pixel_aspect; int height = size, width = aspect * size; - int sfra = INT_MAX, efra = INT_MIN, cfra; + int sfra = INT_MAX, efra = INT_MIN; float scale = 1.0f, scale_step = 0.0f; - MovieTrackingTrack *track; /* Calculate maximal frame range of tracks where stabilization is active. */ - for (track = ctx->tracking->tracks.first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &ctx->tracking->tracks) { if ((track->flag & TRACK_USE_2D_STAB) || ((stab->flag & TRACKING_STABILIZE_ROTATION) && (track->flag & TRACK_USE_2D_STAB_ROT))) { int first_frame = track->markers[0].framenr; @@ -1158,7 +1153,7 @@ static float calculate_autoscale_factor(StabContext *ctx, int size, float aspect } use_values_from_fcurves(ctx, true); - for (cfra = sfra; cfra <= efra; cfra++) { + for (int cfra = sfra; cfra <= efra; cfra++) { float translation[2], pivot[2], angle, tmp_scale; float mat[4][4]; const float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index ed582dc5b94..ada6ce96d58 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -126,7 +126,6 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking) MovieTrackingTrack *track; ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; ListBase *old_tracks; - int a; if (map->is_camera) { old_tracks = &tracking->tracks; @@ -146,7 +145,7 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking) * this is needed to keep names in unique state and it's faster to change names * of currently operating tracks (if needed) */ - for (a = 0; a < map->num_tracks; a++) { + for (int a = 0; a < map->num_tracks; a++) { MovieTrackingTrack *old_track; bool mapped_to_old = false; @@ -221,11 +220,9 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking) void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata)) { - int i = 0; - BLI_ghash_free(map->hash, NULL, NULL); - for (i = 0; i < map->num_tracks; i++) { + for (int i = 0; i < map->num_tracks; i++) { if (map->customdata && customdata_free) { customdata_free(&map->customdata[i * map->customdata_size]); } @@ -345,12 +342,11 @@ void tracking_get_marker_coords_for_tracking(int frame_width, double search_pixel_x[5], double search_pixel_y[5]) { - int i; float unified_coords[2]; float pixel_coords[2]; /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { marker_unified_to_search_pixel( frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords); search_pixel_x[i] = pixel_coords[0] - 0.5f; @@ -373,12 +369,11 @@ void tracking_set_marker_coords_from_tracking(int frame_width, const double search_pixel_x[5], const double search_pixel_y[5]) { - int i; float marker_unified[2]; float search_pixel[2]; /* Convert the corners into search space coordinates. */ - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { search_pixel[0] = search_pixel_x[i] + 0.5; search_pixel[1] = search_pixel_y[i] + 0.5; search_pixel_to_marker_unified( @@ -394,7 +389,7 @@ void tracking_set_marker_coords_from_tracking(int frame_width, * Otherwise, the entire patch shifted, and that delta should be applied to * all the coordinates. */ - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { marker->pattern_corners[i][0] -= marker_unified[0]; marker->pattern_corners[i][1] -= marker_unified[1]; } @@ -672,8 +667,6 @@ static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor, static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf) { ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0); - size_t size; - int i; BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); @@ -682,13 +675,13 @@ static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf) * * Will generalize it later. */ - size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float); + const size_t size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float); grayscale->channels = 1; if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) { grayscale->mall |= IB_rectfloat; grayscale->flags |= IB_rectfloat; - for (i = 0; i < grayscale->x * grayscale->y; i++) { + for (int i = 0; i < grayscale->x * grayscale->y; i++) { const float *pixel = ibuf->rect_float + ibuf->channels * i; grayscale->rect_float[i] = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2]; @@ -785,14 +778,12 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, clamped_height); } else { - int y; /* TODO(sergey): We don't do any color space or alpha conversion * here. Probably Libmv is better to work in the linear space, * but keep sRGB space here for compatibility for now. */ - for (y = 0; y < clamped_height; y++) { - int x; - for (x = 0; x < clamped_width; x++) { + for (int y = 0; y < clamped_height; y++) { + for (int x = 0; x < clamped_width; x++) { int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y; int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y; int dst_index = (dst_y * width + dst_x) * 4, diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h index 2e756b14424..47bafff3a49 100644 --- a/source/blender/blenlib/BLI_math_color_blend.h +++ b/source/blender/blenlib/BLI_math_color_blend.h @@ -64,53 +64,49 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src2[4]); MINLINE void blend_color_overlay_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_hardlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); -MINLINE void blend_color_burn_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); +MINLINE void blend_color_burn_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4]); MINLINE void blend_color_linearburn_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_dodge_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_screen_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_softlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_pinlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_linearlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_vividlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_difference_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_exclusion_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_color_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); -MINLINE void blend_color_hue_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); +MINLINE void blend_color_hue_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4]); MINLINE void blend_color_saturation_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_luminosity_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]); + const uchar src1[4], + const uchar src2[4]); MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 05ffb02597d..1c518cf1487 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -220,8 +220,8 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets) if (nbuckets > nbuckets_old) { for (i = 0; i < nbuckets_old; i++) { for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { - const unsigned hash = ghash_entryhash(gh, e); - const unsigned bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_entryhash(gh, e); + const uint bucket_index = ghash_bucket_index(gh, hash); e_next = e->next; e->next = buckets_new[bucket_index]; buckets_new[bucket_index] = e; @@ -232,8 +232,8 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets) for (i = 0; i < nbuckets_old; i++) { #ifdef GHASH_USE_MODULO_BUCKETS for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { - const unsigned hash = ghash_entryhash(gh, e); - const unsigned bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_entryhash(gh, e); + const uint bucket_index = ghash_bucket_index(gh, hash); e_next = e->next; e->next = buckets_new[bucket_index]; buckets_new[bucket_index] = e; @@ -241,7 +241,7 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets) #else /* No need to recompute hashes in this case, since our mask is just smaller, * all items in old bucket 'i' will go in same new bucket (i & new_mask)! */ - const unsigned bucket_index = ghash_bucket_index(gh, i); + const uint bucket_index = ghash_bucket_index(gh, i); BLI_assert(!buckets_old[i] || (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i])))); Entry *e; diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index a1c88edca6f..0a496d2bd68 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -224,7 +224,7 @@ MINLINE unsigned int power_of_2_max_u(unsigned int x) return x + 1; } -MINLINE unsigned power_of_2_min_u(unsigned x) +MINLINE unsigned int power_of_2_min_u(unsigned int x) { x |= (x >> 1); x |= (x >> 2); diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c index 7241779b32a..eb82bb81a89 100644 --- a/source/blender/blenlib/intern/math_color_blend_inline.c +++ b/source/blender/blenlib/intern/math_color_blend_inline.c @@ -49,9 +49,7 @@ /* straight alpha byte blending modes */ -MINLINE void blend_color_mix_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_mix_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight over operation */ @@ -64,10 +62,10 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], tmp[2] = (mt * src1[3] * src1[2]) + (t * 255 * src2[2]); tmp[3] = (mt * src1[3]) + (t * 255); - dst[0] = (unsigned char)divide_round_i(tmp[0], tmp[3]); - dst[1] = (unsigned char)divide_round_i(tmp[1], tmp[3]); - dst[2] = (unsigned char)divide_round_i(tmp[2], tmp[3]); - dst[3] = (unsigned char)divide_round_i(tmp[3], 255); + dst[0] = (uchar)divide_round_i(tmp[0], tmp[3]); + dst[1] = (uchar)divide_round_i(tmp[1], tmp[3]); + dst[2] = (uchar)divide_round_i(tmp[2], tmp[3]); + dst[3] = (uchar)divide_round_i(tmp[3], 255); } else { /* no op */ @@ -75,9 +73,7 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], } } -MINLINE void blend_color_add_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_add_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight add operation */ @@ -88,9 +84,9 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], tmp[1] = (src1[1] * 255) + (src2[1] * t); tmp[2] = (src1[2] * 255) + (src2[2] * t); - dst[0] = (unsigned char)min_ii(divide_round_i(tmp[0], 255), 255); - dst[1] = (unsigned char)min_ii(divide_round_i(tmp[1], 255), 255); - dst[2] = (unsigned char)min_ii(divide_round_i(tmp[2], 255), 255); + dst[0] = (uchar)min_ii(divide_round_i(tmp[0], 255), 255); + dst[1] = (uchar)min_ii(divide_round_i(tmp[1], 255), 255); + dst[2] = (uchar)min_ii(divide_round_i(tmp[2], 255), 255); dst[3] = src1[3]; } else { @@ -99,9 +95,7 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], } } -MINLINE void blend_color_sub_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_sub_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight sub operation */ @@ -112,9 +106,9 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], tmp[1] = (src1[1] * 255) - (src2[1] * t); tmp[2] = (src1[2] * 255) - (src2[2] * t); - dst[0] = (unsigned char)max_ii(divide_round_i(tmp[0], 255), 0); - dst[1] = (unsigned char)max_ii(divide_round_i(tmp[1], 255), 0); - dst[2] = (unsigned char)max_ii(divide_round_i(tmp[2], 255), 0); + dst[0] = (uchar)max_ii(divide_round_i(tmp[0], 255), 0); + dst[1] = (uchar)max_ii(divide_round_i(tmp[1], 255), 0); + dst[2] = (uchar)max_ii(divide_round_i(tmp[2], 255), 0); dst[3] = src1[3]; } else { @@ -123,9 +117,7 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], } } -MINLINE void blend_color_mul_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_mul_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight multiply operation */ @@ -137,9 +129,9 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], tmp[1] = (mt * src1[1] * 255) + (t * src1[1] * src2[1]); tmp[2] = (mt * src1[2] * 255) + (t * src1[2] * src2[2]); - dst[0] = (unsigned char)divide_round_i(tmp[0], 255 * 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255 * 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255 * 255); + dst[0] = (uchar)divide_round_i(tmp[0], 255 * 255); + dst[1] = (uchar)divide_round_i(tmp[1], 255 * 255); + dst[2] = (uchar)divide_round_i(tmp[2], 255 * 255); dst[3] = src1[3]; } else { @@ -148,9 +140,7 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], } } -MINLINE void blend_color_lighten_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_lighten_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight lighten operation */ @@ -162,9 +152,9 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], tmp[1] = (mt * src1[1]) + (t * max_ii(src1[1], src2[1])); tmp[2] = (mt * src1[2]) + (t * max_ii(src1[2], src2[2])); - dst[0] = (unsigned char)divide_round_i(tmp[0], 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255); + dst[0] = (uchar)divide_round_i(tmp[0], 255); + dst[1] = (uchar)divide_round_i(tmp[1], 255); + dst[2] = (uchar)divide_round_i(tmp[2], 255); dst[3] = src1[3]; } else { @@ -173,9 +163,7 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], } } -MINLINE void blend_color_darken_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_darken_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight darken operation */ @@ -187,9 +175,9 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], tmp[1] = (mt * src1[1]) + (t * min_ii(src1[1], src2[1])); tmp[2] = (mt * src1[2]) + (t * min_ii(src1[2], src2[2])); - dst[0] = (unsigned char)divide_round_i(tmp[0], 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255); + dst[0] = (uchar)divide_round_i(tmp[0], 255); + dst[1] = (uchar)divide_round_i(tmp[1], 255); + dst[2] = (uchar)divide_round_i(tmp[2], 255); dst[3] = src1[3]; } else { @@ -198,9 +186,7 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], } } -MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_erase_alpha_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight so just modify alpha channel */ @@ -209,7 +195,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], dst[0] = src1[0]; dst[1] = src1[1]; dst[2] = src1[2]; - dst[3] = (unsigned char)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0); + dst[3] = (uchar)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0); } else { /* no op */ @@ -217,9 +203,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], } } -MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4]) +MINLINE void blend_color_add_alpha_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { if (src2[3] != 0) { /* straight so just modify alpha channel */ @@ -228,7 +212,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], dst[0] = src1[0]; dst[1] = src1[1]; dst[2] = src1[2]; - dst[3] = (unsigned char)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255); + dst[3] = (uchar)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255); } else { /* no op */ @@ -236,9 +220,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], } } -MINLINE void blend_color_overlay_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_overlay_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = (int)src2[3]; if (fac != 0) { @@ -254,7 +236,7 @@ MINLINE void blend_color_overlay_byte(unsigned char dst[4], else { temp = (2 * src1[i] * src2[i]) >> 8; } - dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); + dst[i] = (uchar)min_ii((temp * fac + src1[i] * mfac) / 255, 255); } } else { @@ -263,9 +245,7 @@ MINLINE void blend_color_overlay_byte(unsigned char dst[4], } } -MINLINE void blend_color_hardlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_hardlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = (int)src2[3]; if (fac != 0) { @@ -281,7 +261,7 @@ MINLINE void blend_color_hardlight_byte(unsigned char dst[4], else { temp = (2 * src2[i] * src1[i]) >> 8; } - dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); + dst[i] = (uchar)min_ii((temp * fac + src1[i] * mfac) / 255, 255); } } else { @@ -290,9 +270,7 @@ MINLINE void blend_color_hardlight_byte(unsigned char dst[4], } } -MINLINE void blend_color_burn_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_burn_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -301,7 +279,7 @@ MINLINE void blend_color_burn_byte(unsigned char dst[4], while (i--) { const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -310,9 +288,7 @@ MINLINE void blend_color_burn_byte(unsigned char dst[4], } } -MINLINE void blend_color_linearburn_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_linearburn_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -321,7 +297,7 @@ MINLINE void blend_color_linearburn_byte(unsigned char dst[4], while (i--) { const int temp = max_ii(src1[i] + src2[i] - 255, 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -330,9 +306,7 @@ MINLINE void blend_color_linearburn_byte(unsigned char dst[4], } } -MINLINE void blend_color_dodge_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_dodge_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -341,7 +315,7 @@ MINLINE void blend_color_dodge_byte(unsigned char dst[4], while (i--) { const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -350,9 +324,7 @@ MINLINE void blend_color_dodge_byte(unsigned char dst[4], } } -MINLINE void blend_color_screen_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_screen_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -361,7 +333,7 @@ MINLINE void blend_color_screen_byte(unsigned char dst[4], while (i--) { const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -370,9 +342,7 @@ MINLINE void blend_color_screen_byte(unsigned char dst[4], } } -MINLINE void blend_color_softlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_softlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -388,7 +358,7 @@ MINLINE void blend_color_softlight_byte(unsigned char dst[4], else { temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255); } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -397,9 +367,7 @@ MINLINE void blend_color_softlight_byte(unsigned char dst[4], } } -MINLINE void blend_color_pinlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_pinlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -415,7 +383,7 @@ MINLINE void blend_color_pinlight_byte(unsigned char dst[4], else { temp = min_ii(2 * src2[i], src1[i]); } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -424,9 +392,7 @@ MINLINE void blend_color_pinlight_byte(unsigned char dst[4], } } -MINLINE void blend_color_linearlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_linearlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -442,7 +408,7 @@ MINLINE void blend_color_linearlight_byte(unsigned char dst[4], else { temp = max_ii(src1[i] + 2 * src2[i] - 255, 0); } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -451,9 +417,7 @@ MINLINE void blend_color_linearlight_byte(unsigned char dst[4], } } -MINLINE void blend_color_vividlight_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_vividlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -475,7 +439,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], else { temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0); } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -484,9 +448,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], } } -MINLINE void blend_color_difference_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_difference_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -495,7 +457,7 @@ MINLINE void blend_color_difference_byte(unsigned char dst[4], while (i--) { const int temp = abs(src1[i] - src2[i]); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -504,9 +466,7 @@ MINLINE void blend_color_difference_byte(unsigned char dst[4], } } -MINLINE void blend_color_exclusion_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_exclusion_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -515,7 +475,7 @@ MINLINE void blend_color_exclusion_byte(unsigned char dst[4], while (i--) { const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255); } } else { @@ -524,9 +484,7 @@ MINLINE void blend_color_exclusion_byte(unsigned char dst[4], } } -MINLINE void blend_color_color_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_color_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -542,9 +500,9 @@ MINLINE void blend_color_color_byte(unsigned char dst[4], hsv_to_rgb(h1, s1, v1, &r, &g, &b); - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); } else { /* no op */ @@ -552,9 +510,7 @@ MINLINE void blend_color_color_byte(unsigned char dst[4], } } -MINLINE void blend_color_hue_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_hue_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -569,9 +525,9 @@ MINLINE void blend_color_hue_byte(unsigned char dst[4], hsv_to_rgb(h1, s1, v1, &r, &g, &b); - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); } else { /* no op */ @@ -579,9 +535,7 @@ MINLINE void blend_color_hue_byte(unsigned char dst[4], } } -MINLINE void blend_color_saturation_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_saturation_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -598,9 +552,9 @@ MINLINE void blend_color_saturation_byte(unsigned char dst[4], hsv_to_rgb(h1, s1, v1, &r, &g, &b); - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); } else { /* no op */ @@ -608,9 +562,7 @@ MINLINE void blend_color_saturation_byte(unsigned char dst[4], } } -MINLINE void blend_color_luminosity_byte(unsigned char dst[4], - unsigned const char src1[4], - unsigned const char src2[4]) +MINLINE void blend_color_luminosity_byte(uchar dst[4], const uchar src1[4], const uchar src2[4]) { const int fac = src2[3]; if (fac != 0) { @@ -625,9 +577,9 @@ MINLINE void blend_color_luminosity_byte(unsigned char dst[4], hsv_to_rgb(h1, s1, v1, &r, &g, &b); - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); } else { /* no op */ @@ -635,9 +587,9 @@ MINLINE void blend_color_luminosity_byte(unsigned char dst[4], } } -MINLINE void blend_color_interpolate_byte(unsigned char dst[4], - const unsigned char src1[4], - const unsigned char src2[4], +MINLINE void blend_color_interpolate_byte(uchar dst[4], + const uchar src1[4], + const uchar src2[4], float ft) { /* do color interpolation, but in premultiplied space so that RGB colors @@ -647,10 +599,10 @@ MINLINE void blend_color_interpolate_byte(unsigned char dst[4], int tmp = (mt * src1[3] + t * src2[3]); if (tmp > 0) { - dst[0] = (unsigned char)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp); - dst[1] = (unsigned char)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp); - dst[2] = (unsigned char)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp); - dst[3] = (unsigned char)divide_round_i(tmp, 255); + dst[0] = (uchar)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp); + dst[1] = (uchar)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp); + dst[2] = (uchar)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp); + dst[3] = (uchar)divide_round_i(tmp, 255); } else { copy_v4_v4_uchar(dst, src1); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 55f21250659..5919b7e1dd6 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -240,10 +240,7 @@ void interp_v3_v3v3v3_uv( p[2] = v1[2] + ((v2[2] - v1[2]) * uv[0]) + ((v3[2] - v1[2]) * uv[1]); } -void interp_v3_v3v3_uchar(char unsigned target[3], - const unsigned char a[3], - const unsigned char b[3], - const float t) +void interp_v3_v3v3_uchar(uchar target[3], const uchar a[3], const uchar b[3], const float t) { const float s = 1.0f - t; @@ -253,14 +250,10 @@ void interp_v3_v3v3_uchar(char unsigned target[3], } void interp_v3_v3v3_char(char target[3], const char a[3], const char b[3], const float t) { - interp_v3_v3v3_uchar( - (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); + interp_v3_v3v3_uchar((uchar *)target, (const uchar *)a, (const uchar *)b, t); } -void interp_v4_v4v4_uchar(char unsigned target[4], - const unsigned char a[4], - const unsigned char b[4], - const float t) +void interp_v4_v4v4_uchar(uchar target[4], const uchar a[4], const uchar b[4], const float t) { const float s = 1.0f - t; @@ -271,8 +264,7 @@ void interp_v4_v4v4_uchar(char unsigned target[4], } void interp_v4_v4v4_char(char target[4], const char a[4], const char b[4], const float t) { - interp_v4_v4v4_uchar( - (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); + interp_v4_v4v4_uchar((uchar *)target, (const uchar *)a, (const uchar *)b, t); } void mid_v3_v3v3(float v[3], const float v1[3], const float v2[3]) @@ -303,12 +295,12 @@ void mid_v3_v3v3v3v3( v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f; } -void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int nbr) +void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const uint nbr) { const float factor = 1.0f / (float)nbr; zero_v3(r); - for (unsigned int i = 0; i < nbr; i++) { + for (uint i = 0; i < nbr; i++) { madd_v3_v3fl(r, vec_arr[i], factor); } } @@ -1119,10 +1111,10 @@ void range_vn_i(int *array_tar, const int size, const int start) } } -void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start) +void range_vn_u(uint *array_tar, const int size, const uint start) { - unsigned int *array_pt = array_tar + (size - 1); - unsigned int j = start + (unsigned int)(size - 1); + uint *array_pt = array_tar + (size - 1); + uint j = start + (uint)(size - 1); int i = size; while (i--) { *(array_pt--) = j--; @@ -1329,18 +1321,18 @@ void copy_vn_short(short *array_tar, const int size, const short val) } } -void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val) +void copy_vn_ushort(ushort *array_tar, const int size, const ushort val) { - unsigned short *tar = array_tar + (size - 1); + ushort *tar = array_tar + (size - 1); int i = size; while (i--) { *(tar--) = val; } } -void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val) +void copy_vn_uchar(uchar *array_tar, const int size, const uchar val) { - unsigned char *tar = array_tar + (size - 1); + uchar *tar = array_tar + (size - 1); int i = size; while (i--) { *(tar--) = val; diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 63657f33bba..7fc95a33092 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -600,7 +600,7 @@ uint BLI_str_utf8_as_unicode(const char *p) uint BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) { int i, len; - unsigned mask = 0; + uint mask = 0; uint result; const unsigned char c = (unsigned char)*p; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ce878128ae5..9c7e4a35e1f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -121,7 +121,7 @@ #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_library.h" -#include "BKE_library_idmap.h" +#include "BKE_main_idmap.h" #include "BKE_library_override.h" #include "BKE_library_query.h" #include "BKE_main.h" // for Main @@ -2613,7 +2613,29 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p /** \name Read ID * \{ */ -static void lib_link_id(FileData *fd, Main *UNUSED(bmain), ID *id) +static void lib_link_id(FileData *fd, Main *bmain, ID *id); +static void lib_link_nodetree(FileData *fd, Main *bmain, bNodeTree *ntree); +static void lib_link_collection(FileData *fd, Main *bmain, Collection *collection); + +static void lib_link_id_private_id(FileData *fd, Main *bmain, ID *id) +{ + /* Handle 'private IDs'. */ + bNodeTree *nodetree = ntreeFromID(id); + if (nodetree != NULL) { + lib_link_id(fd, bmain, &nodetree->id); + lib_link_nodetree(fd, bmain, nodetree); + } + + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + if (scene->master_collection != NULL) { + lib_link_id(fd, bmain, &scene->master_collection->id); + lib_link_collection(fd, bmain, scene->master_collection); + } + } +} + +static void lib_link_id(FileData *fd, Main *bmain, ID *id) { /* Note: WM IDProperties are never written to file, hence they should always be NULL here. */ BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL); @@ -2628,6 +2650,8 @@ static void lib_link_id(FileData *fd, Main *UNUSED(bmain), ID *id) id->override_library->reference = newlibadr_us(fd, id->lib, id->override_library->reference); id->override_library->storage = newlibadr_us(fd, id->lib, id->override_library->storage); } + + lib_link_id_private_id(fd, bmain, id); } static void direct_link_id_override_property_operation_cb(FileData *fd, void *data) @@ -2646,6 +2670,30 @@ static void direct_link_id_override_property_cb(FileData *fd, void *data) link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb); } +static void direct_link_id(FileData *fd, ID *id); +static void direct_link_nodetree(FileData *fd, bNodeTree *ntree); +static void direct_link_collection(FileData *fd, Collection *collection); + +static void direct_link_id_private_id(FileData *fd, ID *id) +{ + /* Handle 'private IDs'. */ + bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); + if (nodetree != NULL && *nodetree != NULL) { + *nodetree = newdataadr(fd, *nodetree); + direct_link_id(fd, (ID *)*nodetree); + direct_link_nodetree(fd, *nodetree); + } + + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + if (scene->master_collection != NULL) { + scene->master_collection = newdataadr(fd, scene->master_collection); + direct_link_id(fd, &scene->master_collection->id); + direct_link_collection(fd, scene->master_collection); + } + } +} + static void direct_link_id(FileData *fd, ID *id) { /*link direct data of ID properties*/ @@ -2685,6 +2733,9 @@ static void direct_link_id(FileData *fd, ID *id) if (drawdata) { BLI_listbase_clear((ListBase *)drawdata); } + + /* Handle 'private IDs'. */ + direct_link_id_private_id(fd, id); } /** \} */ @@ -3874,14 +3925,9 @@ static void direct_link_camera(FileData *fd, Camera *ca) /** \name Read ID: Light * \{ */ -static void lib_link_light(FileData *fd, Main *bmain, Light *la) +static void lib_link_light(FileData *fd, Main *UNUSED(bmain), Light *la) { la->ipo = newlibadr_us(fd, la->id.lib, la->ipo); // XXX deprecated - old animation system - - if (la->nodetree) { - lib_link_id(fd, bmain, &la->nodetree->id); - lib_link_ntree(fd, la->id.lib, la->nodetree); - } } static void direct_link_light(FileData *fd, Light *la) @@ -3894,12 +3940,6 @@ static void direct_link_light(FileData *fd, Light *la) direct_link_curvemapping(fd, la->curfalloff); } - la->nodetree = newdataadr(fd, la->nodetree); - if (la->nodetree) { - direct_link_id(fd, &la->nodetree->id); - direct_link_nodetree(fd, la->nodetree); - } - la->preview = direct_link_preview_image(fd, la->preview); } @@ -4016,14 +4056,9 @@ static void direct_link_mball(FileData *fd, MetaBall *mb) /** \name Read ID: World * \{ */ -static void lib_link_world(FileData *fd, Main *bmain, World *wrld) +static void lib_link_world(FileData *fd, Main *UNUSED(bmain), World *wrld) { wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system - - if (wrld->nodetree) { - lib_link_id(fd, bmain, &wrld->nodetree->id); - lib_link_ntree(fd, wrld->id.lib, wrld->nodetree); - } } static void direct_link_world(FileData *fd, World *wrld) @@ -4031,12 +4066,6 @@ static void direct_link_world(FileData *fd, World *wrld) wrld->adt = newdataadr(fd, wrld->adt); direct_link_animdata(fd, wrld->adt); - wrld->nodetree = newdataadr(fd, wrld->nodetree); - if (wrld->nodetree) { - direct_link_id(fd, &wrld->nodetree->id); - direct_link_nodetree(fd, wrld->nodetree); - } - wrld->preview = direct_link_preview_image(fd, wrld->preview); BLI_listbase_clear(&wrld->gpumaterial); } @@ -4278,15 +4307,10 @@ static void direct_link_curve(FileData *fd, Curve *cu) /** \name Read ID: Texture * \{ */ -static void lib_link_texture(FileData *fd, Main *bmain, Tex *tex) +static void lib_link_texture(FileData *fd, Main *UNUSED(bmain), Tex *tex) { tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima); tex->ipo = newlibadr_us(fd, tex->id.lib, tex->ipo); // XXX deprecated - old animation system - - if (tex->nodetree) { - lib_link_id(fd, bmain, &tex->nodetree->id); - lib_link_ntree(fd, tex->id.lib, tex->nodetree); - } } static void direct_link_texture(FileData *fd, Tex *tex) @@ -4296,12 +4320,6 @@ static void direct_link_texture(FileData *fd, Tex *tex) tex->coba = newdataadr(fd, tex->coba); - tex->nodetree = newdataadr(fd, tex->nodetree); - if (tex->nodetree) { - direct_link_id(fd, &tex->nodetree->id); - direct_link_nodetree(fd, tex->nodetree); - } - tex->preview = direct_link_preview_image(fd, tex->preview); tex->iuser.ok = 1; @@ -4314,15 +4332,10 @@ static void direct_link_texture(FileData *fd, Tex *tex) /** \name Read ID: Material * \{ */ -static void lib_link_material(FileData *fd, Main *bmain, Material *ma) +static void lib_link_material(FileData *fd, Main *UNUSED(bmain), Material *ma) { ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system - if (ma->nodetree) { - lib_link_id(fd, bmain, &ma->nodetree->id); - lib_link_ntree(fd, ma->id.lib, ma->nodetree); - } - /* relink grease pencil settings */ if (ma->gp_style != NULL) { MaterialGPencilStyle *gp_style = ma->gp_style; @@ -4342,12 +4355,6 @@ static void direct_link_material(FileData *fd, Material *ma) ma->texpaintslot = NULL; - ma->nodetree = newdataadr(fd, ma->nodetree); - if (ma->nodetree) { - direct_link_id(fd, &ma->nodetree->id); - direct_link_nodetree(fd, ma->nodetree); - } - ma->preview = direct_link_preview_image(fd, ma->preview); BLI_listbase_clear(&ma->gpumaterial); @@ -6329,7 +6336,7 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene) } #endif -static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce) +static void lib_link_scene(FileData *fd, Main *UNUSED(bmain), Scene *sce) { lib_link_keyingsets(fd, &sce->id, &sce->keyingsets); @@ -6472,8 +6479,6 @@ static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce) } if (sce->nodetree) { - lib_link_id(fd, bmain, &sce->nodetree->id); - lib_link_ntree(fd, sce->id.lib, sce->nodetree); composite_patch(sce->nodetree, sce); } @@ -6496,11 +6501,6 @@ static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce) } #endif - if (sce->master_collection) { - lib_link_id(fd, bmain, &sce->master_collection->id); - lib_link_collection_data(fd, sce->id.lib, sce->master_collection); - } - for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { lib_link_view_layer(fd, sce->id.lib, view_layer); } @@ -6833,12 +6833,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(srl->freestyleConfig.linesets)); } - sce->nodetree = newdataadr(fd, sce->nodetree); - if (sce->nodetree) { - direct_link_id(fd, &sce->nodetree->id); - direct_link_nodetree(fd, sce->nodetree); - } - direct_link_view_settings(fd, &sce->view_settings); sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world); @@ -6894,13 +6888,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) } #endif - if (sce->master_collection) { - sce->master_collection = newdataadr(fd, sce->master_collection); - /* Needed because this is an ID outside of Main. */ - direct_link_id(fd, &sce->master_collection->id); - direct_link_collection(fd, sce->master_collection); - } - /* insert into global old-new map for reading without UI (link_global accesses it again) */ link_glob_list(fd, &sce->view_layers); for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { @@ -8593,7 +8580,7 @@ static void lib_link_mask(FileData *fd, Main *UNUSED(bmain), Mask *mask) /** \name Read ID: Line Style * \{ */ -static void lib_link_linestyle(FileData *fd, Main *bmain, FreestyleLineStyle *linestyle) +static void lib_link_linestyle(FileData *fd, Main *UNUSED(bmain), FreestyleLineStyle *linestyle) { LineStyleModifier *m; @@ -8634,10 +8621,6 @@ static void lib_link_linestyle(FileData *fd, Main *bmain, FreestyleLineStyle *li mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object); } } - if (linestyle->nodetree) { - lib_link_id(fd, bmain, &linestyle->nodetree->id); - lib_link_ntree(fd, linestyle->id.lib, linestyle->nodetree); - } } static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier *modifier) @@ -8828,11 +8811,6 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle) for (a = 0; a < MAX_MTEX; a++) { linestyle->mtex[a] = newdataadr(fd, linestyle->mtex[a]); } - linestyle->nodetree = newdataadr(fd, linestyle->nodetree); - if (linestyle->nodetree) { - direct_link_id(fd, &linestyle->nodetree->id); - direct_link_nodetree(fd, linestyle->nodetree); - } } /** \} */ @@ -10121,39 +10099,6 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch } } -static void expand_id(FileData *fd, Main *mainvar, ID *id) -{ - if (id->override_library) { - expand_doit(fd, mainvar, id->override_library->reference); - expand_doit(fd, mainvar, id->override_library->storage); - } -} - -static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop) -{ - if (!prop) { - return; - } - - switch (prop->type) { - case IDP_ID: - expand_doit(fd, mainvar, IDP_Id(prop)); - break; - case IDP_IDPARRAY: { - IDProperty *idp_array = IDP_IDPArray(prop); - for (int i = 0; i < prop->len; i++) { - expand_idprops(fd, mainvar, &idp_array[i]); - } - break; - } - case IDP_GROUP: - for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { - expand_idprops(fd, mainvar, loop); - } - break; - } -} - static void expand_fmodifiers(FileData *fd, Main *mainvar, ListBase *list) { FModifier *fcm; @@ -10196,40 +10141,6 @@ static void expand_fcurves(FileData *fd, Main *mainvar, ListBase *list) } } -static void expand_action(FileData *fd, Main *mainvar, bAction *act) -{ - bActionChannel *chan; - - // XXX deprecated - old animation system -------------- - for (chan = act->chanbase.first; chan; chan = chan->next) { - expand_doit(fd, mainvar, chan->ipo); - expand_constraint_channels(fd, mainvar, &chan->constraintChannels); - } - // --------------------------------------------------- - - /* F-Curves in Action */ - expand_fcurves(fd, mainvar, &act->curves); - - for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { - if (marker->camera) { - expand_doit(fd, mainvar, marker->camera); - } - } -} - -static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list) -{ - KeyingSet *ks; - KS_Path *ksp; - - /* expand the ID-pointers in KeyingSets's paths */ - for (ks = list->first; ks; ks = ks->next) { - for (ksp = ks->paths.first; ksp; ksp = ksp->next) { - expand_doit(fd, mainvar, ksp->id); - } - } -} - static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list) { NlaStrip *strip; @@ -10266,6 +10177,104 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) } } +static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop) +{ + if (!prop) { + return; + } + + switch (prop->type) { + case IDP_ID: + expand_doit(fd, mainvar, IDP_Id(prop)); + break; + case IDP_IDPARRAY: { + IDProperty *idp_array = IDP_IDPArray(prop); + for (int i = 0; i < prop->len; i++) { + expand_idprops(fd, mainvar, &idp_array[i]); + } + break; + } + case IDP_GROUP: + for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { + expand_idprops(fd, mainvar, loop); + } + break; + } +} + +static void expand_id(FileData *fd, Main *mainvar, ID *id); +static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree); +static void expand_collection(FileData *fd, Main *mainvar, Collection *collection); + +static void expand_id_private_id(FileData *fd, Main *mainvar, ID *id) +{ + /* Handle 'private IDs'. */ + bNodeTree *nodetree = ntreeFromID(id); + if (nodetree != NULL) { + expand_id(fd, mainvar, &nodetree->id); + expand_nodetree(fd, mainvar, nodetree); + } + + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + if (scene->master_collection != NULL) { + expand_id(fd, mainvar, &scene->master_collection->id); + expand_collection(fd, mainvar, scene->master_collection); + } + } +} + +static void expand_id(FileData *fd, Main *mainvar, ID *id) +{ + expand_idprops(fd, mainvar, id->properties); + + if (id->override_library) { + expand_doit(fd, mainvar, id->override_library->reference); + expand_doit(fd, mainvar, id->override_library->storage); + } + + AnimData *adt = BKE_animdata_from_id(id); + if (adt != NULL) { + expand_animdata(fd, mainvar, adt); + } + + expand_id_private_id(fd, mainvar, id); +} + +static void expand_action(FileData *fd, Main *mainvar, bAction *act) +{ + bActionChannel *chan; + + // XXX deprecated - old animation system -------------- + for (chan = act->chanbase.first; chan; chan = chan->next) { + expand_doit(fd, mainvar, chan->ipo); + expand_constraint_channels(fd, mainvar, &chan->constraintChannels); + } + // --------------------------------------------------- + + /* F-Curves in Action */ + expand_fcurves(fd, mainvar, &act->curves); + + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { + if (marker->camera) { + expand_doit(fd, mainvar, marker->camera); + } + } +} + +static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list) +{ + KeyingSet *ks; + KS_Path *ksp; + + /* expand the ID-pointers in KeyingSets's paths */ + for (ks = list->first; ks; ks = ks->next) { + for (ksp = ks->paths.first; ksp; ksp = ksp->next) { + expand_doit(fd, mainvar, ksp->id); + } + } +} + static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part) { int a; @@ -10276,10 +10285,6 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting expand_doit(fd, mainvar, part->bb_ob); expand_doit(fd, mainvar, part->collision_group); - if (part->adt) { - expand_animdata(fd, mainvar, part->adt); - } - for (a = 0; a < MAX_MTEX; a++) { if (part->mtex[a]) { expand_doit(fd, mainvar, part->mtex[a]->tex); @@ -10343,10 +10348,6 @@ static void expand_collection(FileData *fd, Main *mainvar, Collection *collectio static void expand_key(FileData *fd, Main *mainvar, Key *key) { expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system - - if (key->adt) { - expand_animdata(fd, mainvar, key->adt); - } } static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) @@ -10354,10 +10355,6 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) bNode *node; bNodeSocket *sock; - if (ntree->adt) { - expand_animdata(fd, mainvar, ntree->adt); - } - if (ntree->gpd) { expand_doit(fd, mainvar, ntree->gpd); } @@ -10389,14 +10386,6 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) { expand_doit(fd, mainvar, tex->ima); expand_doit(fd, mainvar, tex->ipo); // XXX deprecated - old animation system - - if (tex->adt) { - expand_animdata(fd, mainvar, tex->adt); - } - - if (tex->nodetree) { - expand_nodetree(fd, mainvar, tex->nodetree); - } } static void expand_brush(FileData *fd, Main *mainvar, Brush *brush) @@ -10414,14 +10403,6 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma) { expand_doit(fd, mainvar, ma->ipo); // XXX deprecated - old animation system - if (ma->adt) { - expand_animdata(fd, mainvar, ma->adt); - } - - if (ma->nodetree) { - expand_nodetree(fd, mainvar, ma->nodetree); - } - if (ma->gp_style) { MaterialGPencilStyle *gp_style = ma->gp_style; expand_doit(fd, mainvar, gp_style->sima); @@ -10432,37 +10413,17 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma) static void expand_light(FileData *fd, Main *mainvar, Light *la) { expand_doit(fd, mainvar, la->ipo); // XXX deprecated - old animation system - - if (la->adt) { - expand_animdata(fd, mainvar, la->adt); - } - - if (la->nodetree) { - expand_nodetree(fd, mainvar, la->nodetree); - } } static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt) { expand_doit(fd, mainvar, lt->ipo); // XXX deprecated - old animation system expand_doit(fd, mainvar, lt->key); - - if (lt->adt) { - expand_animdata(fd, mainvar, lt->adt); - } } static void expand_world(FileData *fd, Main *mainvar, World *wrld) { expand_doit(fd, mainvar, wrld->ipo); // XXX deprecated - old animation system - - if (wrld->adt) { - expand_animdata(fd, mainvar, wrld->adt); - } - - if (wrld->nodetree) { - expand_nodetree(fd, mainvar, wrld->nodetree); - } } static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb) @@ -10472,10 +10433,6 @@ static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb) for (a = 0; a < mb->totcol; a++) { expand_doit(fd, mainvar, mb->mat[a]); } - - if (mb->adt) { - expand_animdata(fd, mainvar, mb->adt); - } } static void expand_curve(FileData *fd, Main *mainvar, Curve *cu) @@ -10495,20 +10452,12 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu) expand_doit(fd, mainvar, cu->bevobj); expand_doit(fd, mainvar, cu->taperobj); expand_doit(fd, mainvar, cu->textoncurve); - - if (cu->adt) { - expand_animdata(fd, mainvar, cu->adt); - } } static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me) { int a; - if (me->adt) { - expand_animdata(fd, mainvar, me->adt); - } - for (a = 0; a < me->totcol; a++) { expand_doit(fd, mainvar, me->mat[a]); } @@ -10577,10 +10526,6 @@ static void expand_bones(FileData *fd, Main *mainvar, Bone *bone) static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm) { - if (arm->adt) { - expand_animdata(fd, mainvar, arm->adt); - } - for (Bone *curBone = arm->bonebase.first; curBone; curBone = curBone->next) { expand_bones(fd, mainvar, curBone); } @@ -10666,10 +10611,6 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) } // XXX deprecated - old animation system (for version patching only) - if (ob->adt) { - expand_animdata(fd, mainvar, ob->adt); - } - for (a = 0; a < ob->totcol; a++) { expand_doit(fd, mainvar, ob->mat[a]); } @@ -10745,19 +10686,12 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) expand_doit(fd, mainvar, sce->camera); expand_doit(fd, mainvar, sce->world); - if (sce->adt) { - expand_animdata(fd, mainvar, sce->adt); - } expand_keyingsets(fd, mainvar, &sce->keyingsets); if (sce->set) { expand_doit(fd, mainvar, sce->set); } - if (sce->nodetree) { - expand_nodetree(fd, mainvar, sce->nodetree); - } - for (srl = sce->r.layers.first; srl; srl = srl->next) { expand_doit(fd, mainvar, srl->mat_override); for (module = srl->freestyleConfig.modules.first; module; module = module->next) { @@ -10843,10 +10777,6 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) } #endif - if (sce->master_collection) { - expand_collection(fd, mainvar, sce->master_collection); - } - if (sce->r.bake.cage_object) { expand_doit(fd, mainvar, sce->r.bake.cage_object); } @@ -10864,26 +10794,17 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) expand_doit(fd, mainvar, bgpic->ima); } } - - if (ca->adt) { - expand_animdata(fd, mainvar, ca->adt); - } } -static void expand_cachefile(FileData *fd, Main *mainvar, CacheFile *cache_file) +static void expand_cachefile(FileData *UNUSED(fd), + Main *UNUSED(mainvar), + CacheFile *UNUSED(cache_file)) { - if (cache_file->adt) { - expand_animdata(fd, mainvar, cache_file->adt); - } } static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk) { expand_doit(fd, mainvar, spk->sound); - - if (spk->adt) { - expand_animdata(fd, mainvar, spk->adt); - } } static void expand_sound(FileData *fd, Main *mainvar, bSound *snd) @@ -10891,18 +10812,12 @@ static void expand_sound(FileData *fd, Main *mainvar, bSound *snd) expand_doit(fd, mainvar, snd->ipo); // XXX deprecated - old animation system } -static void expand_lightprobe(FileData *fd, Main *mainvar, LightProbe *prb) +static void expand_lightprobe(FileData *UNUSED(fd), Main *UNUSED(mainvar), LightProbe *UNUSED(prb)) { - if (prb->adt) { - expand_animdata(fd, mainvar, prb->adt); - } } -static void expand_movieclip(FileData *fd, Main *mainvar, MovieClip *clip) +static void expand_movieclip(FileData *UNUSED(fd), Main *UNUSED(mainvar), MovieClip *UNUSED(clip)) { - if (clip->adt) { - expand_animdata(fd, mainvar, clip->adt); - } } static void expand_mask_parent(FileData *fd, Main *mainvar, MaskParent *parent) @@ -10916,10 +10831,6 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask) { MaskLayer *mask_layer; - if (mask->adt) { - expand_animdata(fd, mainvar, mask->adt); - } - for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) { MaskSpline *spline; @@ -10948,13 +10859,7 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li expand_doit(fd, mainvar, linestyle->mtex[a]->object); } } - if (linestyle->nodetree) { - expand_nodetree(fd, mainvar, linestyle->nodetree); - } - if (linestyle->adt) { - expand_animdata(fd, mainvar, linestyle->adt); - } for (m = linestyle->color_modifiers.first; m; m = m->next) { if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { expand_doit(fd, mainvar, ((LineStyleColorModifier_DistanceFromObject *)m)->target); @@ -10974,10 +10879,6 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd) { - if (gpd->adt) { - expand_animdata(fd, mainvar, gpd->adt); - } - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { expand_doit(fd, mainvar, gpl->parent); } @@ -11030,7 +10931,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) while (id) { if (id->tag & LIB_TAG_NEED_EXPAND) { expand_id(fd, mainvar, id); - expand_idprops(fd, mainvar, id->properties); switch (GS(id->name)) { case ID_OB: diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 8cbbf765f66..d14b7a51a94 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -476,7 +476,7 @@ BMLog *BM_log_create(BMesh *bm) BMLog *log = MEM_callocN(sizeof(*log), __func__); const uint reserve_num = (uint)(bm->totvert + bm->totface); - log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); + log->unused_ids = range_tree_uint_alloc(0, (uint)-1); log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num); log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num); @@ -618,7 +618,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) /* Create BMVert index remap array */ id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert); BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { - const unsigned id = bm_log_vert_id_get(log, v); + const uint id = bm_log_vert_id_get(log, v); const void *key = POINTER_FROM_UINT(id); const void *val = BLI_ghash_lookup(id_to_idx, key); varr[i] = POINTER_AS_UINT(val); @@ -628,7 +628,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) /* Create BMFace index remap array */ id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface); BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { - const unsigned id = bm_log_face_id_get(log, f); + const uint id = bm_log_face_id_get(log, f); const void *key = POINTER_FROM_UINT(id); const void *val = BLI_ghash_lookup(id_to_idx, key); farr[i] = POINTER_AS_UINT(val); @@ -1039,7 +1039,7 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v) { BMLogEntry *entry = log->current_entry; const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = POINTER_FROM_UINT(v_id); BLI_assert(entry); @@ -1057,7 +1057,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v) { BMLogEntry *entry = log->current_entry; const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = POINTER_FROM_UINT(v_id); BLI_assert(entry); @@ -1075,7 +1075,7 @@ float BM_log_original_mask(BMLog *log, BMVert *v) { BMLogEntry *entry = log->current_entry; const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = POINTER_FROM_UINT(v_id); BLI_assert(entry); @@ -1090,7 +1090,7 @@ void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const { BMLogEntry *entry = log->current_entry; const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = POINTER_FROM_UINT(v_id); BLI_assert(entry); diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 374c912e3f5..f6ed95d322d 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -1298,7 +1298,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, if (use_partial_connect) { for (uint i = 0; i < edge_net_init_len; i++) { - for (unsigned j = 0; j < 2; j++) { + for (uint j = 0; j < 2; j++) { BMVert *v_delimit = (&edge_arr[i]->v1)[j]; BMVert *v_other; diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index d5cbe947293..8b4a59d5b9b 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -86,7 +86,7 @@ enum { } \ (void)0 -void poly_rotate_plane(const float normal[3], float (*verts)[3], unsigned const int nverts); +void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts); /* include the rest of our private declarations */ #include "bmesh_structure.h" diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index e52467614ac..2f0b21667e4 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -41,7 +41,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate) { - const unsigned pair_split_max = f->len / 2; + const uint pair_split_max = f->len / 2; BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max); STACK_DECLARE(loops_split); BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max); diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index c3d19862ffb..adc612cfb54 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -205,7 +205,7 @@ static void barycentric_weights_v2_grid_cache(const uint xtot, static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const uint xtot, - unsigned const int ytot, + const uint ytot, const short mat_nr, const bool use_smooth, const bool use_flip, diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 848669301c3..efb8b810581 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -260,7 +260,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMEdge *e; /* data: edge-to-join, sort_value: error weight */ struct SortPtrByFloat *jedges; - unsigned i, totedge; + uint i, totedge; uint totedge_tag = 0; struct DelimitData delimit_data = {0}; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 2cc86a7c93f..e2741b806c2 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -177,8 +177,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool #else BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); - unsigned vert_seek_a_tot = 0; - unsigned vert_seek_b_tot = 0; + uint vert_seek_a_tot = 0; + uint vert_seek_b_tot = 0; #endif BMIter iter; diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index 4f70281fb45..286bcbfb759 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -79,7 +79,8 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) error_context = "File access"; } - else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_REQUIRED_ATTRIBUTE_MISSING) { + else if (parserError.getErrorType() == + GeneratedSaxParser::ParserError::ERROR_REQUIRED_ATTRIBUTE_MISSING) { isError = true; } diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index c76cb8c80a6..32f5463a0e7 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -279,7 +279,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) const std::string &name = bc_get_dae_name(mesh); - for (unsigned i = 0; i < prim_arr.getCount(); i++) { + for (unsigned int i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType(); @@ -683,7 +683,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) // XXX The proper function of TRIANGLE_FANS is not tested!!! // XXX In particular the handling of the normal_indices looks very wrong to me if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { - unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount(); + unsigned int grouped_vertex_count = mp->getGroupedVertexElementsCount(); for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) { unsigned int first_vertex = position_indices[0]; // Store first trifan vertex unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index fcdf24d2d2f..05494b79af0 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -665,7 +665,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; } - WORKBENCH_MaterialData *material; + WORKBENCH_MaterialData *material = NULL; if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && !DRW_state_is_image_render(); diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 941a6741998..1fb0b394cb1 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -69,63 +69,6 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd, } copy_v3_v3(wd->ambient_color, studiolight->light_ambient); - -#if 0 - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED); - -# if STUDIOLIGHT_SH_BANDS == 2 - /* Use Geomerics non-linear SH. */ - mul_v3_v3fl(wd->spherical_harmonics_coefs[0], sl->spherical_harmonics_coefs[0], M_1_PI); - /* Swizzle to make shader code simpler. */ - for (int i = 0; i < 3; i++) { - copy_v3_fl3(wd->spherical_harmonics_coefs[i + 1], - -sl->spherical_harmonics_coefs[3][i], - sl->spherical_harmonics_coefs[2][i], - -sl->spherical_harmonics_coefs[1][i]); - - /* 1.5f is to improve the contrast a bit. */ - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], M_1_PI * 1.5f); - } - - /* Precompute as much as we can. See shader code for derivation. */ - float len_r1[3], lr1_r0[3], p[3], a[3]; - for (int i = 0; i < 3; i++) { - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 0.5f); - len_r1[i] = len_v3(wd->spherical_harmonics_coefs[i + 1]); - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 1.0f / len_r1[i]); - } - /* lr1_r0 = lenR1 / R0; */ - copy_v3_v3(lr1_r0, wd->spherical_harmonics_coefs[0]); - invert_v3(lr1_r0); - mul_v3_v3(lr1_r0, len_r1); - /* p = 1.0 + 2.0 * lr1_r0; */ - copy_v3_v3(p, lr1_r0); - mul_v3_fl(p, 2.0f); - add_v3_fl(p, 1.0f); - /* a = (1.0 - lr1_r0) / (1.0 + lr1_r0); */ - copy_v3_v3(a, lr1_r0); - add_v3_fl(a, 1.0f); - invert_v3(a); - negate_v3(lr1_r0); - add_v3_fl(lr1_r0, 1.0f); - mul_v3_v3(a, lr1_r0); - /* sh_coefs[4] = p; */ - copy_v3_v3(wd->spherical_harmonics_coefs[4], p); - /* sh_coefs[5] = R0 * a; */ - mul_v3_v3v3(wd->spherical_harmonics_coefs[5], wd->spherical_harmonics_coefs[0], a); - /* sh_coefs[0] = R0 * (1.0 - a) * (p + 1.0); */ - negate_v3(a); - add_v3_fl(a, 1.0f); - add_v3_fl(p, 1.0f); - mul_v3_v3(a, p); - mul_v3_v3(wd->spherical_harmonics_coefs[0], a); -# else - for (int i = 0; i < STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN; i++) { - /* Can't memcpy because of alignment */ - copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]); - } -# endif -#endif } static void compute_parallel_lines_nor_and_dist(const float v1[2], diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index d2d8972c245..de7d2e1a395 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -72,7 +72,7 @@ void ED_init_standard_node_socket_type(struct bNodeSocketType *stype); void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype); void ED_node_sample_set(const float col[4]); void ED_node_draw_snap( - struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos); + struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos); /* node_draw.c */ void ED_node_tree_update(const struct bContext *C); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 37ffb1b9d6d..622b64f547f 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -452,7 +452,7 @@ float ED_view3d_radius_to_dist(const struct View3D *v3d, const bool use_aspect, const float radius); -void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned int pos); /* backbuffer select and draw support */ void ED_view3d_backbuf_depth_validate(struct ViewContext *vc); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index a23bd7dad35..8af3664d41b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1343,7 +1343,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s uchar grid_line_color[3]; /* Make an estimate of at least how many vertices will be needed */ - unsigned vertex_count = 4; + uint vertex_count = 4; vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1); vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 0c564bb7593..bd8017acd28 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3935,7 +3935,10 @@ static Base *mesh_separate_tagged( /* DAG_relations_tag_update(bmain); */ /* new in 2.5 */ - BKE_object_material_array_assign(bmain, base_new->object, BKE_object_material_array(obedit), *BKE_object_material_num(obedit)); + BKE_object_material_array_assign(bmain, + base_new->object, + BKE_object_material_array(obedit), + *BKE_object_material_num(obedit)); ED_object_base_select(base_new, BA_SELECT); @@ -4002,7 +4005,10 @@ static Base *mesh_separate_arrays(Main *bmain, /* DAG_relations_tag_update(bmain); */ /* new in 2.5 */ - BKE_object_material_array_assign(bmain, base_new->object, BKE_object_material_array(obedit), *BKE_object_material_num(obedit)); + BKE_object_material_array_assign(bmain, + base_new->object, + BKE_object_material_array(obedit), + *BKE_object_material_num(obedit)); ED_object_base_select(base_new, BA_SELECT); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 05fa78aab1c..9ccbc7a1a0a 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -701,7 +701,7 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext * PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free, - const unsigned int selection_mask) + const uint selection_mask) { Object *ob; EnumPropertyItem *item = NULL; @@ -1807,10 +1807,10 @@ static void vgroup_smooth_subset(Object *ob, float *weight_accum_prev; float *weight_accum_curr; - unsigned int subset_index; + uint subset_index; /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */ - unsigned int *verts_used; + uint *verts_used; STACK_DECLARE(verts_used); BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map); @@ -1882,12 +1882,12 @@ static void vgroup_smooth_subset(Object *ob, memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot); for (iter = 0; iter < repeat; iter++) { - unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used); + uint *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used); /* avoid looping over all verts */ // for (i = 0; i < dvert_tot; i++) for (vi_step = verts_used; vi_step != vi_end; vi_step++) { - const unsigned int i = *vi_step; + const uint i = *vi_step; float weight_tot = 0.0f; float weight = 0.0f; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 3ea583e5b1f..96bc5648b75 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -465,7 +465,8 @@ static Scene *preview_prepare_scene( copy_v4_v4(base->object->color, sp->color); if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) { - /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI */ + /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI + */ Material ***matar = BKE_object_material_array(base->object); int actcol = max_ii(base->object->actcol - 1, 0); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 4fef9a7b741..7059ebb4fb2 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -3362,7 +3362,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float if (count_fine > 0) { GPU_vertformat_clear(format); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 015657318b2..cf66ba14328 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -291,7 +291,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, for (i = 0; i < ss->pmap[(int)index].count; i++) { const MPoly *p = &ss->mpoly[vert_map->indices[i]]; - unsigned f_adj_v[2]; + uint f_adj_v[2]; if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) { int j; for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { @@ -2203,7 +2203,7 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob) /* For the smooth brush, uses the neighboring vertices around vert to calculate * a smoothed location for vert. Skips corner vertices (used by only one * polygon.) */ -static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert) +static void neighbor_average(SculptSession *ss, float avg[3], uint vert) { const MeshElemMap *vert_map = &ss->pmap[vert]; const MVert *mvert = ss->mvert; @@ -2217,7 +2217,7 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert) for (i = 0; i < vert_map->count; i++) { const MPoly *p = &ss->mpoly[vert_map->indices[i]]; - unsigned f_adj_v[2]; + uint f_adj_v[2]; if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) { int j; @@ -2243,7 +2243,7 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert) /* Similar to neighbor_average(), but returns an averaged mask value * instead of coordinate. Also does not restrict based on border or * corner vertices. */ -static float neighbor_average_mask(SculptSession *ss, unsigned vert) +static float neighbor_average_mask(SculptSession *ss, uint vert) { const float *vmask = ss->vmask; float avg = 0; @@ -2251,7 +2251,7 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert) for (i = 0; i < ss->pmap[vert].count; i++) { const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]]; - unsigned f_adj_v[2]; + uint f_adj_v[2]; if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) { int j; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 901efbdf0ff..f06b1a02675 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -546,6 +546,12 @@ static void action_listener(wmWindow *UNUSED(win), break; case NC_SCENE: switch (wmn->data) { + case ND_SEQUENCER: + if (wmn->action == NA_SELECTED) { + saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; + ED_area_tag_refresh(sa); + } + break; case ND_OB_ACTIVE: case ND_OB_SELECT: /* Selection changed, so force refresh to flush diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 42a1566629a..8dd5a7c7d0c 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -164,7 +164,7 @@ static void set_fcurve_vertex_color(FCurve *fcu, bool sel) } static void draw_fcurve_selected_keyframe_vertices( - FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos) + FCurve *fcu, View2D *v2d, bool edit, bool sel, uint pos) { const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); @@ -200,7 +200,7 @@ static void draw_fcurve_selected_keyframe_vertices( } /* helper func - draw keyframe vertices only for an F-Curve */ -static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos) +static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, uint pos) { immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); @@ -214,7 +214,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ static void draw_fcurve_selected_handle_vertices( - FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos) + FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, uint pos) { (void)v2d; /* TODO: use this to draw only points in view */ @@ -259,10 +259,7 @@ static void draw_fcurve_selected_handle_vertices( } /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ -static void draw_fcurve_handle_vertices(FCurve *fcu, - View2D *v2d, - bool sel_handle_only, - unsigned pos) +static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, uint pos) { /* smooth outlines for more consistent appearance */ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); @@ -353,7 +350,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) BezTriple *bezt = fcu->bezt, *prevbezt = NULL; int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE; const float *fp; - unsigned char col[4]; + uchar col[4]; for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) { /* if only selected keyframes can get their handles shown, @@ -428,7 +425,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) * have a consistent appearance (due to off-pixel alignments)... */ static void draw_fcurve_sample_control( - float x, float y, float xscale, float yscale, float hsize, unsigned int pos) + float x, float y, float xscale, float yscale, float hsize, uint pos) { /* adjust view transform before starting */ GPU_matrix_push(); @@ -491,8 +488,7 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu) /* Helper func - just draw the F-Curve by sampling the visible region * (for drawing curves with modifiers). */ -static void draw_fcurve_curve( - bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, unsigned int pos) +static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos) { SpaceGraph *sipo = (SpaceGraph *)ac->sl; float samplefreq; @@ -684,8 +680,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu) } /* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */ -static void draw_fcurve_curve_bezts( - bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos) +static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos) { BezTriple *prevbezt = fcu->bezt; BezTriple *bezt = prevbezt + 1; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 3f563fe9033..c455b7d7c54 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -147,7 +147,7 @@ void ED_image_draw_info(Scene *scene, int channels, int x, int y, - const unsigned char cp[4], + const uchar cp[4], const float fp[4], const float linearcol[4], int *zp, @@ -164,13 +164,13 @@ void ED_image_draw_info(Scene *scene, /* text colors */ /* XXX colored text not allowed in Blender UI */ #if 0 - unsigned char red[3] = {255, 50, 50}; - unsigned char green[3] = {0, 255, 0}; - unsigned char blue[3] = {100, 100, 255}; + uchar red[3] = {255, 50, 50}; + uchar green[3] = {0, 255, 0}; + uchar blue[3] = {100, 100, 255}; #else - unsigned char red[3] = {255, 255, 255}; - unsigned char green[3] = {255, 255, 255}; - unsigned char blue[3] = {255, 255, 255}; + uchar red[3] = {255, 255, 255}; + uchar green[3] = {255, 255, 255}; + uchar blue[3] = {255, 255, 255}; #endif float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0; float col[4], finalcol[4]; @@ -613,7 +613,7 @@ static void draw_image_buffer(const bContext *C, } else { float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char *display_buffer; + uchar *display_buffer; void *cache_handle; ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; @@ -760,7 +760,7 @@ static void draw_image_paint_helpers( float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha}; UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); - unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + uchar *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (!display_buffer) { BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); @@ -794,8 +794,8 @@ static void draw_image_paint_helpers( } } -static void draw_udim_tile_grid(unsigned int pos_attr, - unsigned int color_attr, +static void draw_udim_tile_grid(uint pos_attr, + uint color_attr, ARegion *ar, int x, int y, @@ -832,8 +832,8 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima) float stepy = BLI_rcti_size_y(&ar->v2d.mask) / BLI_rctf_size_y(&ar->v2d.cur); GPUVertFormat *format = immVertexFormat(); - unsigned int pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, 8 * num_tiles); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 35c9082b54c..121c597c1bb 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -376,7 +376,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp const int font_size = data->label_size / aspect; const float margin = (float)(NODE_DY / 4); int label_height; - unsigned char color[3]; + uchar color[3]; nodeLabel(ntree, node, label, sizeof(label)); @@ -3483,7 +3483,7 @@ void draw_nodespace_back_pix(const bContext *C, y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof; if (ibuf->rect || ibuf->rect_float) { - unsigned char *display_buffer = NULL; + uchar *display_buffer = NULL; void *cache_handle = NULL; if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) { @@ -3707,11 +3707,11 @@ static struct { GPUBatch *batch; /* for batching line together */ GPUBatch *batch_single; /* for single line */ GPUVertBuf *inst_vbo; - unsigned int p0_id, p1_id, p2_id, p3_id; - unsigned int colid_id; + uint p0_id, p1_id, p2_id, p3_id; + uint colid_id; GPUVertBufRaw p0_step, p1_step, p2_step, p3_step; GPUVertBufRaw colid_step; - unsigned int count; + uint count; bool enabled; } g_batch_link = {0}; @@ -3727,11 +3727,11 @@ static void nodelink_batch_reset(void) } static void set_nodelink_vertex(GPUVertBuf *vbo, - unsigned int uv_id, - unsigned int pos_id, - unsigned int exp_id, - unsigned int v, - const unsigned char uv[2], + uint uv_id, + uint pos_id, + uint exp_id, + uint v, + const uchar uv[2], const float pos[2], const float exp[2]) { @@ -3756,7 +3756,7 @@ static void nodelink_batch_init(void) int v = 0; for (int k = 0; k < 2; k++) { - unsigned char uv[2] = {0, 0}; + uchar uv[2] = {0, 0}; float pos[2] = {0.0f, 0.0f}; float exp[2] = {0.0f, 1.0f}; @@ -4000,8 +4000,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } -void ED_node_draw_snap( - View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos) +void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, uint pos) { immBegin(GPU_PRIM_LINES, 4); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 2081c69a1a4..6e165df3e2b 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -722,18 +722,18 @@ static void node_socket_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, - unsigned pos_id, - unsigned col_id, - unsigned shape_id, - unsigned size_id, - unsigned outline_col_id, + uint pos_id, + uint col_id, + uint shape_id, + uint size_id, + uint outline_col_id, float size, bool selected) { PointerRNA ptr; float color[4]; float outline_color[4]; - unsigned int flags = 0; + uint flags = 0; RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 5c6e7d94f59..67e5b5045d4 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2703,7 +2703,7 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle, color); /* Now the numbers. */ - unsigned char text_col[4]; + uchar text_col[4]; UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); text_col[3] = 255; @@ -2956,7 +2956,7 @@ static void outliner_draw_tree_element(bContext *C, float ufac = UI_UNIT_X / 20.0f; int offsx = 0; eOLDrawState active = OL_DRAWSEL_NONE; - unsigned char text_color[4]; + uchar text_color[4]; UI_GetThemeColor4ubv(TH_TEXT, text_color); float icon_bgcolor[4], icon_border[4]; outliner_icon_background_colors(icon_bgcolor, icon_border); @@ -3211,11 +3211,11 @@ static void outliner_draw_tree_element(bContext *C, } } -static void outliner_draw_hierarchy_lines_recursive(unsigned pos, +static void outliner_draw_hierarchy_lines_recursive(uint pos, SpaceOutliner *soops, ListBase *lb, int startx, - const unsigned char col[4], + const uchar col[4], bool draw_grayed_out, int *starty) { @@ -3237,7 +3237,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, dash.step_len = UI_UNIT_X / dash.steps_num; dash.gap_len = dash.step_len / 2; - const unsigned char grayed_alpha = col[3] / 2; + const uchar grayed_alpha = col[3] / 2; /* For vertical lines between objects. */ y1 = y2 = y1_dashed = y2_dashed = *starty; @@ -3319,7 +3319,7 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *soops, { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - unsigned char col[4]; + uchar col[4]; immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col); @@ -3372,7 +3372,7 @@ static void outliner_draw_struct_marks(ARegion *ar, } } -static void outliner_draw_highlights_recursive(unsigned pos, +static void outliner_draw_highlights_recursive(uint pos, const ARegion *ar, const SpaceOutliner *soops, const ListBase *lb, diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 95d7f79f666..9e3c9d6725d 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -48,7 +48,6 @@ set(SRC view3d_buttons.c view3d_camera_control.c view3d_draw.c - view3d_draw_legacy.c view3d_edit.c view3d_fly.c view3d_gizmo_armature.c diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 2cdfd8039c1..0daa5aa53ae 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -87,7 +87,7 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], } } -void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos) { float verts[CIRCLE_RESOL][3]; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 0e5592abfd2..d092de4fcce 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -33,7 +33,9 @@ #include "BKE_camera.h" #include "BKE_collection.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_key.h" #include "BKE_main.h" #include "BKE_scene.h" @@ -56,11 +58,13 @@ #include "DNA_windowmanager_types.h" #include "DRW_engine.h" +#include "DRW_select_buffer.h" #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" #include "ED_screen.h" +#include "ED_screen_types.h" #include "ED_transform.h" #include "DEG_depsgraph_query.h" @@ -1936,11 +1940,454 @@ static bool view3d_clipping_test(const float co[3], const float clip[6][4]) return true; } -/* for 'local' ED_view3d_clipping_local must run first - * then all comparisons can be done in localspace */ +/* For 'local' ED_view3d_clipping_local must run first + * then all comparisons can be done in localspace. */ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) { return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } +void ED_view3d_clipping_set(RegionView3D *UNUSED(rv3d)) +{ + for (uint a = 0; a < 6; a++) { + glEnable(GL_CLIP_DISTANCE0 + a); + } +} + +/* Use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set. */ +void ED_view3d_clipping_disable(void) +{ + for (uint a = 0; a < 6; a++) { + glDisable(GL_CLIP_DISTANCE0 + a); + } +} +void ED_view3d_clipping_enable(void) +{ + for (uint a = 0; a < 6; a++) { + glEnable(GL_CLIP_DISTANCE0 + a); + } +} + +/* *********************** backdraw for selection *************** */ + +/** + * \note Only use in object mode. + */ +static void validate_object_select_id( + struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact) +{ + Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); + + BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + UNUSED_VARS_NDEBUG(ar); + + if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || + BKE_paint_select_face_test(obact_eval))) { + /* do nothing */ + } + /* texture paint mode sampling */ + else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && + (v3d->shading.type > OB_WIRE)) { + /* do nothing */ + } + else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { + /* do nothing */ + } + else { + v3d->flag &= ~V3D_INVALID_BACKBUF; + return; + } + + if (!(v3d->flag & V3D_INVALID_BACKBUF)) { + return; + } + + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { + Base *base = BKE_view_layer_base_find(view_layer, obact); + DRW_select_buffer_context_create(&base, 1, -1); + } + + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + v3d->flag &= ~V3D_INVALID_BACKBUF; +} + +/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. + * Calling this function should be avoided during interactive drawing. */ +static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) +{ + DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); + + GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); + GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); + GPU_framebuffer_bind(tmp_fb); + + glReadPixels(rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + GL_DEPTH_COMPONENT, + GL_FLOAT, + data); + + GPU_framebuffer_restore(); + GPU_framebuffer_free(tmp_fb); +} + +void ED_view3d_select_id_validate(ViewContext *vc) +{ + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact); + } +} + +void ED_view3d_backbuf_depth_validate(ViewContext *vc) +{ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + ARegion *ar = vc->ar; + Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval); + } + + vc->v3d->flag &= ~V3D_INVALID_BACKBUF; + } +} + +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + +/* *********************** */ + +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + /* clamp rect by region */ + rcti r = { + .xmin = 0, + .xmax = ar->winx - 1, + .ymin = 0, + .ymax = ar->winy - 1, + }; + + /* Constrain rect to depth bounds */ + BLI_rcti_isect(&r, rect, rect); + + /* assign values to compare with the ViewDepths */ + int x = rect->xmin; + int y = rect->ymin; + + int w = BLI_rcti_size_x(rect); + int h = BLI_rcti_size_y(rect); + + if (w <= 0 || h <= 0) { + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = NULL; + + d->damaged = false; + } + else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { + d->x = x; + d->y = y; + d->w = w; + d->h = h; + + if (d->depths) { + MEM_freeN(d->depths); + } + + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + + d->damaged = true; + } + + if (d->damaged) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + view3d_opengl_read_Z_pixels(viewport, rect, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } +} + +/* Note, with nouveau drivers the glReadPixels() is very slow. [#24339]. */ +void ED_view3d_depth_update(ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + /* Create storage for, and, if necessary, copy depth buffer. */ + if (!rv3d->depths) { + rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + } + if (rv3d->depths) { + ViewDepths *d = rv3d->depths; + if (d->w != ar->winx || d->h != ar->winy || !d->depths) { + d->w = ar->winx; + d->h = ar->winy; + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); + d->damaged = true; + } + + if (d->damaged) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + rcti r = { + .xmin = 0, + .xmax = d->w, + .ymin = 0, + .ymax = d->h, + }; + view3d_opengl_read_Z_pixels(viewport, &r, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } + } +} + +/* Utility function to find the closest Z value, use for autodepth. */ +float view3d_depth_near(ViewDepths *d) +{ + /* Convert to float for comparisons. */ + const float near = (float)d->depth_range[0]; + const float far_real = (float)d->depth_range[1]; + float far = far_real; + + const float *depths = d->depths; + float depth = FLT_MAX; + int i = (int)d->w * (int)d->h; /* Cast to avoid short overflow. */ + + /* Far is both the starting 'far' value + * and the closest value found. */ + while (i--) { + depth = *depths++; + if ((depth < far) && (depth > near)) { + far = depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + +void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) +{ + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); + + GPU_clear(GPU_DEPTH_BIT); + + GPU_depth_test(true); + + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); + + GPU_depth_test(false); +} + +/* *********************** customdata **************** */ + +void ED_view3d_datamask(const bContext *C, + const Scene *UNUSED(scene), + const View3D *v3d, + CustomData_MeshMasks *r_cddata_masks) +{ + if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) { + r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + r_cddata_masks->vmask |= CD_MASK_ORCO; + } + else if (v3d->shading.type == OB_SOLID) { + if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { + r_cddata_masks->lmask |= CD_MASK_MLOOPUV; + } + if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) { + r_cddata_masks->lmask |= CD_MASK_MLOOPCOL; + } + } + + if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && + (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) { + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; + } +} + +/* Goes over all modes and view3d settings. */ +void ED_view3d_screen_datamask(const bContext *C, + const Scene *scene, + const bScreen *screen, + CustomData_MeshMasks *r_cddata_masks) +{ + CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); + + /* Check if we need tfaces & mcols due to view mode. */ + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); + } + } +} + +/** + * Store values from #RegionView3D, set when drawing. + * This is needed when we draw with to a viewport using a different matrix + * (offscreen drawing for example). + * + * Values set by #ED_view3d_update_viewmat should be handled here. + */ +struct RV3DMatrixStore { + float winmat[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float persmat[4][4]; + float persinv[4][4]; + float viewcamtexcofac[4]; + float pixsize; +}; + +struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +{ + struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); + copy_m4_m4(rv3dmat->winmat, rv3d->winmat); + copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); + copy_m4_m4(rv3dmat->persmat, rv3d->persmat); + copy_m4_m4(rv3dmat->persinv, rv3d->persinv); + copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); + copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); + rv3dmat->pixsize = rv3d->pixsize; + return (void *)rv3dmat; +} + +void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) +{ + struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; + copy_m4_m4(rv3d->winmat, rv3dmat->winmat); + copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); + copy_m4_m4(rv3d->persmat, rv3dmat->persmat); + copy_m4_m4(rv3d->persinv, rv3dmat->persinv); + copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); + copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); + rv3d->pixsize = rv3dmat->pixsize; +} + +/** + * \note The info that this uses is updated in #ED_refresh_viewport_fps, + * which currently gets called during #SCREEN_OT_animation_step. + */ +void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset) +{ + ScreenFrameRateInfo *fpsi = scene->fps_info; + char printable[16]; + + if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { + return; + } + + printable[0] = '\0'; + + /* Doing an average for a more robust calculation. */ + fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / + (fpsi->lredrawtime - fpsi->redrawtime)); + + float fps = 0.0f; + int tot = 0; + for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { + if (fpsi->redrawtimes_fps[i]) { + fps += fpsi->redrawtimes_fps[i]; + tot++; + } + } + if (tot) { + fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; + fps = fps / tot; + } + + const int font_id = BLF_default(); + + /* Is this more than half a frame behind? */ + if (fps + 0.5f < (float)(FPS)) { + UI_FontThemeColor(font_id, TH_REDALERT); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); + } + + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); + + *yoffset -= U.widget_unit; + +#ifdef WITH_INTERNATIONAL + BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); +#else + BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); +#endif + + BLF_disable(font_id, BLF_SHADOW); +} + +static bool view3d_main_region_do_render_draw(const Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type && type->view_update && type->view_draw); +} + +bool ED_view3d_calc_render_border( + const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + bool use_border; + + /* Test if there is a 3d view rendering. */ + if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { + return false; + } + + /* Test if there is a border render. */ + if (rv3d->persp == RV3D_CAMOB) { + use_border = (scene->r.mode & R_BORDER) != 0; + } + else { + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + } + + if (!use_border) { + return false; + } + + /* Compute border. */ + if (rv3d->persp == RV3D_CAMOB) { + rctf viewborder; + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); + BLI_rcti_isect(&ar->winrct, rect, rect); + + return true; +} + /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c deleted file mode 100644 index 38cb5ad8651..00000000000 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spview3d - */ - -#include <string.h> -#include <stdio.h> -#include <math.h> - -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" -#include "DNA_customdata_types.h" -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_light_types.h" -#include "DNA_scene_types.h" -#include "DNA_world_types.h" -#include "DNA_brush_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" -#include "BLI_endian_switch.h" -#include "BLI_threads.h" - -#include "BKE_anim.h" -#include "BKE_camera.h" -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_image.h" -#include "BKE_key.h" -#include "BKE_layer.h" -#include "BKE_object.h" -#include "BKE_global.h" -#include "BKE_paint.h" -#include "BKE_scene.h" -#include "BKE_unit.h" -#include "BKE_movieclip.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" -#include "IMB_colormanagement.h" - -#include "BIF_glutil.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "BLF_api.h" -#include "BLT_translation.h" - -#include "ED_armature.h" -#include "ED_keyframing.h" -#include "ED_gpencil.h" -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_screen_types.h" -#include "ED_transform.h" -#include "ED_view3d.h" - -#include "UI_interface.h" -#include "UI_interface_icons.h" -#include "UI_resources.h" - -#include "GPU_framebuffer.h" -#include "GPU_immediate.h" -#include "GPU_state.h" -#include "GPU_viewport.h" - -#include "RE_engine.h" - -#include "DRW_engine.h" -#include "DRW_select_buffer.h" - -#include "view3d_intern.h" /* own include */ - -/* ********* custom clipping *********** */ - -/* Legacy 2.7x, now use shaders that use clip distance instead. - * Remove once clipping is working properly. */ -#define USE_CLIP_PLANES - -void ED_view3d_clipping_set(RegionView3D *rv3d) -{ -#ifdef USE_CLIP_PLANES - double plane[4]; - const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - - for (unsigned a = 0; a < tot; a++) { - copy_v4db_v4fl(plane, rv3d->clip[a]); - glClipPlane(GL_CLIP_PLANE0 + a, plane); - glEnable(GL_CLIP_PLANE0 + a); - glEnable(GL_CLIP_DISTANCE0 + a); - } -#else - for (unsigned a = 0; a < 6; a++) { - glEnable(GL_CLIP_DISTANCE0 + a); - } -#endif -} - -/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ -void ED_view3d_clipping_disable(void) -{ - for (unsigned a = 0; a < 6; a++) { -#ifdef USE_CLIP_PLANES - glDisable(GL_CLIP_PLANE0 + a); -#endif - glDisable(GL_CLIP_DISTANCE0 + a); - } -} -void ED_view3d_clipping_enable(void) -{ - for (unsigned a = 0; a < 6; a++) { -#ifdef USE_CLIP_PLANES - glEnable(GL_CLIP_PLANE0 + a); -#endif - glEnable(GL_CLIP_DISTANCE0 + a); - } -} - -/* *********************** backdraw for selection *************** */ - -/** - * \note Only use in object mode. - */ -static void validate_object_select_id( - struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact) -{ - Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); - - BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); - UNUSED_VARS_NDEBUG(ar); - - if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || - BKE_paint_select_face_test(obact_eval))) { - /* do nothing */ - } - /* texture paint mode sampling */ - else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && - (v3d->shading.type > OB_WIRE)) { - /* do nothing */ - } - else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { - /* do nothing */ - } - else { - v3d->flag &= ~V3D_INVALID_BACKBUF; - return; - } - - if (!(v3d->flag & V3D_INVALID_BACKBUF)) { - return; - } - - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { - Base *base = BKE_view_layer_base_find(view_layer, obact); - DRW_select_buffer_context_create(&base, 1, -1); - } - - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - v3d->flag &= ~V3D_INVALID_BACKBUF; -} - -/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. - * Calling this function should be avoided during interactive drawing. */ -static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) -{ - DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); - - GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); - GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); - GPU_framebuffer_bind(tmp_fb); - - glReadPixels(rect->xmin, - rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - GL_DEPTH_COMPONENT, - GL_FLOAT, - data); - - GPU_framebuffer_restore(); - GPU_framebuffer_free(tmp_fb); -} - -void ED_view3d_select_id_validate(ViewContext *vc) -{ - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact); - } -} - -void ED_view3d_backbuf_depth_validate(ViewContext *vc) -{ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - ARegion *ar = vc->ar; - Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval); - } - - vc->v3d->flag &= ~V3D_INVALID_BACKBUF; - } -} - -/** - * allow for small values [0.5 - 2.5], - * and large values, FLT_MAX by clamping by the area size - */ -int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) -{ - return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); -} - -/* *********************** */ - -void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) -{ - /* clamp rect by region */ - rcti r = { - .xmin = 0, - .xmax = ar->winx - 1, - .ymin = 0, - .ymax = ar->winy - 1, - }; - - /* Constrain rect to depth bounds */ - BLI_rcti_isect(&r, rect, rect); - - /* assign values to compare with the ViewDepths */ - int x = rect->xmin; - int y = rect->ymin; - - int w = BLI_rcti_size_x(rect); - int h = BLI_rcti_size_y(rect); - - if (w <= 0 || h <= 0) { - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = NULL; - - d->damaged = false; - } - else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { - d->x = x; - d->y = y; - d->w = w; - d->h = h; - - if (d->depths) { - MEM_freeN(d->depths); - } - - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); - - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - view3d_opengl_read_Z_pixels(viewport, rect, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } -} - -/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ -void ED_view3d_depth_update(ARegion *ar) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Create storage for, and, if necessary, copy depth buffer */ - if (!rv3d->depths) { - rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - } - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != ar->winx || d->h != ar->winy || !d->depths) { - d->w = ar->winx; - d->h = ar->winy; - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - rcti r = { - .xmin = 0, - .xmax = d->w, - .ymin = 0, - .ymax = d->h, - }; - view3d_opengl_read_Z_pixels(viewport, &r, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } - } -} - -/* utility function to find the closest Z value, use for autodepth */ -float view3d_depth_near(ViewDepths *d) -{ - /* convert to float for comparisons */ - const float near = (float)d->depth_range[0]; - const float far_real = (float)d->depth_range[1]; - float far = far_real; - - const float *depths = d->depths; - float depth = FLT_MAX; - int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ - - /* far is both the starting 'far' value - * and the closest value found. */ - while (i--) { - depth = *depths++; - if ((depth < far) && (depth > near)) { - far = depth; - } - } - - return far == far_real ? FLT_MAX : far; -} - -void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) -{ - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); - - GPU_clear(GPU_DEPTH_BIT); - - GPU_depth_test(true); - - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); - - GPU_depth_test(false); -} - -/* *********************** customdata **************** */ - -void ED_view3d_datamask(const bContext *C, - const Scene *UNUSED(scene), - const View3D *v3d, - CustomData_MeshMasks *r_cddata_masks) -{ - if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) { - r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - r_cddata_masks->vmask |= CD_MASK_ORCO; - } - else if (v3d->shading.type == OB_SOLID) { - if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { - r_cddata_masks->lmask |= CD_MASK_MLOOPUV; - } - if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) { - r_cddata_masks->lmask |= CD_MASK_MLOOPCOL; - } - } - - if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && - (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) { - r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; - } -} - -/* goes over all modes and view3d settings */ -void ED_view3d_screen_datamask(const bContext *C, - const Scene *scene, - const bScreen *screen, - CustomData_MeshMasks *r_cddata_masks) -{ - CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); - - /* check if we need tfaces & mcols due to view mode */ - for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); - } - } -} - -/** - * Store values from #RegionView3D, set when drawing. - * This is needed when we draw with to a viewport using a different matrix - * (offscreen drawing for example). - * - * Values set by #ED_view3d_update_viewmat should be handled here. - */ -struct RV3DMatrixStore { - float winmat[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float persmat[4][4]; - float persinv[4][4]; - float viewcamtexcofac[4]; - float pixsize; -}; - -struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) -{ - struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); - copy_m4_m4(rv3dmat->winmat, rv3d->winmat); - copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); - copy_m4_m4(rv3dmat->persmat, rv3d->persmat); - copy_m4_m4(rv3dmat->persinv, rv3d->persinv); - copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); - copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); - rv3dmat->pixsize = rv3d->pixsize; - return (void *)rv3dmat; -} - -void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) -{ - struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; - copy_m4_m4(rv3d->winmat, rv3dmat->winmat); - copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); - copy_m4_m4(rv3d->persmat, rv3dmat->persmat); - copy_m4_m4(rv3d->persinv, rv3dmat->persinv); - copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); - copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); - rv3d->pixsize = rv3dmat->pixsize; -} - -/** - * \note The info that this uses is updated in #ED_refresh_viewport_fps, - * which currently gets called during #SCREEN_OT_animation_step. - */ -void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset) -{ - ScreenFrameRateInfo *fpsi = scene->fps_info; - char printable[16]; - - if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { - return; - } - - printable[0] = '\0'; - -#if 0 - /* this is too simple, better do an average */ - fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) -#else - fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / - (fpsi->lredrawtime - fpsi->redrawtime)); - - float fps = 0.0f; - int tot = 0; - for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { - if (fpsi->redrawtimes_fps[i]) { - fps += fpsi->redrawtimes_fps[i]; - tot++; - } - } - if (tot) { - fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; - - // fpsi->redrawtime_index++; - // if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) { - // fpsi->redrawtime = 0; - //} - - fps = fps / tot; - } -#endif - - const int font_id = BLF_default(); - - /* is this more than half a frame behind? */ - if (fps + 0.5f < (float)(FPS)) { - UI_FontThemeColor(font_id, TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); - } - else { - UI_FontThemeColor(font_id, TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); - } - - BLF_enable(font_id, BLF_SHADOW); - BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); - BLF_shadow_offset(font_id, 1, -1); - - *yoffset -= U.widget_unit; - -#ifdef WITH_INTERNATIONAL - BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); -#else - BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); -#endif - - BLF_disable(font_id, BLF_SHADOW); -} - -static bool view3d_main_region_do_render_draw(const Scene *scene) -{ - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->view_update && type->view_draw); -} - -bool ED_view3d_calc_render_border( - const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - bool use_border; - - /* test if there is a 3d view rendering */ - if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { - return false; - } - - /* test if there is a border render */ - if (rv3d->persp == RV3D_CAMOB) { - use_border = (scene->r.mode & R_BORDER) != 0; - } - else { - use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; - } - - if (!use_border) { - return false; - } - - /* compute border */ - if (rv3d->persp == RV3D_CAMOB) { - rctf viewborder; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); - - rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); - } - else { - rect->xmin = v3d->render_border.xmin * ar->winx; - rect->xmax = v3d->render_border.xmax * ar->winx; - rect->ymin = v3d->render_border.ymin * ar->winy; - rect->ymax = v3d->render_border.ymax * ar->winy; - } - - BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); - BLI_rcti_isect(&ar->winrct, rect, rect); - - return true; -} diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 53ff9952d05..e81a896e062 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -19,6 +19,7 @@ /** \file * \ingroup edtransform + * \brief conversion and adaptation of different datablocks to a common struct. */ #ifndef __TRANSFORM_CONVERT_H__ @@ -60,28 +61,38 @@ void clipUVData(TransInfo *t); /* transform_convert_action.c */ void flushTransIntFrameActionData(TransInfo *t); + /* transform_convert_armature.c */ void restoreMirrorPoseBones(TransDataContainer *tc); void restoreBones(TransDataContainer *tc); + /* transform_convert_graph.c */ void flushTransGraphData(TransInfo *t); + /* transform_convert_mask.c */ void flushTransMasking(TransInfo *t); + /* transform_convert_mesh.c */ void flushTransUVs(TransInfo *t); void trans_mesh_customdata_correction_init(TransInfo *t); void trans_mesh_customdata_correction_apply(struct TransDataContainer *tc, bool is_final); + /* transform_convert_node.c */ void flushTransNodes(TransInfo *t); + /* transform_convert_object.c */ void trans_obdata_in_obmode_update_all(struct TransInfo *t); void trans_obchild_in_obmode_update_all(struct TransInfo *t); + /* transform_convert_paintcurve.c */ void flushTransPaintCurve(TransInfo *t); + /* transform_convert_particle.c */ void flushTransParticles(TransInfo *t); + /* transform_convert_sequencer.c */ void flushTransSeq(TransInfo *t); + /* transform_convert_tracking.c */ void flushTransTracking(TransInfo *t); @@ -96,45 +107,62 @@ bool FrameOnMouseSide(char side, float frame, float cframe); /* transform_convert_action.c */ void createTransActionData(bContext *C, TransInfo *t); + /* transform_convert_armature.c */ struct bKinematicConstraint *has_targetless_ik(struct bPoseChannel *pchan); void createTransPose(TransInfo *t); void createTransArmatureVerts(TransInfo *t); + /* transform_convert_cursor.c */ void createTransCursor_image(TransInfo *t); void createTransCursor_view3d(TransInfo *t); + /* transform_convert_curve.c */ void createTransCurveVerts(TransInfo *t); + /* transform_convert_graph.c */ void createTransGraphEditData(bContext *C, TransInfo *t); + /* transform_convert_gpencil.c */ void createTransGPencil(bContext *C, TransInfo *t); + /* transform_convert_lattice.c */ void createTransLatticeVerts(TransInfo *t); + /* transform_convert_mask.c */ void createTransMaskingData(bContext *C, TransInfo *t); + /* transform_convert_mball.c */ void createTransMBallVerts(TransInfo *t); + /* transform_convert_mesh.c */ void createTransEditVerts(TransInfo *t); void createTransEdge(TransInfo *t); void createTransUVs(bContext *C, TransInfo *t); + /* transform_convert_nla.c */ void createTransNlaData(bContext *C, TransInfo *t); + /* transform_convert_node.c */ void createTransNodeData(bContext *UNUSED(C), TransInfo *t); + /* transform_convert_object.c */ void clear_trans_object_base_flags(TransInfo *t); void createTransObject(bContext *C, TransInfo *t); void createTransTexspace(TransInfo *t); + /* transform_convert_paintcurve.c */ void createTransPaintCurveVerts(bContext *C, TransInfo *t); + /* transform_convert_particle.c */ void createTransParticleVerts(bContext *C, TransInfo *t); + /* transform_convert_sculpt.c */ void createTransSculpt(TransInfo *t); + /* transform_convert_sequence.c */ void createTransSeqData(bContext *C, TransInfo *t); + /* transform_convert_tracking.c */ void createTransTrackingData(bContext *C, TransInfo *t); void cancelTransTracking(TransInfo *t); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index bb70b548675..e258fbdccd1 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -228,24 +228,34 @@ static void generate_geometry(GpencilModifierData *md, for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) { /* check if stroke can be duplicated */ if (valid_strokes[idx]) { - /* Duplicate stroke */ - bGPDstroke *gps_dst = MEM_dupallocN(gps); - gps_dst->points = MEM_dupallocN(gps->points); - if (gps->dvert) { - gps_dst->dvert = MEM_dupallocN(gps->dvert); - BKE_gpencil_stroke_weights_duplicate(gps, gps_dst); + /* Calculate original stroke center (only first loop). */ + float r_min[3], r_max[3], center[3]; + if (x == 1) { + INIT_MINMAX(r_min, r_max); + BKE_gpencil_stroke_minmax(gps, false, r_min, r_max); + add_v3_v3v3(center, r_min, r_max); + mul_v3_fl(center, 0.5f); + sub_v3_v3v3(center, center, ob->obmat[3]); } - gps_dst->triangles = MEM_dupallocN(gps->triangles); + + /* Duplicate stroke */ + bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps); /* Move points */ for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps_dst->points[i]; + /* Apply object local transform (Rot/Scale). */ if (mmd->object) { - /* apply local changes (rot/scale) */ mul_m4_v3(mat, &pt->x); } - /* global changes */ - mul_m4_v3(current_offset, &pt->x); + /* Translate to object origin. */ + float fpt[3]; + sub_v3_v3v3(fpt, &pt->x, center); + /* Global Rotate and scale. */ + mul_mat3_m4_v3(current_offset, fpt); + /* Global translate. */ + add_v3_v3(fpt, center); + add_v3_v3v3(&pt->x, fpt, current_offset[3]); } /* if replace material, use new one */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index c070300e06b..aa94340e041 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -218,7 +218,11 @@ const EnumPropertyItem rna_enum_brush_gpencil_weight_types_items[] = { #ifndef RNA_RUNTIME static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = { - {GP_BRUSH_ERASER_SOFT, "SOFT", 0, "Dissolve,", "Erase strokes, fading their points strength and thickness"}, + {GP_BRUSH_ERASER_SOFT, + "SOFT", + 0, + "Dissolve,", + "Erase strokes, fading their points strength and thickness"}, {GP_BRUSH_ERASER_HARD, "HARD", 0, "Point", "Erase stroke points"}, {GP_BRUSH_ERASER_STROKE, "STROKE", 0, "Stroke", "Erase entire strokes"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 7bfe63e562a..3f26686d45a 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -119,8 +119,14 @@ static void deformVerts(ModifierData *md, /* silly that defaxis and curve_deform_verts are off by 1 * but leave for now to save having to call do_versions */ - curve_deform_verts( - cmd->object, ctx->object, vertexCos, numVerts, dvert, defgrp_index, cmd->flag, cmd->defaxis - 1); + curve_deform_verts(cmd->object, + ctx->object, + vertexCos, + numVerts, + dvert, + defgrp_index, + cmd->flag, + cmd->defaxis - 1); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 3128183060a..21131a7c898 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -101,8 +101,14 @@ static void deformVerts(ModifierData *md, MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */ - lattice_deform_verts( - lmd->object, ctx->object, mesh_src, vertexCos, numVerts, lmd->flag, lmd->name, lmd->strength); + lattice_deform_verts(lmd->object, + ctx->object, + mesh_src, + vertexCos, + numVerts, + lmd->flag, + lmd->name, + lmd->strength); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 773cbf72d5b..51ad40bdd87 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1090,7 +1090,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes /* validate loop edges */ #if 0 { - unsigned i = 0; + uint i = 0; printf("\n"); for (; i < maxPolys * 4; i += 4) { uint ii; diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 59ed3b0b005..c879b2d3754 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -140,8 +140,9 @@ static void smoothModifier_do( } float *vco_new = accumulated_vecs[i]; - const float f_new = invert_vgroup ? (1.0f - defvert_find_weight(dv, defgrp_index)) * fac_new : - defvert_find_weight(dv, defgrp_index) * fac_new; + const float f_new = invert_vgroup ? + (1.0f - defvert_find_weight(dv, defgrp_index)) * fac_new : + defvert_find_weight(dv, defgrp_index) * fac_new; if (f_new <= 0.0f) { continue; } diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index b82865a727d..e22863bc602 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -132,11 +132,8 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) } } -static void window_set_custom_cursor(wmWindow *win, - unsigned const char mask[16][2], - unsigned char bitmap[16][2], - int hotx, - int hoty) +static void window_set_custom_cursor( + wmWindow *win, const uchar mask[16][2], uchar bitmap[16][2], int hotx, int hoty) { GHOST_SetCustomCursorShape( win->ghostwin, (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask, 16, 16, hotx, hoty, true); @@ -380,8 +377,8 @@ void WM_cursor_time(wmWindow *win, int nr) {0, 60, 66, 66, 60, 66, 66, 60}, {0, 56, 68, 68, 120, 64, 68, 56}, }; - unsigned char mask[16][2]; - unsigned char bitmap[16][2] = {{0}}; + uchar mask[16][2]; + uchar bitmap[16][2] = {{0}}; int i, idx; if (win->lastcursor == 0) { |