diff options
Diffstat (limited to 'intern')
195 files changed, 6211 insertions, 4298 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 9d5b5a2d1a6..b1bb1d3654d 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -45,7 +45,7 @@ if(WITH_CYCLES_NATIVE_ONLY) ) if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + string(APPEND CMAKE_CXX_FLAGS " -march=native") set(CYCLES_KERNEL_FLAGS "-march=native") else() if(NOT MSVC_NATIVE_ARCH_FLAGS) @@ -101,10 +101,10 @@ elseif(WIN32 AND MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}") endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox") + string(APPEND CMAKE_CXX_FLAGS " ${CYCLES_KERNEL_FLAGS}") + string(APPEND CMAKE_CXX_FLAGS_RELEASE " /Ox") + string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /Ox") + string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /Ox") elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) check_cxx_compiler_flag(-msse CXX_HAS_SSE) check_cxx_compiler_flag(-mavx CXX_HAS_AVX) @@ -113,20 +113,20 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) # Assume no signal trapping for better code generation. set(CYCLES_KERNEL_FLAGS "-fno-trapping-math") # Avoid overhead of setting errno for NaNs. - set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-math-errno") + string(APPEND CYCLES_KERNEL_FLAGS " -fno-math-errno") # Let compiler optimize 0.0 - x without worrying about signed zeros. - set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signed-zeros") + string(APPEND CYCLES_KERNEL_FLAGS " -fno-signed-zeros") if(CMAKE_COMPILER_IS_GNUCC) # Assume no signal trapping for better code generation. - set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signaling-nans") + string(APPEND CYCLES_KERNEL_FLAGS " -fno-signaling-nans") # Assume a fixed rounding mode for better constant folding. - set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-rounding-math") + string(APPEND CYCLES_KERNEL_FLAGS " -fno-rounding-math") endif() if(CXX_HAS_SSE) if(CMAKE_COMPILER_IS_GNUCC) - set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -mfpmath=sse") + string(APPEND CYCLES_KERNEL_FLAGS " -mfpmath=sse") endif() set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -msse -msse2") @@ -140,7 +140,7 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) endif() endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}") + string(APPEND CMAKE_CXX_FLAGS " ${CYCLES_KERNEL_FLAGS}") elseif(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Intel") check_cxx_compiler_flag(/QxSSE2 CXX_HAS_SSE) check_cxx_compiler_flag(/arch:AVX CXX_HAS_AVX) diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 0d805dc8683..2d48563d8a6 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -130,7 +130,7 @@ blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # avoid link failure with clang 3.4 debug if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4') - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gline-tables-only") + string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gline-tables-only") endif() add_dependencies(bf_intern_cycles bf_rna) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 72d98e78c4d..6b88be3e7aa 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1271,7 +1271,7 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) - col = layout.column(heading="Show in") + col = layout.column(heading="Show In") col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False) col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index e1ab3b3fbc1..c1da9f1983f 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -388,18 +388,19 @@ static void blender_camera_sync(Camera *cam, const char *viewname, PointerRNA *cscene) { - /* copy camera to compare later */ - Camera prevcam = *cam; float aspectratio, sensor_size; /* viewplane */ - blender_camera_viewplane(bcam, width, height, &cam->viewplane, &aspectratio, &sensor_size); + BoundBox2D viewplane; + blender_camera_viewplane(bcam, width, height, &viewplane, &aspectratio, &sensor_size); - cam->width = bcam->full_width; - cam->height = bcam->full_height; + cam->set_viewplane_left(viewplane.left); + cam->set_viewplane_right(viewplane.right); + cam->set_viewplane_top(viewplane.top); + cam->set_viewplane_bottom(viewplane.bottom); - cam->full_width = width; - cam->full_height = height; + cam->set_full_width(width); + cam->set_full_height(height); /* panorama sensor */ if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { @@ -422,85 +423,91 @@ static void blender_camera_sync(Camera *cam, } if (horizontal_fit) { - cam->sensorwidth = sensor_size; - cam->sensorheight = sensor_size * fit_yratio / fit_xratio; + cam->set_sensorwidth(sensor_size); + cam->set_sensorheight(sensor_size * fit_yratio / fit_xratio); } else { - cam->sensorwidth = sensor_size * fit_xratio / fit_yratio; - cam->sensorheight = sensor_size; + cam->set_sensorwidth(sensor_size * fit_xratio / fit_yratio); + cam->set_sensorheight(sensor_size); } } /* clipping distances */ - cam->nearclip = bcam->nearclip; - cam->farclip = bcam->farclip; + cam->set_nearclip(bcam->nearclip); + cam->set_farclip(bcam->farclip); /* type */ - cam->type = bcam->type; + cam->set_camera_type(bcam->type); /* panorama */ - cam->panorama_type = bcam->panorama_type; - cam->fisheye_fov = bcam->fisheye_fov; - cam->fisheye_lens = bcam->fisheye_lens; - cam->latitude_min = bcam->latitude_min; - cam->latitude_max = bcam->latitude_max; + cam->set_panorama_type(bcam->panorama_type); + cam->set_fisheye_fov(bcam->fisheye_fov); + cam->set_fisheye_lens(bcam->fisheye_lens); + cam->set_latitude_min(bcam->latitude_min); + cam->set_latitude_max(bcam->latitude_max); - cam->longitude_min = bcam->longitude_min; - cam->longitude_max = bcam->longitude_max; + cam->set_longitude_min(bcam->longitude_min); + cam->set_longitude_max(bcam->longitude_max); /* panorama stereo */ - cam->interocular_distance = bcam->interocular_distance; - cam->convergence_distance = bcam->convergence_distance; - cam->use_spherical_stereo = bcam->use_spherical_stereo; + cam->set_interocular_distance(bcam->interocular_distance); + cam->set_convergence_distance(bcam->convergence_distance); + cam->set_use_spherical_stereo(bcam->use_spherical_stereo); - if (cam->use_spherical_stereo) { + if (cam->get_use_spherical_stereo()) { if (strcmp(viewname, "left") == 0) - cam->stereo_eye = Camera::STEREO_LEFT; + cam->set_stereo_eye(Camera::STEREO_LEFT); else if (strcmp(viewname, "right") == 0) - cam->stereo_eye = Camera::STEREO_RIGHT; + cam->set_stereo_eye(Camera::STEREO_RIGHT); else - cam->stereo_eye = Camera::STEREO_NONE; + cam->set_stereo_eye(Camera::STEREO_NONE); } - cam->use_pole_merge = bcam->use_pole_merge; - cam->pole_merge_angle_from = bcam->pole_merge_angle_from; - cam->pole_merge_angle_to = bcam->pole_merge_angle_to; + cam->set_use_pole_merge(bcam->use_pole_merge); + cam->set_pole_merge_angle_from(bcam->pole_merge_angle_from); + cam->set_pole_merge_angle_to(bcam->pole_merge_angle_to); /* anamorphic lens bokeh */ - cam->aperture_ratio = bcam->aperture_ratio; + cam->set_aperture_ratio(bcam->aperture_ratio); /* perspective */ - cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio); - cam->focaldistance = bcam->focaldistance; - cam->aperturesize = bcam->aperturesize; - cam->blades = bcam->apertureblades; - cam->bladesrotation = bcam->aperturerotation; + cam->set_fov(2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio)); + cam->set_focaldistance(bcam->focaldistance); + cam->set_aperturesize(bcam->aperturesize); + cam->set_blades(bcam->apertureblades); + cam->set_bladesrotation(bcam->aperturerotation); /* transform */ - cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type); - cam->motion.clear(); - cam->motion.resize(bcam->motion_steps, cam->matrix); - cam->use_perspective_motion = false; - cam->shuttertime = bcam->shuttertime; - cam->fov_pre = cam->fov; - cam->fov_post = cam->fov; - cam->motion_position = bcam->motion_position; + cam->set_matrix(blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type)); - cam->rolling_shutter_type = bcam->rolling_shutter_type; - cam->rolling_shutter_duration = bcam->rolling_shutter_duration; + array<Transform> motion; + motion.resize(bcam->motion_steps, cam->get_matrix()); + cam->set_motion(motion); + cam->set_use_perspective_motion(false); - cam->shutter_curve = bcam->shutter_curve; + cam->set_shuttertime(bcam->shuttertime); + cam->set_fov_pre(cam->get_fov()); + cam->set_fov_post(cam->get_fov()); + cam->set_motion_position(bcam->motion_position); + + cam->set_rolling_shutter_type(bcam->rolling_shutter_type); + cam->set_rolling_shutter_duration(bcam->rolling_shutter_duration); + + cam->set_shutter_curve(bcam->shutter_curve); /* border */ - cam->border = bcam->border; - cam->viewport_camera_border = bcam->viewport_camera_border; + cam->set_border_left(bcam->border.left); + cam->set_border_right(bcam->border.right); + cam->set_border_top(bcam->border.top); + cam->set_border_bottom(bcam->border.bottom); - bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale"); - cam->offscreen_dicing_scale = bcam->offscreen_dicing_scale; + cam->set_viewport_camera_border_left(bcam->viewport_camera_border.left); + cam->set_viewport_camera_border_right(bcam->viewport_camera_border.right); + cam->set_viewport_camera_border_top(bcam->viewport_camera_border.top); + cam->set_viewport_camera_border_bottom(bcam->viewport_camera_border.bottom); - /* set update flag */ - if (cam->modified(prevcam)) - cam->tag_update(); + bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale"); + cam->set_offscreen_dicing_scale(bcam->offscreen_dicing_scale); } /* Sync Render Camera */ @@ -582,22 +589,24 @@ void BlenderSync::sync_camera_motion( Camera *cam = scene->camera; BL::Array<float, 16> b_ob_matrix; - b_engine.camera_model_matrix(b_ob, cam->use_spherical_stereo, b_ob_matrix); + b_engine.camera_model_matrix(b_ob, cam->get_use_spherical_stereo(), b_ob_matrix); Transform tfm = get_transform(b_ob_matrix); - tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type); + tfm = blender_camera_matrix(tfm, cam->get_camera_type(), cam->get_panorama_type()); if (motion_time == 0.0f) { /* When motion blur is not centered in frame, cam->matrix gets reset. */ - cam->matrix = tfm; + cam->set_matrix(tfm); } /* Set transform in motion array. */ int motion_step = cam->motion_step(motion_time); if (motion_step >= 0) { - cam->motion[motion_step] = tfm; + array<Transform> motion = cam->get_motion(); + motion[motion_step] = tfm; + cam->set_motion(motion); } - if (cam->type == CAMERA_PERSPECTIVE) { + if (cam->get_camera_type() == CAMERA_PERSPECTIVE) { BlenderCamera bcam; float aspectratio, sensor_size; blender_camera_init(&bcam, b_render); @@ -610,18 +619,18 @@ void BlenderSync::sync_camera_motion( blender_camera_viewplane(&bcam, width, height, NULL, &aspectratio, &sensor_size); /* TODO(sergey): De-duplicate calculation with camera sync. */ float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio); - if (fov != cam->fov) { + if (fov != cam->get_fov()) { VLOG(1) << "Camera " << b_ob.name() << " FOV change detected."; if (motion_time == 0.0f) { - cam->fov = fov; + cam->set_fov(fov); } else if (motion_time == -1.0f) { - cam->fov_pre = fov; - cam->use_perspective_motion = true; + cam->set_fov_pre(fov); + cam->set_use_perspective_motion(true); } else if (motion_time == 1.0f) { - cam->fov_post = fov; - cam->use_perspective_motion = true; + cam->set_fov_post(fov); + cam->set_use_perspective_motion(true); } } } diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 6288c370567..964241e9904 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -77,7 +77,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, hair->used_shaders.size() - 1); + int shader = clamp(b_part.material() - 1, 0, hair->get_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() : @@ -307,7 +307,7 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa VLOG(1) << "Exporting curve segments for mesh " << hair->name; } - hair->reserve_curves(hair->num_curves() + num_curves, hair->curve_keys.size() + num_keys); + hair->reserve_curves(hair->num_curves() + num_curves, hair->get_curve_keys().size() + num_keys); num_keys = 0; num_curves = 0; @@ -350,9 +350,9 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa } /* check allocation */ - if ((hair->curve_keys.size() != num_keys) || (hair->num_curves() != num_curves)) { + if ((hair->get_curve_keys().size() != num_keys) || (hair->num_curves() != num_curves)) { VLOG(1) << "Allocation failed, clearing data"; - hair->clear(); + hair->clear(true); } } @@ -402,7 +402,7 @@ static void export_hair_motion_validate_attribute(Hair *hair, bool have_motion) { Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - const int num_keys = hair->curve_keys.size(); + const int num_keys = hair->get_curve_keys().size(); if (num_motion_keys != num_keys || !have_motion) { /* No motion or hair "topology" changed, remove attributes again. */ @@ -423,8 +423,8 @@ static void export_hair_motion_validate_attribute(Hair *hair, 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]; + mP[key] = float3_to_float4(hair->get_curve_keys()[key]); + mP[key].w = hair->get_curve_radius()[key]; } } } @@ -447,7 +447,7 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int } /* export motion vectors for curve keys */ - size_t numkeys = hair->curve_keys.size(); + size_t numkeys = hair->get_curve_keys().size(); float4 *mP = attr_mP->data_float4() + motion_step * numkeys; bool have_motion = false; int i = 0; @@ -458,24 +458,24 @@ static void ExportCurveSegmentsMotion(Hair *hair, 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)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]; + int curve_key_end = (num_curves + 1 < (int)hair->get_curve_first_key().size() ? + hair->get_curve_first_key()[num_curves + 1] : + (int)hair->get_curve_keys().size()); + const int num_center_curve_keys = curve_key_end - hair->get_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 < hair->curve_keys.size()) { + if (i < hair->get_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(hair->curve_keys[i]); - curve_key.w = hair->curve_radius[i]; + float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]); + curve_key.w = hair->get_curve_radius()[i]; if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f) have_motion = true; } @@ -560,7 +560,7 @@ void BlenderSync::sync_particle_hair( float3 *generated = attr_generated->data_float3(); for (size_t i = 0; i < hair->num_curves(); i++) { - float3 co = hair->curve_keys[hair->get_curve(i).first_key]; + float3 co = hair->get_curve_keys()[hair->get_curve(i).first_key]; generated[i] = co * size - loc; } } @@ -742,7 +742,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st } /* Export motion keys. */ - const int num_keys = hair->curve_keys.size(); + const int num_keys = hair->get_curve_keys().size(); float4 *mP = attr_mP->data_float4() + motion_step * num_keys; bool have_motion = false; int num_motion_keys = 0; @@ -769,8 +769,8 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st if (!have_motion) { /* TODO: use epsilon for comparison? Was needed for particles due to * transform, but ideally should not happen anymore. */ - float4 curve_key = float3_to_float4(hair->curve_keys[i]); - curve_key.w = hair->curve_radius[i]; + float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]); + curve_key.w = hair->get_curve_radius()[i]; have_motion = !(mP[i] == curve_key); } } @@ -817,42 +817,54 @@ void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motio } #endif -void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, - BL::Object b_ob, - Hair *hair, - const vector<Shader *> &used_shaders) +void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair) { - /* 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(hair->curve_keys); - oldcurve_radius.steal_data(hair->curve_radius); + /* make a copy of the shaders as the caller in the main thread still need them for syncing the + * attributes */ + array<Node *> used_shaders = hair->get_used_shaders(); - hair->clear(); - hair->used_shaders = used_shaders; + Hair new_hair; + new_hair.set_used_shaders(used_shaders); if (view_layer.use_hair) { if (b_ob.type() == BL::Object::type_HAIR) { /* Hair object. */ - sync_hair(hair, b_ob, false); + sync_hair(&new_hair, b_ob, false); } else { /* Particle hair. */ - bool need_undeformed = hair->need_attribute(scene, ATTR_STD_GENERATED); + bool need_undeformed = new_hair.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(hair, b_mesh, b_ob, false); + sync_particle_hair(&new_hair, b_mesh, b_ob, false); free_object_to_mesh(b_data, b_ob, b_mesh); } } } + /* update original sockets */ + + for (const SocketType &socket : new_hair.type->inputs) { + /* Those sockets are updated in sync_object, so do not modify them. */ + if (socket.name == "use_motion_blur" || socket.name == "motion_steps" || + socket.name == "used_shaders") { + continue; + } + hair->set_value(socket, new_hair, socket); + } + + hair->attributes.clear(); + foreach (Attribute &attr, new_hair.attributes.attributes) { + hair->attributes.attributes.push_back(std::move(attr)); + } + /* tag update */ - const bool rebuild = ((oldcurve_keys != hair->curve_keys) || - (oldcurve_radius != hair->curve_radius)); + + /* Compares curve_keys rather than strands in order to handle quick hair + * adjustments in dynamic BVH - other methods could probably do this better. */ + const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified()); hair->tag_update(scene, rebuild); } diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp index 0293223864d..ffcaef0b2a9 100644 --- a/intern/cycles/blender/blender_device.cpp +++ b/intern/cycles/blender/blender_device.cpp @@ -47,8 +47,7 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen vector<DeviceInfo> devices = Device::available_devices(BlenderSession::device_override); if (devices.empty()) { - printf("Found no Cycles device of the specified type, falling back to CPU...\n"); - return Device::available_devices(DEVICE_MASK_CPU).front(); + return Device::dummy_device("Found no Cycles device of the specified type"); } int threads = blender_device_threads(b_scene); diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp index a665bd97a8d..bd2f0731030 100644 --- a/intern/cycles/blender/blender_geometry.cpp +++ b/intern/cycles/blender/blender_geometry.cpp @@ -25,6 +25,7 @@ #include "blender/blender_util.h" #include "util/util_foreach.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN @@ -45,7 +46,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, BL::Object &b_ob, BL::Object &b_ob_instance, bool object_updated, - bool use_particle_hair) + bool use_particle_hair, + TaskPool *task_pool) { /* Test if we can instance or if the object is modified. */ BL::ID b_ob_data = b_ob.data(); @@ -57,7 +59,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, GeometryKey key(b_key_id.ptr.data, geom_type); /* Find shader indices. */ - vector<Shader *> used_shaders; + array<Node *> used_shaders; BL::Object::material_slots_iterator slot; for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { @@ -74,11 +76,18 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, if (material_override) find_shader(material_override, used_shaders, default_shader); else - used_shaders.push_back(default_shader); + used_shaders.push_back_slow(default_shader); } - /* Test if we need to sync. */ + /* Ensure we only sync instanced geometry once. */ Geometry *geom = geometry_map.find(key); + if (geom) { + if (geometry_synced.find(geom) != geometry_synced.end()) { + return geom; + } + } + + /* Test if we need to sync. */ bool sync = true; if (geom == NULL) { /* Add new geometry if it did not exist yet. */ @@ -105,7 +114,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, } /* 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 if (geom->get_used_shaders() != used_shaders) { ; } else { @@ -113,7 +122,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, * because the shader needs different geometry attributes. */ bool attribute_recalc = false; - foreach (Shader *shader, geom->used_shaders) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->need_update_geometry) { attribute_recalc = true; } @@ -125,28 +135,39 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, } } - /* 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->name = ustring(b_ob_data.name().c_str()); - if (geom_type == Geometry::HAIR) { - Hair *hair = static_cast<Hair *>(geom); - sync_hair(b_depsgraph, b_ob, hair, used_shaders); - } - else if (geom_type == Geometry::VOLUME) { - Volume *volume = static_cast<Volume *>(geom); - sync_volume(b_ob, volume, used_shaders); + /* Store the shaders immediately for the object attribute code. */ + geom->set_used_shaders(used_shaders); + + auto sync_func = [=]() mutable { + if (progress.get_cancel()) + return; + + progress.set_sync_status("Synchronizing object", b_ob.name()); + + if (geom_type == Geometry::HAIR) { + Hair *hair = static_cast<Hair *>(geom); + sync_hair(b_depsgraph, b_ob, hair); + } + else if (geom_type == Geometry::VOLUME) { + Volume *volume = static_cast<Volume *>(geom); + sync_volume(b_ob, volume); + } + else { + Mesh *mesh = static_cast<Mesh *>(geom); + sync_mesh(b_depsgraph, b_ob, mesh); + } + }; + + /* Defer the actual geometry sync to the task_pool for multithreading */ + if (task_pool) { + task_pool->push(sync_func); } else { - Mesh *mesh = static_cast<Mesh *>(geom); - sync_mesh(b_depsgraph, b_ob, mesh, used_shaders); + sync_func(); } return geom; @@ -156,10 +177,11 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, BL::Object &b_ob, Object *object, float motion_time, - bool use_particle_hair) + bool use_particle_hair, + TaskPool *task_pool) { /* Ensure we only sync instanced geometry once. */ - Geometry *geom = object->geometry; + Geometry *geom = object->get_geometry(); if (geometry_motion_synced.find(geom) != geometry_motion_synced.end()) return; @@ -177,16 +199,29 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, return; } - if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) { - Hair *hair = static_cast<Hair *>(geom); - sync_hair_motion(b_depsgraph, b_ob, hair, motion_step); - } - else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) { - /* No volume motion blur support yet. */ + auto sync_func = [=]() mutable { + if (progress.get_cancel()) + return; + + if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) { + Hair *hair = static_cast<Hair *>(geom); + sync_hair_motion(b_depsgraph, b_ob, hair, motion_step); + } + else if (b_ob.type() == BL::Object::type_VOLUME || 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); + } + }; + + /* Defer the actual geometry sync to the task_pool for multithreading */ + if (task_pool) { + task_pool->push(sync_func); } else { - Mesh *mesh = static_cast<Mesh *>(geom); - sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step); + sync_func(); } } diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp index 6f95821e31e..ff4ecc5a3f9 100644 --- a/intern/cycles/blender/blender_light.cpp +++ b/intern/cycles/blender/blender_light.cpp @@ -42,7 +42,7 @@ void BlenderSync::sync_light(BL::Object &b_parent, 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) + if (light->get_is_portal()) *use_portal = true; return; } @@ -52,16 +52,16 @@ void BlenderSync::sync_light(BL::Object &b_parent, 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; + light->set_size(b_point_light.shadow_soft_size()); + light->set_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(); + light->set_size(b_spot_light.shadow_soft_size()); + light->set_light_type(LIGHT_SPOT); + light->set_spot_angle(b_spot_light.spot_size()); + light->set_spot_smooth(b_spot_light.spot_blend()); break; } /* Hemi were removed from 2.8 */ @@ -72,88 +72,88 @@ void BlenderSync::sync_light(BL::Object &b_parent, // } case BL::Light::type_SUN: { BL::SunLight b_sun_light(b_light); - light->angle = b_sun_light.angle(); - light->type = LIGHT_DISTANT; + light->set_angle(b_sun_light.angle()); + light->set_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(); + light->set_size(1.0f); + light->set_axisu(transform_get_column(&tfm, 0)); + light->set_axisv(transform_get_column(&tfm, 1)); + light->set_sizeu(b_area_light.size()); switch (b_area_light.shape()) { case BL::AreaLight::shape_SQUARE: - light->sizev = light->sizeu; - light->round = false; + light->set_sizev(light->get_sizeu()); + light->set_round(false); break; case BL::AreaLight::shape_RECTANGLE: - light->sizev = b_area_light.size_y(); - light->round = false; + light->set_sizev(b_area_light.size_y()); + light->set_round(false); break; case BL::AreaLight::shape_DISK: - light->sizev = light->sizeu; - light->round = true; + light->set_sizev(light->get_sizeu()); + light->set_round(true); break; case BL::AreaLight::shape_ELLIPSE: - light->sizev = b_area_light.size_y(); - light->round = true; + light->set_sizev(b_area_light.size_y()); + light->set_round(true); break; } - light->type = LIGHT_AREA; + light->set_light_type(LIGHT_AREA); break; } } /* strength */ - light->strength = get_float3(b_light.color()); - light->strength *= BL::PointLight(b_light).energy(); + float3 strength = get_float3(b_light.color()) * BL::PointLight(b_light).energy(); + light->set_strength(strength); /* location and (inverted!) direction */ - light->co = transform_get_column(&tfm, 3); - light->dir = -transform_get_column(&tfm, 2); - light->tfm = tfm; + light->set_co(transform_get_column(&tfm, 3)); + light->set_dir(-transform_get_column(&tfm, 2)); + light->set_tfm(tfm); /* shader */ - vector<Shader *> used_shaders; + array<Node *> used_shaders; find_shader(b_light, used_shaders, scene->default_light); - light->shader = used_shaders[0]; + light->set_shader(static_cast<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"); + light->set_cast_shadow(get_boolean(clight, "cast_shadow")); + light->set_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; + light->set_samples(samples * samples); else - light->samples = samples; + light->set_samples(samples); - light->max_bounces = get_int(clight, "max_bounces"); + light->set_max_bounces(get_int(clight, "max_bounces")); if (b_ob != b_ob_instance) { - light->random_id = random_id; + light->set_random_id(random_id); } else { - light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0); + light->set_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"); + if (light->get_light_type() == LIGHT_AREA) + light->set_is_portal(get_boolean(clight, "is_portal")); else - light->is_portal = false; + light->set_is_portal(false); - if (light->is_portal) + if (light->get_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; + light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0); + light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0); + light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0); + light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0); /* tag */ light->tag_update(scene); @@ -178,25 +178,25 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal) if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc || b_world.ptr.data != world_map) { - light->type = LIGHT_BACKGROUND; + light->set_light_type(LIGHT_BACKGROUND); if (sampling_method == SAMPLING_MANUAL) { - light->map_resolution = get_int(cworld, "sample_map_resolution"); + light->set_map_resolution(get_int(cworld, "sample_map_resolution")); } else { - light->map_resolution = 0; + light->set_map_resolution(0); } - light->shader = scene->default_background; - light->use_mis = sample_as_light; - light->max_bounces = get_int(cworld, "max_bounces"); + light->set_shader(scene->default_background); + light->set_use_mis(sample_as_light); + light->set_max_bounces(get_int(cworld, "max_bounces")); /* force enable light again when world is resynced */ - light->is_enabled = true; + light->set_is_enabled(true); int samples = get_int(cworld, "samples"); if (get_boolean(cscene, "use_square_samples")) - light->samples = samples * samples; + light->set_samples(samples * samples); else - light->samples = samples; + light->set_samples(samples); light->tag_update(scene); light_map.set_recalc(b_world); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index b78a2c30b5e..e85b4ee1fc6 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -48,8 +48,8 @@ struct MikkUserData { float *tangent_sign) : mesh(mesh), texface(NULL), orco(NULL), tangent(tangent), tangent_sign(tangent_sign) { - const AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : - mesh->attributes; + const AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes : + mesh->attributes; Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); vertex_normal = attr_vN->data_float3(); @@ -85,8 +85,8 @@ struct MikkUserData { static int mikk_get_num_faces(const SMikkTSpaceContext *context) { const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - if (userdata->mesh->subd_faces.size()) { - return userdata->mesh->subd_faces.size(); + if (userdata->mesh->get_num_subd_faces()) { + return userdata->mesh->get_num_subd_faces(); } else { return userdata->mesh->num_triangles(); @@ -96,9 +96,9 @@ static int mikk_get_num_faces(const SMikkTSpaceContext *context) static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) { const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - if (userdata->mesh->subd_faces.size()) { + if (userdata->mesh->get_num_subd_faces()) { const Mesh *mesh = userdata->mesh; - return mesh->subd_faces[face_num].num_corners; + return mesh->get_subd_num_corners()[face_num]; } else { return 3; @@ -107,19 +107,19 @@ static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const i static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num) { - if (mesh->subd_faces.size()) { - const Mesh::SubdFace &face = mesh->subd_faces[face_num]; - return mesh->subd_face_corners[face.start_corner + vert_num]; + if (mesh->get_num_subd_faces()) { + const Mesh::SubdFace &face = mesh->get_subd_face(face_num); + return mesh->get_subd_face_corners()[face.start_corner + vert_num]; } else { - return mesh->triangles[face_num * 3 + vert_num]; + return mesh->get_triangles()[face_num * 3 + vert_num]; } } static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num) { - if (mesh->subd_faces.size()) { - const Mesh::SubdFace &face = mesh->subd_faces[face_num]; + if (mesh->get_num_subd_faces()) { + const Mesh::SubdFace &face = mesh->get_subd_face(face_num); return face.start_corner + vert_num; } else { @@ -135,7 +135,7 @@ static void mikk_get_position(const SMikkTSpaceContext *context, const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; const Mesh *mesh = userdata->mesh; const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); - const float3 vP = mesh->verts[vertex_index]; + const float3 vP = mesh->get_verts()[vertex_index]; P[0] = vP.x; P[1] = vP.y; P[2] = vP.z; @@ -178,8 +178,8 @@ static void mikk_get_normal(const SMikkTSpaceContext *context, const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; const Mesh *mesh = userdata->mesh; float3 vN; - if (mesh->subd_faces.size()) { - const Mesh::SubdFace &face = mesh->subd_faces[face_num]; + if (mesh->get_num_subd_faces()) { + const Mesh::SubdFace &face = mesh->get_subd_face(face_num); if (face.smooth) { const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); vN = userdata->vertex_normal[vertex_index]; @@ -189,13 +189,13 @@ static void mikk_get_normal(const SMikkTSpaceContext *context, } } else { - if (mesh->smooth[face_num]) { + if (mesh->get_smooth()[face_num]) { const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); vN = userdata->vertex_normal[vertex_index]; } else { const Mesh::Triangle tri = mesh->get_triangle(face_num); - vN = tri.compute_normal(&mesh->verts[0]); + vN = tri.compute_normal(&mesh->get_verts()[0]); } } N[0] = vN.x; @@ -222,7 +222,8 @@ static void mikk_compute_tangents( const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render) { /* Create tangent attributes. */ - AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : mesh->attributes; + AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes : + mesh->attributes; Attribute *attr; ustring name; if (layer_name != NULL) { @@ -555,7 +556,7 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b for (int vert_index = 0; vert_index < num_verts; ++vert_index) { sorted_vert_indeices[vert_index] = vert_index; } - VertexAverageComparator compare(mesh->verts); + VertexAverageComparator compare(mesh->get_verts()); sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare); /* This array stores index of the original vertex for the given vertex * index. @@ -563,12 +564,12 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b vector<int> vert_orig_index(num_verts); for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) { const int vert_index = sorted_vert_indeices[sorted_vert_index]; - const float3 &vert_co = mesh->verts[vert_index]; + const float3 &vert_co = mesh->get_verts()[vert_index]; bool found = false; for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts; ++other_sorted_vert_index) { const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index]; - const float3 &other_vert_co = mesh->verts[other_vert_index]; + const float3 &other_vert_co = mesh->get_verts()[other_vert_index]; /* We are too far away now, we wouldn't have duplicate. */ if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) - (vert_co.x + vert_co.y + vert_co.z) > @@ -733,7 +734,7 @@ static void attr_create_random_per_island(Scene *scene, static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, - const vector<Shader *> &used_shaders, + const array<Node *> &used_shaders, bool subdivision = false, bool subdivide_uvs = true) { @@ -744,7 +745,7 @@ static void create_mesh(Scene *scene, int numcorners = 0; int numngons = 0; bool use_loop_normals = b_mesh.use_auto_smooth() && - (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK); + (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ if (numfaces == 0) { @@ -763,8 +764,11 @@ static void create_mesh(Scene *scene, } /* allocate memory */ + if (subdivision) { + mesh->reserve_subd_faces(numfaces, numngons, numcorners); + } + mesh->reserve_mesh(numverts, numtris); - mesh->reserve_subd_faces(numfaces, numngons, numcorners); /* create vertex coordinates and normals */ BL::Mesh::vertices_iterator v; @@ -876,7 +880,7 @@ static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Object &b_ob, BL::Mesh &b_mesh, - const vector<Shader *> &used_shaders, + const array<Node *> &used_shaders, float dicing_rate, int max_subdivisions) { @@ -895,31 +899,21 @@ static void create_subd_mesh(Scene *scene, } } - mesh->subd_creases.resize(num_creases); + mesh->reserve_subd_creases(num_creases); - Mesh::SubdEdgeCrease *crease = mesh->subd_creases.data(); for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { if (e->crease() != 0.0f) { - crease->v[0] = e->vertices()[0]; - crease->v[1] = e->vertices()[1]; - crease->crease = e->crease(); - - crease++; + mesh->add_crease(e->vertices()[0], e->vertices()[1], e->crease()); } } /* set subd params */ - if (!mesh->subd_params) { - mesh->subd_params = new SubdParams(mesh); - } - SubdParams &sdparams = *mesh->subd_params; - PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); + float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); - sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); - sdparams.max_level = max_subdivisions; - - sdparams.objecttoworld = get_transform(b_ob.matrix_world()); + mesh->set_subd_dicing_rate(subd_dicing_rate); + mesh->set_subd_max_level(max_subdivisions); + mesh->set_subd_objecttoworld(get_transform(b_ob.matrix_world())); } /* Sync */ @@ -956,14 +950,14 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me return; } - const size_t numverts = mesh->verts.size(); + const size_t numverts = mesh->get_verts().size(); if (b_mesh_cache.vertex_velocities.length() != numverts) { return; } /* Find or add attribute */ - float3 *P = &mesh->verts[0]; + float3 *P = &mesh->get_verts()[0]; Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (!attr_mP) { @@ -997,11 +991,11 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) return; /* If the mesh has modifiers following the fluid domain we can't export motion. */ - if (b_fluid_domain.mesh_vertices.length() != mesh->verts.size()) + if (b_fluid_domain.mesh_vertices.length() != mesh->get_verts().size()) return; /* Find or add attribute */ - float3 *P = &mesh->verts[0]; + float3 *P = &mesh->get_verts()[0]; Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (!attr_mP) { @@ -1012,7 +1006,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) float motion_times[2] = {-1.0f, 1.0f}; for (int step = 0; step < 2; step++) { float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f; - float3 *mP = attr_mP->data_float3() + step * mesh->verts.size(); + float3 *mP = attr_mP->data_float3() + step * mesh->get_verts().size(); BL::FluidDomainSettings::mesh_vertices_iterator svi; int i = 0; @@ -1024,56 +1018,79 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) } } -void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, - BL::Object b_ob, - Mesh *mesh, - const vector<Shader *> &used_shaders) +void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh) { - array<int> oldtriangles; - array<Mesh::SubdFace> oldsubd_faces; - array<int> oldsubd_face_corners; - oldtriangles.steal_data(mesh->triangles); - oldsubd_faces.steal_data(mesh->subd_faces); - oldsubd_face_corners.steal_data(mesh->subd_face_corners); + /* make a copy of the shaders as the caller in the main thread still need them for syncing the + * attributes */ + array<Node *> used_shaders = mesh->get_used_shaders(); - mesh->clear(); - mesh->used_shaders = used_shaders; - - mesh->subdivision_type = Mesh::SUBDIVISION_NONE; + Mesh new_mesh; + new_mesh.set_used_shaders(used_shaders); 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 = object_subdivision_type(b_ob, preview, experimental); + new_mesh.set_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); + bool need_undeformed = new_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); + b_data, b_ob, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type()); if (b_mesh) { /* Sync mesh itself. */ - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) - create_subd_mesh( - scene, mesh, b_ob, b_mesh, mesh->used_shaders, dicing_rate, max_subdivisions); + if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE) + create_subd_mesh(scene, + &new_mesh, + b_ob, + b_mesh, + new_mesh.get_used_shaders(), + dicing_rate, + max_subdivisions); else - create_mesh(scene, mesh, b_mesh, mesh->used_shaders, false); + create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false); free_object_to_mesh(b_data, b_ob, b_mesh); } } /* cached velocities (e.g. from alembic archive) */ - sync_mesh_cached_velocities(b_ob, scene, mesh); + sync_mesh_cached_velocities(b_ob, scene, &new_mesh); /* mesh fluid motion mantaflow */ - sync_mesh_fluid_motion(b_ob, scene, mesh); + sync_mesh_fluid_motion(b_ob, scene, &new_mesh); + + /* update original sockets */ + + for (const SocketType &socket : new_mesh.type->inputs) { + /* Those sockets are updated in sync_object, so do not modify them. */ + if (socket.name == "use_motion_blur" || socket.name == "motion_steps" || + socket.name == "used_shaders") { + continue; + } + mesh->set_value(socket, new_mesh, socket); + } + + mesh->attributes.clear(); + foreach (Attribute &attr, new_mesh.attributes.attributes) { + mesh->attributes.attributes.push_back(std::move(attr)); + } + + mesh->subd_attributes.clear(); + foreach (Attribute &attr, new_mesh.subd_attributes.attributes) { + mesh->subd_attributes.attributes.push_back(std::move(attr)); + } + + mesh->set_num_subd_faces(new_mesh.get_num_subd_faces()); /* tag update */ - bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) || - (oldsubd_face_corners != mesh->subd_face_corners); + bool rebuild = (mesh->triangles_is_modified()) || (mesh->subd_num_corners_is_modified()) || + (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) || + (mesh->subd_ptex_offset_is_modified()) || + (mesh->subd_start_corner_is_modified()) || + (mesh->subd_face_corners_is_modified()); mesh->tag_update(scene, rebuild); } @@ -1096,7 +1113,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, } /* Skip if no vertices were exported. */ - size_t numverts = mesh->verts.size(); + size_t numverts = mesh->get_verts().size(); if (numverts == 0) { return; } @@ -1141,7 +1158,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, if (new_attribute) { /* In case of new attribute, we verify if there really was any motion. */ if (b_mesh.vertices.length() != numverts || - memcmp(mP, &mesh->verts[0], sizeof(float3) * numverts) == 0) { + memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) { /* no motion, remove attributes again */ if (b_mesh.vertices.length() != numverts) { VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name(); @@ -1157,7 +1174,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, VLOG(1) << "Filling deformation motion for object " << b_ob.name(); /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ - float3 *P = &mesh->verts[0]; + float3 *P = &mesh->get_verts()[0]; float3 *N = (attr_N) ? attr_N->data_float3() : NULL; for (int step = 0; step < motion_step; step++) { memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts); @@ -1170,7 +1187,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, if (b_mesh.vertices.length() != numverts) { VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name() << " at time " << motion_step; - memcpy(mP, &mesh->verts[0], sizeof(float3) * numverts); + memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts); if (mN != NULL) { memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts); } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 4146d87ad2e..4a70cbbf41f 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -32,6 +32,7 @@ #include "util/util_foreach.h" #include "util/util_hash.h" #include "util/util_logging.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN @@ -103,7 +104,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, bool use_particle_hair, bool show_lights, BlenderObjectCulling &culling, - bool *use_portal) + bool *use_portal, + TaskPool *geom_task_pool) { const bool is_instance = b_instance.is_instance(); BL::Object b_ob = b_instance.object(); @@ -181,6 +183,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, return NULL; } + /* Use task pool only for non-instances, since sync_dupli_particle accesses + * geometry. This restriction should be removed for better performance. */ + TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool; + /* key to lookup object */ ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair); Object *object; @@ -193,12 +199,19 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* Set transform at matching motion time step. */ int time_index = object->motion_step(motion_time); if (time_index >= 0) { - object->motion[time_index] = tfm; + array<Transform> motion = object->get_motion(); + motion[time_index] = tfm; + object->set_motion(motion); } /* mesh deformation */ - if (object->geometry) - sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair); + if (object->get_geometry()) + sync_geometry_motion(b_depsgraph, + b_ob_instance, + object, + motion_time, + use_particle_hair, + object_geom_task_pool); } return object; @@ -211,34 +224,36 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object_updated = true; /* mesh sync */ - object->geometry = sync_geometry( - b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair); + /* b_ob is owned by the iterator and will go out of scope at the end of the block. + * b_ob_instance is the original object and will remain valid for deferred geometry + * sync. */ + Geometry *geometry = sync_geometry(b_depsgraph, + b_ob_instance, + b_ob_instance, + object_updated, + use_particle_hair, + object_geom_task_pool); + object->set_geometry(geometry); /* special case not tracked by object update flags */ - /* holdout */ - if (use_holdout != object->use_holdout) { - object->use_holdout = use_holdout; - scene->object_manager->tag_update(scene); + if (sync_object_attributes(b_instance, object)) { object_updated = true; } - if (visibility != object->visibility) { - object->visibility = visibility; - object_updated = true; + /* holdout */ + object->set_use_holdout(use_holdout); + if (object->use_holdout_is_modified()) { + scene->object_manager->tag_update(scene); } + object->set_visibility(visibility); + bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); - if (is_shadow_catcher != object->is_shadow_catcher) { - object->is_shadow_catcher = is_shadow_catcher; - object_updated = true; - } + object->set_is_shadow_catcher(is_shadow_catcher); float shadow_terminator_offset = get_float(cobject, "shadow_terminator_offset"); - if (shadow_terminator_offset != object->shadow_terminator_offset) { - object->shadow_terminator_offset = shadow_terminator_offset; - object_updated = true; - } + object->set_shadow_terminator_offset(shadow_terminator_offset); /* sync the asset name for Cryptomatte */ BL::Object parent = b_ob.parent(); @@ -252,48 +267,49 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, else { parent_name = b_ob.name(); } - if (object->asset_name != parent_name) { - object->asset_name = parent_name; - object_updated = true; - } + object->set_asset_name(parent_name); /* 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->geometry && object->geometry->need_update) || - tfm != object->tfm) { + if (object->is_modified() || object_updated || + (object->get_geometry() && object->get_geometry()->is_modified()) || + tfm != object->get_tfm()) { object->name = b_ob.name().c_str(); - object->pass_id = b_ob.pass_index(); - object->color = get_float3(b_ob.color()); - object->tfm = tfm; - object->motion.clear(); + object->set_pass_id(b_ob.pass_index()); + object->set_color(get_float3(b_ob.color())); + object->set_tfm(tfm); + array<Transform> motion; + object->set_motion(motion); /* motion blur */ Scene::MotionType need_motion = scene->need_motion(); - if (need_motion != Scene::MOTION_NONE && object->geometry) { - Geometry *geom = object->geometry; - geom->use_motion_blur = false; - geom->motion_steps = 0; + if (need_motion != Scene::MOTION_NONE && object->get_geometry()) { + Geometry *geom = object->get_geometry(); + geom->set_use_motion_blur(false); + geom->set_motion_steps(0); uint motion_steps; if (need_motion == Scene::MOTION_BLUR) { motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); - geom->motion_steps = motion_steps; + geom->set_motion_steps(motion_steps); if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { - geom->use_motion_blur = true; + geom->set_use_motion_blur(true); } } else { motion_steps = 3; - geom->motion_steps = motion_steps; + geom->set_motion_steps(motion_steps); } - object->motion.clear(); - object->motion.resize(motion_steps, transform_empty()); + motion.resize(motion_steps, transform_empty()); if (motion_steps) { - object->motion[motion_steps / 2] = tfm; + motion[motion_steps / 2] = tfm; + + /* update motion socket before trying to access object->motion_time */ + object->set_motion(motion); for (size_t step = 0; step < motion_steps; step++) { motion_times.insert(object->motion_time(step)); @@ -303,15 +319,15 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* dupli texture coordinates and random_id */ if (is_instance) { - object->dupli_generated = 0.5f * get_float3(b_instance.orco()) - - make_float3(0.5f, 0.5f, 0.5f); - object->dupli_uv = get_float2(b_instance.uv()); - object->random_id = b_instance.random_id(); + object->set_dupli_generated(0.5f * get_float3(b_instance.orco()) - + make_float3(0.5f, 0.5f, 0.5f)); + object->set_dupli_uv(get_float2(b_instance.uv())); + object->set_random_id(b_instance.random_id()); } else { - object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f); - object->dupli_uv = make_float2(0.0f, 0.0f); - object->random_id = hash_uint2(hash_string(object->name.c_str()), 0); + object->set_dupli_generated(make_float3(0.0f, 0.0f, 0.0f)); + object->set_dupli_uv(make_float2(0.0f, 0.0f)); + object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0)); } object->tag_update(scene); @@ -325,12 +341,141 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, return object; } +/* This function mirrors drw_uniform_property_lookup in draw_instance_data.cpp */ +static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value) +{ + PointerRNA ptr; + PropertyRNA *prop; + + if (!RNA_path_resolve(&b_id.ptr, name.c_str(), &ptr, &prop)) { + return false; + } + + PropertyType type = RNA_property_type(prop); + int arraylen = RNA_property_array_length(&ptr, prop); + + if (arraylen == 0) { + float value; + + if (type == PROP_FLOAT) + value = RNA_property_float_get(&ptr, prop); + else if (type == PROP_INT) + value = RNA_property_int_get(&ptr, prop); + else + return false; + + *r_value = make_float4(value, value, value, 1.0f); + return true; + } + else if (type == PROP_FLOAT && arraylen <= 4) { + *r_value = make_float4(0.0f, 0.0f, 0.0f, 1.0f); + RNA_property_float_get_array(&ptr, prop, &r_value->x); + return true; + } + + return false; +} + +/* This function mirrors drw_uniform_attribute_lookup in draw_instance_data.cpp */ +static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance, + const string &name, + bool use_instancer) +{ + string idprop_name = string_printf("[\"%s\"]", name.c_str()); + float4 value; + + /* If requesting instance data, check the parent particle system and object. */ + if (use_instancer && b_instance.is_instance()) { + BL::ParticleSystem b_psys = b_instance.particle_system(); + + if (b_psys) { + if (lookup_property(b_psys.settings(), idprop_name, &value) || + lookup_property(b_psys.settings(), name, &value)) { + return value; + } + } + if (lookup_property(b_instance.parent(), idprop_name, &value) || + lookup_property(b_instance.parent(), name, &value)) { + return value; + } + } + + /* Check the object and mesh. */ + BL::Object b_ob = b_instance.object(); + BL::ID b_data = b_ob.data(); + + if (lookup_property(b_ob, idprop_name, &value) || lookup_property(b_ob, name, &value) || + lookup_property(b_data, idprop_name, &value) || lookup_property(b_data, name, &value)) { + return value; + } + + return make_float4(0.0f); +} + +bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object) +{ + /* Find which attributes are needed. */ + AttributeRequestSet requests = object->get_geometry()->needed_attributes(); + + /* Delete attributes that became unnecessary. */ + vector<ParamValue> &attributes = object->attributes; + bool changed = false; + + for (int i = attributes.size() - 1; i >= 0; i--) { + if (!requests.find(attributes[i].name())) { + attributes.erase(attributes.begin() + i); + changed = true; + } + } + + /* Update attribute values. */ + foreach (AttributeRequest &req, requests.requests) { + ustring name = req.name; + + std::string real_name; + BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name); + + if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) { + bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER); + float4 value = lookup_instance_property(b_instance, real_name, use_instancer); + + /* Try finding the existing attribute value. */ + ParamValue *param = NULL; + + for (size_t i = 0; i < attributes.size(); i++) { + if (attributes[i].name() == name) { + param = &attributes[i]; + break; + } + } + + /* Replace or add the value. */ + ParamValue new_param(name, TypeDesc::TypeFloat4, 1, &value); + assert(new_param.datasize() == sizeof(value)); + + if (!param) { + changed = true; + attributes.push_back(new_param); + } + else if (memcmp(param->data(), &value, sizeof(value)) != 0) { + changed = true; + *param = new_param; + } + } + } + + return changed; +} + /* Object Loop */ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, float motion_time) { + /* Task pool for multithreaded geometry sync. */ + TaskPool geom_task_pool; + /* layer data */ bool motion = motion_time != 0.0f; @@ -355,8 +500,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights; BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); - BL::Depsgraph::object_instances_iterator b_instance_iter; + for (b_depsgraph.object_instances.begin(b_instance_iter); b_instance_iter != b_depsgraph.object_instances.end() && !cancel; ++b_instance_iter) { @@ -372,6 +517,11 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, /* Load per-object culling data. */ culling.init_object(scene, b_ob); + /* Ensure the object geom supporting the hair is processed before adding + * the hair processing task to the task pool, calling .to_mesh() on the + * same object in parallel does not work. */ + const bool sync_hair = b_instance.show_particles() && object_has_particle_hair(b_ob); + /* Object itself. */ if (b_instance.show_self()) { sync_object(b_depsgraph, @@ -381,11 +531,12 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, false, show_lights, culling, - &use_portal); + &use_portal, + sync_hair ? NULL : &geom_task_pool); } /* Particle hair as separate object. */ - if (b_instance.show_particles() && object_has_particle_hair(b_ob)) { + if (sync_hair) { sync_object(b_depsgraph, b_view_layer, b_instance, @@ -393,12 +544,15 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, true, show_lights, culling, - &use_portal); + &use_portal, + &geom_task_pool); } cancel = progress.get_cancel(); } + geom_task_pool.wait_work(); + progress.set_sync_status(""); if (!cancel && !motion) { @@ -431,20 +585,18 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render, if (b_override) b_cam = b_override; - Camera prevcam = *(scene->camera); - int frame_center = b_scene.frame_current(); float subframe_center = b_scene.frame_subframe(); float frame_center_delta = 0.0f; if (scene->need_motion() != Scene::MOTION_PASS && - scene->camera->motion_position != Camera::MOTION_POSITION_CENTER) { - float shuttertime = scene->camera->shuttertime; - if (scene->camera->motion_position == Camera::MOTION_POSITION_END) { + scene->camera->get_motion_position() != Camera::MOTION_POSITION_CENTER) { + float shuttertime = scene->camera->get_shuttertime(); + if (scene->camera->get_motion_position() == Camera::MOTION_POSITION_END) { frame_center_delta = -shuttertime * 0.5f; } else { - assert(scene->camera->motion_position == Camera::MOTION_POSITION_START); + assert(scene->camera->get_motion_position() == Camera::MOTION_POSITION_START); frame_center_delta = shuttertime * 0.5f; } @@ -505,10 +657,6 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render, python_thread_state_restore(python_thread_state); b_engine.frame_set(frame_center, subframe_center); python_thread_state_save(python_thread_state); - - /* tag camera for motion update */ - if (scene->camera->motion_modified(prevcam)) - scene->camera->tag_update(); } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp index bebecb364eb..cb7827b3c4a 100644 --- a/intern/cycles/blender/blender_object_cull.cpp +++ b/intern/cycles/blender/blender_object_cull.cpp @@ -34,10 +34,10 @@ BlenderObjectCulling::BlenderObjectCulling(Scene *scene, BL::Scene &b_scene) if (b_scene.render().use_simplify()) { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - use_scene_camera_cull_ = scene->camera->type != CAMERA_PANORAMA && + use_scene_camera_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA && !b_scene.render().use_multiview() && get_boolean(cscene, "use_camera_cull"); - use_scene_distance_cull_ = scene->camera->type != CAMERA_PANORAMA && + use_scene_distance_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA && !b_scene.render().use_multiview() && get_boolean(cscene, "use_distance_cull"); @@ -123,7 +123,7 @@ bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8]) bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8]) { - float3 camera_position = transform_get_column(&scene->camera->matrix, 3); + float3 camera_position = transform_get_column(&scene->camera->get_matrix(), 3); float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX), bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index e5eab1ae62b..ca221b229b4 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -36,10 +36,10 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, if (!b_psys) return false; - object->hide_on_missing_motion = true; + object->set_hide_on_missing_motion(true); /* test if we need particle data */ - if (!object->geometry->need_attribute(scene, ATTR_STD_PARTICLE)) + if (!object->get_geometry()->need_attribute(scene, ATTR_STD_PARTICLE)) return false; /* don't handle child particles yet */ @@ -56,7 +56,8 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key); /* no update needed? */ - if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update) + if (!need_update && !object->get_geometry()->is_modified() && + !scene->object_manager->need_update) return true; /* first time used in this sync loop? clear and tag update */ @@ -80,10 +81,11 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, psys->particles.push_back_slow(pa); - if (object->particle_index != psys->particles.size() - 1) + object->set_particle_system(psys); + object->set_particle_index(psys->particles.size() - 1); + + if (object->particle_index_is_modified()) scene->object_manager->tag_update(scene); - object->particle_system = psys; - object->particle_index = psys->particles.size() - 1; /* return that this object has particle data */ return true; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 8f662c9e291..8566d0e7ed5 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -444,17 +444,17 @@ void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_ } /* Write cryptomatte metadata. */ - if (scene->film->cryptomatte_passes & CRYPT_OBJECT) { + if (scene->film->get_cryptomatte_passes() & CRYPT_OBJECT) { add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoObject", scene->object_manager->get_cryptomatte_objects(scene)); } - if (scene->film->cryptomatte_passes & CRYPT_MATERIAL) { + if (scene->film->get_cryptomatte_passes() & CRYPT_MATERIAL) { add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoMaterial", scene->shader_manager->get_cryptomatte_materials(scene)); } - if (scene->film->cryptomatte_passes & CRYPT_ASSET) { + if (scene->film->get_cryptomatte_passes() & CRYPT_ASSET) { add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoAsset", scene->object_manager->get_cryptomatte_assets(scene)); @@ -475,6 +475,11 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) { b_depsgraph = b_depsgraph_; + if (session->progress.get_cancel()) { + update_status_progress(); + return; + } + /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind( @@ -505,9 +510,9 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) /* Set buffer params, using film settings from sync_render_passes. */ buffer_params.passes = passes; - buffer_params.denoising_data_pass = scene->film->denoising_data_pass; - buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; - buffer_params.denoising_prefiltered_pass = scene->film->denoising_prefiltered_pass; + buffer_params.denoising_data_pass = scene->film->get_denoising_data_pass(); + buffer_params.denoising_clean_pass = scene->film->get_denoising_clean_pass(); + buffer_params.denoising_prefiltered_pass = scene->film->get_denoising_prefiltered_pass(); BL::RenderResult::views_iterator b_view_iter; @@ -544,8 +549,9 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) /* Make sure all views have different noise patterns. - hardcoded value just to make it random */ if (view_index != 0) { - scene->integrator->seed += hash_uint2(scene->integrator->seed, - hash_uint2(view_index * 0xdeadbeef, 0)); + int seed = scene->integrator->get_seed(); + seed += hash_uint2(seed, hash_uint2(view_index * 0xdeadbeef, 0)); + scene->integrator->set_seed(seed); scene->integrator->tag_update(scene); } @@ -717,7 +723,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay, if (!buffers->copy_from_device()) return; - float exposure = scene->film->exposure; + float exposure = scene->film->get_exposure(); vector<float> pixels(rtile.w * rtile.h * 4); @@ -834,10 +840,7 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_) session->set_denoising(session_params.denoising); /* Update film if denoising data was enabled or disabled. */ - if (scene->film->denoising_data_pass != buffer_params.denoising_data_pass) { - scene->film->denoising_data_pass = buffer_params.denoising_data_pass; - scene->film->tag_update(scene); - } + scene->film->set_denoising_data_pass(buffer_params.denoising_data_pass); /* reset if needed */ if (scene->need_reset()) { @@ -896,7 +899,7 @@ bool BlenderSession::draw(int w, int h) sync->sync_view(b_v3d, b_rv3d, width, height); - if (scene->camera->need_update) + if (scene->camera->is_modified()) reset = true; session->scene->mutex.unlock(); @@ -1111,8 +1114,11 @@ void BlenderSession::update_resumable_tile_manager(int num_samples) VLOG(1) << "Samples range start is " << range_start_sample << ", " << "number of samples to render is " << range_num_samples; - scene->integrator->start_sample = rounded_range_start_sample; - scene->integrator->tag_update(scene); + scene->integrator->set_start_sample(rounded_range_start_sample); + + if (scene->integrator->is_modified()) { + scene->integrator->tag_update(scene); + } session->tile_manager.range_start_sample = rounded_range_start_sample; session->tile_manager.range_num_samples = rounded_range_num_samples; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index c171982b29d..ac86cf3345c 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -42,11 +42,11 @@ typedef map<string, ConvertNode *> ProxyMap; /* Find */ -void BlenderSync::find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader) +void BlenderSync::find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader) { Shader *shader = (id) ? shader_map.find(id) : default_shader; - used_shaders.push_back(shader); + used_shaders.push_back_slow(shader); shader->tag_used(scene); } @@ -97,6 +97,53 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image) return (ImageAlphaType)validate_enum_value(value, IMAGE_ALPHA_NUM_TYPES, IMAGE_ALPHA_AUTO); } +/* Attribute name translation utilities */ + +/* Since Eevee needs to know whether the attribute is uniform or varying + * at the time it compiles the shader for the material, Blender had to + * introduce different namespaces (types) in its attribute node. However, + * Cycles already has object attributes that form a uniform namespace with + * the more common varying attributes. Without completely reworking the + * attribute handling in Cycles to introduce separate namespaces (this could + * be especially hard for OSL which directly uses the name string), the + * space identifier has to be added to the attribute name as a prefix. + * + * The prefixes include a control character to ensure the user specified + * name can't accidentally include a special prefix. + */ + +static const string_view object_attr_prefix("\x01object:"); +static const string_view instancer_attr_prefix("\x01instancer:"); + +static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type) +{ + switch (type) { + case BL::ShaderNodeAttribute::attribute_type_OBJECT: + return ustring::concat(object_attr_prefix, name); + case BL::ShaderNodeAttribute::attribute_type_INSTANCER: + return ustring::concat(instancer_attr_prefix, name); + default: + return ustring(name); + } +} + +BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name) +{ + string_view sname(name); + + if (sname.substr(0, object_attr_prefix.size()) == object_attr_prefix) { + *r_real_name = sname.substr(object_attr_prefix.size()); + return BL::ShaderNodeAttribute::attribute_type_OBJECT; + } + + if (sname.substr(0, instancer_attr_prefix.size()) == instancer_attr_prefix) { + *r_real_name = sname.substr(instancer_attr_prefix.size()); + return BL::ShaderNodeAttribute::attribute_type_INSTANCER; + } + + return BL::ShaderNodeAttribute::attribute_type_GEOMETRY; +} + /* Graph */ static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name) @@ -194,19 +241,19 @@ static void set_default_value(ShaderInput *input, } } -static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping &b_mapping) +static void get_tex_mapping(TextureNode *mapping, BL::TexMapping &b_mapping) { if (!b_mapping) return; - mapping->translation = get_float3(b_mapping.translation()); - mapping->rotation = get_float3(b_mapping.rotation()); - mapping->scale = get_float3(b_mapping.scale()); - mapping->type = (TextureMapping::Type)b_mapping.vector_type(); + mapping->set_tex_mapping_translation(get_float3(b_mapping.translation())); + mapping->set_tex_mapping_rotation(get_float3(b_mapping.rotation())); + mapping->set_tex_mapping_scale(get_float3(b_mapping.scale())); + mapping->set_tex_mapping_type((TextureMapping::Type)b_mapping.vector_type()); - mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x(); - mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y(); - mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z(); + mapping->set_tex_mapping_x_mapping((TextureMapping::Mapping)b_mapping.mapping_x()); + mapping->set_tex_mapping_y_mapping((TextureMapping::Mapping)b_mapping.mapping_y()); + mapping->set_tex_mapping_z_mapping((TextureMapping::Mapping)b_mapping.mapping_z()); } static ShaderNode *add_node(Scene *scene, @@ -225,34 +272,48 @@ static ShaderNode *add_node(Scene *scene, BL::ShaderNodeRGBCurve b_curve_node(b_node); BL::CurveMapping mapping(b_curve_node.mapping()); RGBCurvesNode *curves = graph->create_node<RGBCurvesNode>(); - curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, true); - curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x); + array<float3> curve_mapping_curves; + float min_x, max_x; + curvemapping_color_to_array(mapping, curve_mapping_curves, RAMP_TABLE_SIZE, true); + curvemapping_minmax(mapping, true, &min_x, &max_x); + curves->set_min_x(min_x); + curves->set_max_x(max_x); + curves->set_curves(curve_mapping_curves); node = curves; } if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) { BL::ShaderNodeVectorCurve b_curve_node(b_node); BL::CurveMapping mapping(b_curve_node.mapping()); VectorCurvesNode *curves = graph->create_node<VectorCurvesNode>(); - curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, false); - curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x); + array<float3> curve_mapping_curves; + float min_x, max_x; + curvemapping_color_to_array(mapping, curve_mapping_curves, RAMP_TABLE_SIZE, false); + curvemapping_minmax(mapping, false, &min_x, &max_x); + curves->set_min_x(min_x); + curves->set_max_x(max_x); + curves->set_curves(curve_mapping_curves); node = curves; } else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) { RGBRampNode *ramp = graph->create_node<RGBRampNode>(); BL::ShaderNodeValToRGB b_ramp_node(b_node); BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp()); - colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE); - ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT; + array<float3> ramp_values; + array<float> ramp_alpha; + colorramp_to_array(b_color_ramp, ramp_values, ramp_alpha, RAMP_TABLE_SIZE); + ramp->set_ramp(ramp_values); + ramp->set_ramp_alpha(ramp_alpha); + ramp->set_interpolate(b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT); node = ramp; } else if (b_node.is_a(&RNA_ShaderNodeRGB)) { ColorNode *color = graph->create_node<ColorNode>(); - color->value = get_node_output_rgba(b_node, "Color"); + color->set_value(get_node_output_rgba(b_node, "Color")); node = color; } else if (b_node.is_a(&RNA_ShaderNodeValue)) { ValueNode *value = graph->create_node<ValueNode>(); - value->value = get_node_output_value(b_node, "Value"); + value->set_value(get_node_output_value(b_node, "Value")); node = value; } else if (b_node.is_a(&RNA_ShaderNodeCameraData)) { @@ -270,8 +331,8 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) { BL::ShaderNodeMixRGB b_mix_node(b_node); MixNode *mix = graph->create_node<MixNode>(); - mix->type = (NodeMix)b_mix_node.blend_type(); - mix->use_clamp = b_mix_node.use_clamp(); + mix->set_mix_type((NodeMix)b_mix_node.blend_type()); + mix->set_use_clamp(b_mix_node.use_clamp()); node = mix; } else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) { @@ -301,43 +362,45 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeMapRange)) { BL::ShaderNodeMapRange b_map_range_node(b_node); MapRangeNode *map_range_node = graph->create_node<MapRangeNode>(); - map_range_node->clamp = b_map_range_node.clamp(); - map_range_node->type = (NodeMapRangeType)b_map_range_node.interpolation_type(); + map_range_node->set_clamp(b_map_range_node.clamp()); + map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type()); node = map_range_node; } else if (b_node.is_a(&RNA_ShaderNodeClamp)) { BL::ShaderNodeClamp b_clamp_node(b_node); ClampNode *clamp_node = graph->create_node<ClampNode>(); - clamp_node->type = (NodeClampType)b_clamp_node.clamp_type(); + clamp_node->set_clamp_type((NodeClampType)b_clamp_node.clamp_type()); node = clamp_node; } else if (b_node.is_a(&RNA_ShaderNodeMath)) { BL::ShaderNodeMath b_math_node(b_node); MathNode *math_node = graph->create_node<MathNode>(); - math_node->type = (NodeMathType)b_math_node.operation(); - math_node->use_clamp = b_math_node.use_clamp(); + math_node->set_math_type((NodeMathType)b_math_node.operation()); + math_node->set_use_clamp(b_math_node.use_clamp()); node = math_node; } else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) { BL::ShaderNodeVectorMath b_vector_math_node(b_node); VectorMathNode *vector_math_node = graph->create_node<VectorMathNode>(); - vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation(); + vector_math_node->set_math_type((NodeVectorMathType)b_vector_math_node.operation()); node = vector_math_node; } else if (b_node.is_a(&RNA_ShaderNodeVectorRotate)) { BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node); VectorRotateNode *vector_rotate_node = graph->create_node<VectorRotateNode>(); - vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type(); - vector_rotate_node->invert = b_vector_rotate_node.invert(); + vector_rotate_node->set_rotate_type( + (NodeVectorRotateType)b_vector_rotate_node.rotation_type()); + vector_rotate_node->set_invert(b_vector_rotate_node.invert()); node = vector_rotate_node; } else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) { BL::ShaderNodeVectorTransform b_vector_transform_node(b_node); VectorTransformNode *vtransform = graph->create_node<VectorTransformNode>(); - vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type(); - vtransform->convert_from = (NodeVectorTransformConvertSpace) - b_vector_transform_node.convert_from(); - vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to(); + vtransform->set_transform_type((NodeVectorTransformType)b_vector_transform_node.vector_type()); + vtransform->set_convert_from( + (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_from()); + vtransform->set_convert_to( + (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to()); node = vtransform; } else if (b_node.is_a(&RNA_ShaderNodeNormal)) { @@ -345,13 +408,13 @@ static ShaderNode *add_node(Scene *scene, b_node.outputs.begin(out_it); NormalNode *norm = graph->create_node<NormalNode>(); - norm->direction = get_node_output_vector(b_node, "Normal"); + norm->set_direction(get_node_output_vector(b_node, "Normal")); node = norm; } else if (b_node.is_a(&RNA_ShaderNodeMapping)) { BL::ShaderNodeMapping b_mapping_node(b_node); MappingNode *mapping = graph->create_node<MappingNode>(); - mapping->type = (NodeMappingType)b_mapping_node.vector_type(); + mapping->set_mapping_type((NodeMappingType)b_mapping_node.vector_type()); node = mapping; } else if (b_node.is_a(&RNA_ShaderNodeFresnel)) { @@ -369,7 +432,8 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeAttribute)) { BL::ShaderNodeAttribute b_attr_node(b_node); AttributeNode *attr = graph->create_node<AttributeNode>(); - attr->attribute = b_attr_node.attribute_name(); + attr->set_attribute(blender_attribute_name_add_type(b_attr_node.attribute_name(), + b_attr_node.attribute_type())); node = attr; } else if (b_node.is_a(&RNA_ShaderNodeBackground)) { @@ -384,16 +448,16 @@ static ShaderNode *add_node(Scene *scene, switch (b_aniso_node.distribution()) { case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN: - aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; + aniso->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID); break; case BL::ShaderNodeBsdfAnisotropic::distribution_GGX: - aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID; + aniso->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID); break; case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX: - aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID; + aniso->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID); break; case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY: - aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID; + aniso->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); break; } @@ -409,16 +473,16 @@ static ShaderNode *add_node(Scene *scene, switch (b_subsurface_node.falloff()) { case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC: - subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID; + subsurface->set_falloff(CLOSURE_BSSRDF_CUBIC_ID); break; case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN: - subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID; + subsurface->set_falloff(CLOSURE_BSSRDF_GAUSSIAN_ID); break; case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY: - subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID; + subsurface->set_falloff(CLOSURE_BSSRDF_BURLEY_ID); break; case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK: - subsurface->falloff = CLOSURE_BSSRDF_RANDOM_WALK_ID; + subsurface->set_falloff(CLOSURE_BSSRDF_RANDOM_WALK_ID); break; } @@ -430,19 +494,19 @@ static ShaderNode *add_node(Scene *scene, switch (b_glossy_node.distribution()) { case BL::ShaderNodeBsdfGlossy::distribution_SHARP: - glossy->distribution = CLOSURE_BSDF_REFLECTION_ID; + glossy->set_distribution(CLOSURE_BSDF_REFLECTION_ID); break; case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN: - glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; + glossy->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID); break; case BL::ShaderNodeBsdfGlossy::distribution_GGX: - glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID; + glossy->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID); break; case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY: - glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID; + glossy->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); break; case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX: - glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID; + glossy->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID); break; } node = glossy; @@ -452,16 +516,16 @@ static ShaderNode *add_node(Scene *scene, GlassBsdfNode *glass = graph->create_node<GlassBsdfNode>(); switch (b_glass_node.distribution()) { case BL::ShaderNodeBsdfGlass::distribution_SHARP: - glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID; + glass->set_distribution(CLOSURE_BSDF_SHARP_GLASS_ID); break; case BL::ShaderNodeBsdfGlass::distribution_BECKMANN: - glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID; + glass->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); break; case BL::ShaderNodeBsdfGlass::distribution_GGX: - glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID; + glass->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); break; case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX: - glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; + glass->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID); break; } node = glass; @@ -471,13 +535,13 @@ static ShaderNode *add_node(Scene *scene, RefractionBsdfNode *refraction = graph->create_node<RefractionBsdfNode>(); switch (b_refraction_node.distribution()) { case BL::ShaderNodeBsdfRefraction::distribution_SHARP: - refraction->distribution = CLOSURE_BSDF_REFRACTION_ID; + refraction->set_distribution(CLOSURE_BSDF_REFRACTION_ID); break; case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: - refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + refraction->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); break; case BL::ShaderNodeBsdfRefraction::distribution_GGX: - refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + refraction->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); break; } node = refraction; @@ -487,10 +551,10 @@ static ShaderNode *add_node(Scene *scene, ToonBsdfNode *toon = graph->create_node<ToonBsdfNode>(); switch (b_toon_node.component()) { case BL::ShaderNodeBsdfToon::component_DIFFUSE: - toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID; + toon->set_component(CLOSURE_BSDF_DIFFUSE_TOON_ID); break; case BL::ShaderNodeBsdfToon::component_GLOSSY: - toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID; + toon->set_component(CLOSURE_BSDF_GLOSSY_TOON_ID); break; } node = toon; @@ -500,10 +564,10 @@ static ShaderNode *add_node(Scene *scene, HairBsdfNode *hair = graph->create_node<HairBsdfNode>(); switch (b_hair_node.component()) { case BL::ShaderNodeBsdfHair::component_Reflection: - hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID; + hair->set_component(CLOSURE_BSDF_HAIR_REFLECTION_ID); break; case BL::ShaderNodeBsdfHair::component_Transmission: - hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID; + hair->set_component(CLOSURE_BSDF_HAIR_TRANSMISSION_ID); break; } node = hair; @@ -511,11 +575,11 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) { BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node); PrincipledHairBsdfNode *principled_hair = graph->create_node<PrincipledHairBsdfNode>(); - principled_hair->parametrization = (NodePrincipledHairParametrization)get_enum( - b_principled_hair_node.ptr, - "parametrization", - NODE_PRINCIPLED_HAIR_NUM, - NODE_PRINCIPLED_HAIR_REFLECTANCE); + principled_hair->set_parametrization( + (NodePrincipledHairParametrization)get_enum(b_principled_hair_node.ptr, + "parametrization", + NODE_PRINCIPLED_HAIR_NUM, + NODE_PRINCIPLED_HAIR_REFLECTANCE)); node = principled_hair; } else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) { @@ -523,18 +587,18 @@ static ShaderNode *add_node(Scene *scene, PrincipledBsdfNode *principled = graph->create_node<PrincipledBsdfNode>(); switch (b_principled_node.distribution()) { case BL::ShaderNodeBsdfPrincipled::distribution_GGX: - principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID; + principled->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); break; case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX: - principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; + principled->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID); break; } switch (b_principled_node.subsurface_method()) { case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY: - principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_ID; + principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_ID); break; case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK: - principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID; + principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID); break; } node = principled; @@ -554,9 +618,9 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) { BL::ShaderNodeAmbientOcclusion b_ao_node(b_node); AmbientOcclusionNode *ao = graph->create_node<AmbientOcclusionNode>(); - ao->samples = b_ao_node.samples(); - ao->inside = b_ao_node.inside(); - ao->only_local = b_ao_node.only_local(); + ao->set_samples(b_ao_node.samples()); + ao->set_inside(b_ao_node.inside()); + ao->set_only_local(b_ao_node.only_local()); node = ao; } else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) { @@ -575,7 +639,7 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeWireframe)) { BL::ShaderNodeWireframe b_wireframe_node(b_node); WireframeNode *wire = graph->create_node<WireframeNode>(); - wire->use_pixel_size = b_wireframe_node.use_pixel_size(); + wire->set_use_pixel_size(b_wireframe_node.use_pixel_size()); node = wire; } else if (b_node.is_a(&RNA_ShaderNodeWavelength)) { @@ -605,13 +669,13 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) { BL::ShaderNodeVertexColor b_vertex_color_node(b_node); VertexColorNode *vertex_color_node = graph->create_node<VertexColorNode>(); - vertex_color_node->layer_name = b_vertex_color_node.layer_name(); + vertex_color_node->set_layer_name(ustring(b_vertex_color_node.layer_name())); node = vertex_color_node; } else if (b_node.is_a(&RNA_ShaderNodeBump)) { BL::ShaderNodeBump b_bump_node(b_node); BumpNode *bump = graph->create_node<BumpNode>(); - bump->invert = b_bump_node.invert(); + bump->set_invert(b_bump_node.invert()); node = bump; } else if (b_node.is_a(&RNA_ShaderNodeScript)) { @@ -644,25 +708,26 @@ static ShaderNode *add_node(Scene *scene, BL::ImageUser b_image_user(b_image_node.image_user()); ImageTextureNode *image = graph->create_node<ImageTextureNode>(); - image->interpolation = get_image_interpolation(b_image_node); - image->extension = get_image_extension(b_image_node); - image->projection = (NodeImageProjection)b_image_node.projection(); - image->projection_blend = b_image_node.projection_blend(); + image->set_interpolation(get_image_interpolation(b_image_node)); + image->set_extension(get_image_extension(b_image_node)); + image->set_projection((NodeImageProjection)b_image_node.projection()); + image->set_projection_blend(b_image_node.projection_blend()); BL::TexMapping b_texture_mapping(b_image_node.texture_mapping()); - get_tex_mapping(&image->tex_mapping, b_texture_mapping); + get_tex_mapping(image, b_texture_mapping); if (b_image) { PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr; - image->colorspace = get_enum_identifier(colorspace_ptr, "name"); + image->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name"))); - image->animated = b_image_node.image_user().use_auto_refresh(); - image->alpha_type = get_image_alpha_type(b_image); + image->set_animated(b_image_node.image_user().use_auto_refresh()); + image->set_alpha_type(get_image_alpha_type(b_image)); - image->tiles.clear(); + array<int> tiles; BL::Image::tiles_iterator b_iter; for (b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) { - image->tiles.push_back(b_iter->number()); + tiles.push_back_slow(b_iter->number()); } + image->set_tiles(tiles); /* builtin images will use callback-based reading because * they could only be loaded correct from blender side @@ -684,8 +749,9 @@ static ShaderNode *add_node(Scene *scene, new BlenderImageLoader(b_image, image_frame), image->image_params()); } else { - image->filename = image_user_file_path( - b_image_user, b_image, b_scene.frame_current(), true); + ustring filename = ustring( + image_user_file_path(b_image_user, b_image, b_scene.frame_current(), true)); + image->set_filename(filename); } } node = image; @@ -696,17 +762,17 @@ static ShaderNode *add_node(Scene *scene, BL::ImageUser b_image_user(b_env_node.image_user()); EnvironmentTextureNode *env = graph->create_node<EnvironmentTextureNode>(); - env->interpolation = get_image_interpolation(b_env_node); - env->projection = (NodeEnvironmentProjection)b_env_node.projection(); + env->set_interpolation(get_image_interpolation(b_env_node)); + env->set_projection((NodeEnvironmentProjection)b_env_node.projection()); BL::TexMapping b_texture_mapping(b_env_node.texture_mapping()); - get_tex_mapping(&env->tex_mapping, b_texture_mapping); + get_tex_mapping(env, b_texture_mapping); if (b_image) { PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr; - env->colorspace = get_enum_identifier(colorspace_ptr, "name"); + env->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name"))); - env->animated = b_env_node.image_user().use_auto_refresh(); - env->alpha_type = get_image_alpha_type(b_image); + env->set_animated(b_env_node.image_user().use_auto_refresh()); + env->set_alpha_type(get_image_alpha_type(b_image)); bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED || b_image.source() == BL::Image::source_MOVIE || @@ -719,8 +785,8 @@ static ShaderNode *add_node(Scene *scene, env->image_params()); } else { - env->filename = image_user_file_path( - b_image_user, b_image, b_scene.frame_current(), false); + env->set_filename( + ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current(), false))); } } node = env; @@ -728,103 +794,103 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) { BL::ShaderNodeTexGradient b_gradient_node(b_node); GradientTextureNode *gradient = graph->create_node<GradientTextureNode>(); - gradient->type = (NodeGradientType)b_gradient_node.gradient_type(); + gradient->set_gradient_type((NodeGradientType)b_gradient_node.gradient_type()); BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping()); - get_tex_mapping(&gradient->tex_mapping, b_texture_mapping); + get_tex_mapping(gradient, b_texture_mapping); node = gradient; } else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) { BL::ShaderNodeTexVoronoi b_voronoi_node(b_node); VoronoiTextureNode *voronoi = graph->create_node<VoronoiTextureNode>(); - voronoi->dimensions = b_voronoi_node.voronoi_dimensions(); - voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature(); - voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance(); + voronoi->set_dimensions(b_voronoi_node.voronoi_dimensions()); + voronoi->set_feature((NodeVoronoiFeature)b_voronoi_node.feature()); + voronoi->set_metric((NodeVoronoiDistanceMetric)b_voronoi_node.distance()); BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping()); - get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping); + get_tex_mapping(voronoi, b_texture_mapping); node = voronoi; } else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) { BL::ShaderNodeTexMagic b_magic_node(b_node); MagicTextureNode *magic = graph->create_node<MagicTextureNode>(); - magic->depth = b_magic_node.turbulence_depth(); + magic->set_depth(b_magic_node.turbulence_depth()); BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping()); - get_tex_mapping(&magic->tex_mapping, b_texture_mapping); + get_tex_mapping(magic, b_texture_mapping); node = magic; } else if (b_node.is_a(&RNA_ShaderNodeTexWave)) { BL::ShaderNodeTexWave b_wave_node(b_node); WaveTextureNode *wave = graph->create_node<WaveTextureNode>(); - wave->type = (NodeWaveType)b_wave_node.wave_type(); - wave->bands_direction = (NodeWaveBandsDirection)b_wave_node.bands_direction(); - wave->rings_direction = (NodeWaveRingsDirection)b_wave_node.rings_direction(); - wave->profile = (NodeWaveProfile)b_wave_node.wave_profile(); + wave->set_wave_type((NodeWaveType)b_wave_node.wave_type()); + wave->set_bands_direction((NodeWaveBandsDirection)b_wave_node.bands_direction()); + wave->set_rings_direction((NodeWaveRingsDirection)b_wave_node.rings_direction()); + wave->set_profile((NodeWaveProfile)b_wave_node.wave_profile()); BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping()); - get_tex_mapping(&wave->tex_mapping, b_texture_mapping); + get_tex_mapping(wave, b_texture_mapping); node = wave; } else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) { BL::ShaderNodeTexChecker b_checker_node(b_node); CheckerTextureNode *checker = graph->create_node<CheckerTextureNode>(); BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping()); - get_tex_mapping(&checker->tex_mapping, b_texture_mapping); + get_tex_mapping(checker, b_texture_mapping); node = checker; } else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) { BL::ShaderNodeTexBrick b_brick_node(b_node); BrickTextureNode *brick = graph->create_node<BrickTextureNode>(); - brick->offset = b_brick_node.offset(); - brick->offset_frequency = b_brick_node.offset_frequency(); - brick->squash = b_brick_node.squash(); - brick->squash_frequency = b_brick_node.squash_frequency(); + brick->set_offset(b_brick_node.offset()); + brick->set_offset_frequency(b_brick_node.offset_frequency()); + brick->set_squash(b_brick_node.squash()); + brick->set_squash_frequency(b_brick_node.squash_frequency()); BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping()); - get_tex_mapping(&brick->tex_mapping, b_texture_mapping); + get_tex_mapping(brick, b_texture_mapping); node = brick; } else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) { BL::ShaderNodeTexNoise b_noise_node(b_node); NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>(); - noise->dimensions = b_noise_node.noise_dimensions(); + noise->set_dimensions(b_noise_node.noise_dimensions()); BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping()); - get_tex_mapping(&noise->tex_mapping, b_texture_mapping); + get_tex_mapping(noise, b_texture_mapping); node = noise; } else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) { BL::ShaderNodeTexMusgrave b_musgrave_node(b_node); MusgraveTextureNode *musgrave_node = graph->create_node<MusgraveTextureNode>(); - musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type(); - musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions(); + musgrave_node->set_musgrave_type((NodeMusgraveType)b_musgrave_node.musgrave_type()); + musgrave_node->set_dimensions(b_musgrave_node.musgrave_dimensions()); BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping()); - get_tex_mapping(&musgrave_node->tex_mapping, b_texture_mapping); + get_tex_mapping(musgrave_node, b_texture_mapping); node = musgrave_node; } else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) { BL::ShaderNodeTexCoord b_tex_coord_node(b_node); TextureCoordinateNode *tex_coord = graph->create_node<TextureCoordinateNode>(); - tex_coord->from_dupli = b_tex_coord_node.from_instancer(); + tex_coord->set_from_dupli(b_tex_coord_node.from_instancer()); if (b_tex_coord_node.object()) { - tex_coord->use_transform = true; - tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world()); + tex_coord->set_use_transform(true); + tex_coord->set_ob_tfm(get_transform(b_tex_coord_node.object().matrix_world())); } node = tex_coord; } else if (b_node.is_a(&RNA_ShaderNodeTexSky)) { BL::ShaderNodeTexSky b_sky_node(b_node); SkyTextureNode *sky = graph->create_node<SkyTextureNode>(); - sky->type = (NodeSkyType)b_sky_node.sky_type(); - sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction())); - sky->turbidity = b_sky_node.turbidity(); - sky->ground_albedo = b_sky_node.ground_albedo(); - sky->sun_disc = b_sky_node.sun_disc(); - sky->sun_size = b_sky_node.sun_size(); - sky->sun_intensity = b_sky_node.sun_intensity(); - sky->sun_elevation = b_sky_node.sun_elevation(); - sky->sun_rotation = b_sky_node.sun_rotation(); - sky->altitude = 1000.0f * b_sky_node.altitude(); - sky->air_density = b_sky_node.air_density(); - sky->dust_density = b_sky_node.dust_density(); - sky->ozone_density = b_sky_node.ozone_density(); + sky->set_sky_type((NodeSkyType)b_sky_node.sky_type()); + sky->set_sun_direction(normalize(get_float3(b_sky_node.sun_direction()))); + sky->set_turbidity(b_sky_node.turbidity()); + sky->set_ground_albedo(b_sky_node.ground_albedo()); + sky->set_sun_disc(b_sky_node.sun_disc()); + sky->set_sun_size(b_sky_node.sun_size()); + sky->set_sun_intensity(b_sky_node.sun_intensity()); + sky->set_sun_elevation(b_sky_node.sun_elevation()); + sky->set_sun_rotation(b_sky_node.sun_rotation()); + sky->set_altitude(1000.0f * b_sky_node.altitude()); + sky->set_air_density(b_sky_node.air_density()); + sky->set_dust_density(b_sky_node.dust_density()); + sky->set_ozone_density(b_sky_node.ozone_density()); BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping()); - get_tex_mapping(&sky->tex_mapping, b_texture_mapping); + get_tex_mapping(sky, b_texture_mapping); node = sky; } else if (b_node.is_a(&RNA_ShaderNodeTexIES)) { @@ -832,13 +898,14 @@ static ShaderNode *add_node(Scene *scene, IESLightNode *ies = graph->create_node<IESLightNode>(); switch (b_ies_node.mode()) { case BL::ShaderNodeTexIES::mode_EXTERNAL: - ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath()); + ies->set_filename(ustring(blender_absolute_path(b_data, b_ntree, b_ies_node.filepath()))); break; case BL::ShaderNodeTexIES::mode_INTERNAL: - ies->ies = get_text_datablock_content(b_ies_node.ies().ptr); - if (ies->ies.empty()) { - ies->ies = "\n"; + ustring ies_content = ustring(get_text_datablock_content(b_ies_node.ies().ptr)); + if (ies_content.empty()) { + ies_content = "\n"; } + ies->set_ies(ies_content); break; } node = ies; @@ -846,36 +913,36 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeTexWhiteNoise)) { BL::ShaderNodeTexWhiteNoise b_tex_white_noise_node(b_node); WhiteNoiseTextureNode *white_noise_node = graph->create_node<WhiteNoiseTextureNode>(); - white_noise_node->dimensions = b_tex_white_noise_node.noise_dimensions(); + white_noise_node->set_dimensions(b_tex_white_noise_node.noise_dimensions()); node = white_noise_node; } else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) { BL::ShaderNodeNormalMap b_normal_map_node(b_node); NormalMapNode *nmap = graph->create_node<NormalMapNode>(); - nmap->space = (NodeNormalMapSpace)b_normal_map_node.space(); - nmap->attribute = b_normal_map_node.uv_map(); + nmap->set_space((NodeNormalMapSpace)b_normal_map_node.space()); + nmap->set_attribute(ustring(b_normal_map_node.uv_map())); node = nmap; } else if (b_node.is_a(&RNA_ShaderNodeTangent)) { BL::ShaderNodeTangent b_tangent_node(b_node); TangentNode *tangent = graph->create_node<TangentNode>(); - tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type(); - tangent->axis = (NodeTangentAxis)b_tangent_node.axis(); - tangent->attribute = b_tangent_node.uv_map(); + tangent->set_direction_type((NodeTangentDirectionType)b_tangent_node.direction_type()); + tangent->set_axis((NodeTangentAxis)b_tangent_node.axis()); + tangent->set_attribute(ustring(b_tangent_node.uv_map())); node = tangent; } else if (b_node.is_a(&RNA_ShaderNodeUVMap)) { BL::ShaderNodeUVMap b_uvmap_node(b_node); UVMapNode *uvm = graph->create_node<UVMapNode>(); - uvm->attribute = b_uvmap_node.uv_map(); - uvm->from_dupli = b_uvmap_node.from_instancer(); + uvm->set_attribute(ustring(b_uvmap_node.uv_map())); + uvm->set_from_dupli(b_uvmap_node.from_instancer()); node = uvm; } else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { BL::ShaderNodeTexPointDensity b_point_density_node(b_node); PointDensityTextureNode *point_density = graph->create_node<PointDensityTextureNode>(); - point_density->space = (NodeTexVoxelSpace)b_point_density_node.space(); - point_density->interpolation = get_image_interpolation(b_point_density_node); + point_density->set_space((NodeTexVoxelSpace)b_point_density_node.space()); + point_density->set_interpolation(get_image_interpolation(b_point_density_node)); point_density->handle = scene->image_manager->add_image( new BlenderPointDensityLoader(b_depsgraph, b_point_density_node), point_density->image_params()); @@ -892,33 +959,33 @@ static ShaderNode *add_node(Scene *scene, if (b_ob) { float3 loc, size; point_density_texture_space(b_depsgraph, b_point_density_node, loc, size); - point_density->tfm = transform_translate(-loc) * transform_scale(size) * - transform_inverse(get_transform(b_ob.matrix_world())); + point_density->set_tfm(transform_translate(-loc) * transform_scale(size) * + transform_inverse(get_transform(b_ob.matrix_world()))); } } else if (b_node.is_a(&RNA_ShaderNodeBevel)) { BL::ShaderNodeBevel b_bevel_node(b_node); BevelNode *bevel = graph->create_node<BevelNode>(); - bevel->samples = b_bevel_node.samples(); + bevel->set_samples(b_bevel_node.samples()); node = bevel; } else if (b_node.is_a(&RNA_ShaderNodeDisplacement)) { BL::ShaderNodeDisplacement b_disp_node(b_node); DisplacementNode *disp = graph->create_node<DisplacementNode>(); - disp->space = (NodeNormalMapSpace)b_disp_node.space(); + disp->set_space((NodeNormalMapSpace)b_disp_node.space()); node = disp; } else if (b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) { BL::ShaderNodeVectorDisplacement b_disp_node(b_node); VectorDisplacementNode *disp = graph->create_node<VectorDisplacementNode>(); - disp->space = (NodeNormalMapSpace)b_disp_node.space(); - disp->attribute = ""; + disp->set_space((NodeNormalMapSpace)b_disp_node.space()); + disp->set_attribute(ustring("")); node = disp; } else if (b_node.is_a(&RNA_ShaderNodeOutputAOV)) { BL::ShaderNodeOutputAOV b_aov_node(b_node); OutputAOVNode *aov = graph->create_node<OutputAOVNode>(); - aov->name = b_aov_node.name(); + aov->set_name(ustring(b_aov_node.name())); node = aov; } @@ -1245,7 +1312,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat.name().c_str(); - shader->pass_id = b_mat.pass_index(); + shader->set_pass_id(b_mat.pass_index()); /* create nodes */ if (b_mat.use_nodes() && b_mat.node_tree()) { @@ -1255,7 +1322,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) } else { DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>(); - diffuse->color = get_float3(b_mat.diffuse_color()); + diffuse->set_color(get_float3(b_mat.diffuse_color())); graph->add(diffuse); ShaderNode *out = graph->output(); @@ -1264,13 +1331,13 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) /* settings */ PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles"); - shader->use_mis = get_boolean(cmat, "sample_as_light"); - shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow"); - shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume"); - shader->volume_sampling_method = get_volume_sampling(cmat); - shader->volume_interpolation_method = get_volume_interpolation(cmat); - shader->volume_step_rate = get_float(cmat, "volume_step_rate"); - shader->displacement_method = get_displacement_method(cmat); + shader->set_use_mis(get_boolean(cmat, "sample_as_light")); + shader->set_use_transparent_shadow(get_boolean(cmat, "use_transparent_shadow")); + shader->set_heterogeneous_volume(!get_boolean(cmat, "homogeneous_volume")); + shader->set_volume_sampling_method(get_volume_sampling(cmat)); + shader->set_volume_interpolation_method(get_volume_interpolation(cmat)); + shader->set_volume_step_rate(get_float(cmat, "volume_step_rate")); + shader->set_displacement_method(get_displacement_method(cmat)); shader->set_graph(graph); @@ -1311,7 +1378,6 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all) { Background *background = scene->background; - Background prevbackground = *background; BL::World b_world = b_scene.world(); @@ -1331,14 +1397,14 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, /* volume */ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); - shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume"); - shader->volume_sampling_method = get_volume_sampling(cworld); - shader->volume_interpolation_method = get_volume_interpolation(cworld); - shader->volume_step_rate = get_float(cworld, "volume_step_size"); + shader->set_heterogeneous_volume(!get_boolean(cworld, "homogeneous_volume")); + shader->set_volume_sampling_method(get_volume_sampling(cworld)); + shader->set_volume_interpolation_method(get_volume_interpolation(cworld)); + shader->set_volume_step_rate(get_float(cworld, "volume_step_size")); } else if (new_viewport_parameters.use_scene_world && b_world) { BackgroundNode *background = graph->create_node<BackgroundNode>(); - background->color = get_float3(b_world.color()); + background->set_color(get_float3(b_world.color())); graph->add(background); ShaderNode *out = graph->output(); @@ -1360,29 +1426,32 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, graph->add(light_path); MixNode *mix_scene_with_background = graph->create_node<MixNode>(); - mix_scene_with_background->color2 = world_color; + mix_scene_with_background->set_color2(world_color); graph->add(mix_scene_with_background); EnvironmentTextureNode *texture_environment = graph->create_node<EnvironmentTextureNode>(); - texture_environment->tex_mapping.type = TextureMapping::VECTOR; - texture_environment->tex_mapping.rotation[2] = new_viewport_parameters.studiolight_rotate_z; - texture_environment->filename = new_viewport_parameters.studiolight_path; + texture_environment->set_tex_mapping_type(TextureMapping::VECTOR); + float3 rotation_z = texture_environment->get_tex_mapping_rotation(); + rotation_z[2] = new_viewport_parameters.studiolight_rotate_z; + texture_environment->set_tex_mapping_rotation(rotation_z); + texture_environment->set_filename(new_viewport_parameters.studiolight_path); graph->add(texture_environment); MixNode *mix_intensity = graph->create_node<MixNode>(); - mix_intensity->type = NODE_MIX_MUL; - mix_intensity->fac = 1.0f; - mix_intensity->color2 = make_float3(new_viewport_parameters.studiolight_intensity, - new_viewport_parameters.studiolight_intensity, - new_viewport_parameters.studiolight_intensity); + mix_intensity->set_mix_type(NODE_MIX_MUL); + mix_intensity->set_fac(1.0f); + mix_intensity->set_color2(make_float3(new_viewport_parameters.studiolight_intensity, + new_viewport_parameters.studiolight_intensity, + new_viewport_parameters.studiolight_intensity)); graph->add(mix_intensity); TextureCoordinateNode *texture_coordinate = graph->create_node<TextureCoordinateNode>(); graph->add(texture_coordinate); MixNode *mix_background_with_environment = graph->create_node<MixNode>(); - mix_background_with_environment->fac = new_viewport_parameters.studiolight_background_alpha; - mix_background_with_environment->color1 = world_color; + mix_background_with_environment->set_fac( + new_viewport_parameters.studiolight_background_alpha); + mix_background_with_environment->set_color1(world_color); graph->add(mix_background_with_environment); ShaderNode *out = graph->output(); @@ -1404,9 +1473,9 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, /* AO */ BL::WorldLighting b_light = b_world.light_settings(); - background->use_ao = b_light.use_ambient_occlusion(); - background->ao_factor = b_light.ao_factor(); - background->ao_distance = b_light.distance(); + background->set_use_ao(b_light.use_ambient_occlusion()); + background->set_ao_factor(b_light.ao_factor()); + background->set_ao_distance(b_light.distance()); /* visibility */ PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility"); @@ -1418,12 +1487,12 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, visibility |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0; visibility |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0; - background->visibility = visibility; + background->set_visibility(visibility); } else { - background->use_ao = false; - background->ao_factor = 0.0f; - background->ao_distance = FLT_MAX; + background->set_use_ao(false); + background->set_ao_factor(0.0f); + background->set_ao_distance(FLT_MAX); } shader->set_graph(graph); @@ -1432,22 +1501,23 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, } PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - background->transparent = b_scene.render().film_transparent(); + background->set_transparent(b_scene.render().film_transparent()); - if (background->transparent) { - background->transparent_glass = get_boolean(cscene, "film_transparent_glass"); - background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness"); + if (background->get_transparent()) { + background->set_transparent_glass(get_boolean(cscene, "film_transparent_glass")); + background->set_transparent_roughness_threshold( + get_float(cscene, "film_transparent_roughness")); } else { - background->transparent_glass = false; - background->transparent_roughness_threshold = 0.0f; + background->set_transparent_glass(false); + background->set_transparent_roughness_threshold(0.0f); } - background->use_shader = view_layer.use_background_shader | - viewport_parameters.custom_viewport_parameters(); - background->use_ao = background->use_ao && view_layer.use_background_ao; + background->set_use_shader(view_layer.use_background_shader | + viewport_parameters.custom_viewport_parameters()); + background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao); - if (background->modified(prevbackground)) + if (background->is_modified()) background->tag_update(scene); } @@ -1480,8 +1550,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all) } else { EmissionNode *emission = graph->create_node<EmissionNode>(); - emission->color = make_float3(1.0f, 1.0f, 1.0f); - emission->strength = 1.0f; + emission->set_color(make_float3(1.0f, 1.0f, 1.0f)); + emission->set_strength(1.0f); graph->add(emission); ShaderNode *out = graph->output(); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 0139afb711d..94ff0ff1473 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -118,9 +118,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d if (dicing_prop_changed) { for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) { Geometry *geom = iter.second; - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + if (mesh->get_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)); @@ -238,7 +238,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, 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) { + scene->camera->get_motion_position() == Camera::MOTION_POSITION_CENTER) { sync_objects(b_depsgraph, b_v3d); } sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state); @@ -264,70 +264,75 @@ void BlenderSync::sync_integrator() experimental = (get_enum(cscene, "feature_set") != 0); Integrator *integrator = scene->integrator; - Integrator previntegrator = *integrator; - integrator->min_bounce = get_int(cscene, "min_light_bounces"); - integrator->max_bounce = get_int(cscene, "max_bounces"); + integrator->set_min_bounce(get_int(cscene, "min_light_bounces")); + integrator->set_max_bounce(get_int(cscene, "max_bounces")); - integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces"); - integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces"); - integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces"); - integrator->max_volume_bounce = get_int(cscene, "volume_bounces"); + integrator->set_max_diffuse_bounce(get_int(cscene, "diffuse_bounces")); + integrator->set_max_glossy_bounce(get_int(cscene, "glossy_bounces")); + integrator->set_max_transmission_bounce(get_int(cscene, "transmission_bounces")); + integrator->set_max_volume_bounce(get_int(cscene, "volume_bounces")); - integrator->transparent_min_bounce = get_int(cscene, "min_transparent_bounces"); - integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces"); + integrator->set_transparent_min_bounce(get_int(cscene, "min_transparent_bounces")); + integrator->set_transparent_max_bounce(get_int(cscene, "transparent_max_bounces")); - integrator->volume_max_steps = get_int(cscene, "volume_max_steps"); - integrator->volume_step_rate = (preview) ? get_float(cscene, "volume_preview_step_rate") : - get_float(cscene, "volume_step_rate"); + integrator->set_volume_max_steps(get_int(cscene, "volume_max_steps")); + float volume_step_rate = (preview) ? get_float(cscene, "volume_preview_step_rate") : + get_float(cscene, "volume_step_rate"); + integrator->set_volume_step_rate(volume_step_rate); - integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective"); - integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive"); - integrator->filter_glossy = get_float(cscene, "blur_glossy"); + integrator->set_caustics_reflective(get_boolean(cscene, "caustics_reflective")); + integrator->set_caustics_refractive(get_boolean(cscene, "caustics_refractive")); + integrator->set_filter_glossy(get_float(cscene, "blur_glossy")); - integrator->seed = get_int(cscene, "seed"); + int seed = get_int(cscene, "seed"); if (get_boolean(cscene, "use_animated_seed")) { - integrator->seed = hash_uint2(b_scene.frame_current(), get_int(cscene, "seed")); + seed = hash_uint2(b_scene.frame_current(), get_int(cscene, "seed")); if (b_scene.frame_subframe() != 0.0f) { /* TODO(sergey): Ideally should be some sort of hash_merge, * but this is good enough for now. */ - integrator->seed += hash_uint2((int)(b_scene.frame_subframe() * (float)INT_MAX), - get_int(cscene, "seed")); + seed += hash_uint2((int)(b_scene.frame_subframe() * (float)INT_MAX), + get_int(cscene, "seed")); } } - integrator->sampling_pattern = (SamplingPattern)get_enum( - cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL); + integrator->set_seed(seed); - integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct"); - integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect"); + integrator->set_sample_clamp_direct(get_float(cscene, "sample_clamp_direct")); + integrator->set_sample_clamp_indirect(get_float(cscene, "sample_clamp_indirect")); if (!preview) { - if (integrator->motion_blur != r.use_motion_blur()) { + if (integrator->get_motion_blur() != r.use_motion_blur()) { scene->object_manager->tag_update(scene); - scene->camera->tag_update(); + scene->camera->tag_modified(); } - integrator->motion_blur = r.use_motion_blur(); + integrator->set_motion_blur(r.use_motion_blur()); } - integrator->method = (Integrator::Method)get_enum( - cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH); + integrator->set_method((Integrator::Method)get_enum( + cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH)); + + integrator->set_sample_all_lights_direct(get_boolean(cscene, "sample_all_lights_direct")); + integrator->set_sample_all_lights_indirect(get_boolean(cscene, "sample_all_lights_indirect")); + integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold")); + + SamplingPattern sampling_pattern = (SamplingPattern)get_enum( + cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL); - integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct"); - integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect"); - integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold"); + int adaptive_min_samples = INT_MAX; if (RNA_boolean_get(&cscene, "use_adaptive_sampling")) { - integrator->sampling_pattern = SAMPLING_PATTERN_PMJ; - integrator->adaptive_min_samples = get_int(cscene, "adaptive_min_samples"); - integrator->adaptive_threshold = get_float(cscene, "adaptive_threshold"); + sampling_pattern = SAMPLING_PATTERN_PMJ; + adaptive_min_samples = get_int(cscene, "adaptive_min_samples"); + integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold")); } else { - integrator->adaptive_min_samples = INT_MAX; - integrator->adaptive_threshold = 0.0f; + integrator->set_adaptive_threshold(0.0f); } + integrator->set_sampling_pattern(sampling_pattern); + int diffuse_samples = get_int(cscene, "diffuse_samples"); int glossy_samples = get_int(cscene, "glossy_samples"); int transmission_samples = get_int(cscene, "transmission_samples"); @@ -337,39 +342,40 @@ void BlenderSync::sync_integrator() int volume_samples = get_int(cscene, "volume_samples"); if (get_boolean(cscene, "use_square_samples")) { - integrator->diffuse_samples = diffuse_samples * diffuse_samples; - integrator->glossy_samples = glossy_samples * glossy_samples; - integrator->transmission_samples = transmission_samples * transmission_samples; - integrator->ao_samples = ao_samples * ao_samples; - integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples; - integrator->subsurface_samples = subsurface_samples * subsurface_samples; - integrator->volume_samples = volume_samples * volume_samples; - integrator->adaptive_min_samples = min( - integrator->adaptive_min_samples * integrator->adaptive_min_samples, INT_MAX); + integrator->set_diffuse_samples(diffuse_samples * diffuse_samples); + integrator->set_glossy_samples(glossy_samples * glossy_samples); + integrator->set_transmission_samples(transmission_samples * transmission_samples); + integrator->set_ao_samples(ao_samples * ao_samples); + integrator->set_mesh_light_samples(mesh_light_samples * mesh_light_samples); + integrator->set_subsurface_samples(subsurface_samples * subsurface_samples); + integrator->set_volume_samples(volume_samples * volume_samples); + adaptive_min_samples = min(adaptive_min_samples * adaptive_min_samples, INT_MAX); } else { - integrator->diffuse_samples = diffuse_samples; - integrator->glossy_samples = glossy_samples; - integrator->transmission_samples = transmission_samples; - integrator->ao_samples = ao_samples; - integrator->mesh_light_samples = mesh_light_samples; - integrator->subsurface_samples = subsurface_samples; - integrator->volume_samples = volume_samples; + integrator->set_diffuse_samples(diffuse_samples); + integrator->set_glossy_samples(glossy_samples); + integrator->set_transmission_samples(transmission_samples); + integrator->set_ao_samples(ao_samples); + integrator->set_mesh_light_samples(mesh_light_samples); + integrator->set_subsurface_samples(subsurface_samples); + integrator->set_volume_samples(volume_samples); } + integrator->set_adaptive_min_samples(adaptive_min_samples); + if (b_scene.render().use_simplify()) { if (preview) { - integrator->ao_bounces = get_int(cscene, "ao_bounces"); + integrator->set_ao_bounces(get_int(cscene, "ao_bounces")); } else { - integrator->ao_bounces = get_int(cscene, "ao_bounces_render"); + integrator->set_ao_bounces(get_int(cscene, "ao_bounces_render")); } } else { - integrator->ao_bounces = 0; + integrator->set_ao_bounces(0); } - if (integrator->modified(previntegrator)) + if (integrator->is_modified()) integrator->tag_update(scene); } @@ -380,46 +386,42 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d) PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); Film *film = scene->film; - Film prevfilm = *film; vector<Pass> prevpasses = scene->passes; if (b_v3d) { - film->display_pass = update_viewport_display_passes(b_v3d, scene->passes); + film->set_display_pass(update_viewport_display_passes(b_v3d, scene->passes)); } - film->exposure = get_float(cscene, "film_exposure"); - film->filter_type = (FilterType)get_enum( - cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS); - film->filter_width = (film->filter_type == FILTER_BOX) ? 1.0f : - get_float(cscene, "filter_width"); + film->set_exposure(get_float(cscene, "film_exposure")); + film->set_filter_type( + (FilterType)get_enum(cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS)); + float filter_width = (film->get_filter_type() == FILTER_BOX) ? 1.0f : + get_float(cscene, "filter_width"); + film->set_filter_width(filter_width); if (b_scene.world()) { BL::WorldMistSettings b_mist = b_scene.world().mist_settings(); - film->mist_start = b_mist.start(); - film->mist_depth = b_mist.depth(); + film->set_mist_start(b_mist.start()); + film->set_mist_depth(b_mist.depth()); switch (b_mist.falloff()) { case BL::WorldMistSettings::falloff_QUADRATIC: - film->mist_falloff = 2.0f; + film->set_mist_falloff(2.0f); break; case BL::WorldMistSettings::falloff_LINEAR: - film->mist_falloff = 1.0f; + film->set_mist_falloff(1.0f); break; case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC: - film->mist_falloff = 0.5f; + film->set_mist_falloff(0.5f); break; } } - if (film->modified(prevfilm)) { - film->tag_update(scene); - } - if (!Pass::equals(prevpasses, scene->passes)) { film->tag_passes_update(scene, prevpasses, false); - film->tag_update(scene); + film->tag_modified(); } } @@ -585,7 +587,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::RenderPass b_pass(*b_pass_iter); PassType pass_type = get_pass_type(b_pass); - if (pass_type == PASS_MOTION && scene->integrator->motion_blur) + if (pass_type == PASS_MOTION && scene->integrator->get_motion_blur()) continue; if (pass_type != PASS_NONE) Pass::add(pass_type, passes, b_pass.name().c_str()); @@ -593,12 +595,12 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles"); - scene->film->denoising_flags = 0; + int denoising_flags = 0; if (denoising.use || denoising.store_passes) { if (denoising.type == DENOISER_NLM) { #define MAP_OPTION(name, flag) \ if (!get_boolean(crl, name)) { \ - scene->film->denoising_flags |= flag; \ + denoising_flags |= flag; \ } \ ((void)0) MAP_OPTION("denoising_diffuse_direct", DENOISING_CLEAN_DIFFUSE_DIR); @@ -611,6 +613,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str()); } + scene->film->set_denoising_flags(denoising_flags); if (denoising.store_passes) { b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str()); @@ -622,7 +625,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str()); } - if (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) { + if (scene->film->get_denoising_flags() & DENOISING_CLEAN_ALL_PASSES) { b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str()); } } @@ -665,16 +668,15 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, /* Cryptomatte stores two ID/weight pairs per RGBA layer. * User facing parameter is the number of pairs. */ int crypto_depth = divide_up(min(16, get_int(crl, "pass_crypto_depth")), 2); - scene->film->cryptomatte_depth = crypto_depth; - scene->film->cryptomatte_passes = CRYPT_NONE; + scene->film->set_cryptomatte_depth(crypto_depth); + CryptomatteType cryptomatte_passes = CRYPT_NONE; if (get_boolean(crl, "use_pass_crypto_object")) { for (int i = 0; i < crypto_depth; i++) { string passname = cryptomatte_prefix + string_printf("Object%02d", i); b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } - scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | - CRYPT_OBJECT); + cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT); } if (get_boolean(crl, "use_pass_crypto_material")) { for (int i = 0; i < crypto_depth; i++) { @@ -682,8 +684,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } - scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | - CRYPT_MATERIAL); + cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL); } if (get_boolean(crl, "use_pass_crypto_asset")) { for (int i = 0; i < crypto_depth; i++) { @@ -691,13 +692,12 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } - scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | - CRYPT_ASSET); + cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET); } - if (get_boolean(crl, "pass_crypto_accurate") && scene->film->cryptomatte_passes != CRYPT_NONE) { - scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | - CRYPT_ACCURATE); + if (get_boolean(crl, "pass_crypto_accurate") && cryptomatte_passes != CRYPT_NONE) { + cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ACCURATE); } + scene->film->set_cryptomatte_passes(cryptomatte_passes); if (adaptive_sampling) { Pass::add(PASS_ADAPTIVE_AUX_BUFFER, passes); @@ -721,14 +721,14 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } RNA_END; - scene->film->denoising_data_pass = denoising.use || denoising.store_passes; - scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); - scene->film->denoising_prefiltered_pass = denoising.store_passes && - denoising.type == DENOISER_NLM; + scene->film->set_denoising_data_pass(denoising.use || denoising.store_passes); + scene->film->set_denoising_clean_pass(scene->film->get_denoising_flags() & + DENOISING_CLEAN_ALL_PASSES); + scene->film->set_denoising_prefiltered_pass(denoising.store_passes && + denoising.type == DENOISER_NLM); - scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold(); + scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); scene->film->tag_passes_update(scene, passes); - scene->film->tag_update(scene); scene->integrator->tag_update(scene); return passes; diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 62fd1ac2351..ccf059d7704 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -50,6 +50,7 @@ class ViewLayer; class Shader; class ShaderGraph; class ShaderNode; +class TaskPool; class BlenderSync { public: @@ -145,23 +146,20 @@ class BlenderSync { bool use_particle_hair, bool show_lights, BlenderObjectCulling &culling, - bool *use_portal); + bool *use_portal, + TaskPool *geom_task_pool); + + bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object); /* Volume */ - void sync_volume(BL::Object &b_ob, Volume *volume, const vector<Shader *> &used_shaders); + void sync_volume(BL::Object &b_ob, Volume *volume); /* Mesh */ - void sync_mesh(BL::Depsgraph b_depsgraph, - BL::Object b_ob, - Mesh *mesh, - const vector<Shader *> &used_shaders); + 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, - Hair *hair, - const vector<Shader *> &used_shaders); + void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair); void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step); void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0); void sync_particle_hair( @@ -177,12 +175,15 @@ class BlenderSync { BL::Object &b_ob, BL::Object &b_ob_instance, bool object_updated, - bool use_particle_hair); + bool use_particle_hair, + TaskPool *task_pool); + void sync_geometry_motion(BL::Depsgraph &b_depsgraph, BL::Object &b_ob, Object *object, float motion_time, - bool use_particle_hair); + bool use_particle_hair, + TaskPool *task_pool); /* Light */ void sync_light(BL::Object &b_parent, @@ -206,7 +207,7 @@ class BlenderSync { void free_data_after_sync(BL::Depsgraph &b_depsgraph); /* util */ - void find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader); + void find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader); bool BKE_object_is_modified(BL::Object &b_ob); bool object_is_geometry(BL::Object &b_ob); bool object_is_light(BL::Object &b_ob); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 1ea34b41aa2..5185ebae789 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -40,6 +40,9 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile); CCL_NAMESPACE_BEGIN +typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType; +BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name); + void python_thread_state_save(void **python_thread_state); void python_thread_state_restore(void **python_thread_state); diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 48ae5a2c5ae..094d4bbc08c 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -202,7 +202,7 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, fl continue; } - volume->clipping = b_domain.clipping(); + volume->set_clipping(b_domain.clipping()); Attribute *attr = volume->attributes.add(std); @@ -255,9 +255,9 @@ static void sync_volume_object(BL::BlendData &b_data, BL::VolumeRender b_render(b_volume.render()); - volume->clipping = b_render.clipping(); - volume->step_size = b_render.step_size(); - volume->object_space = (b_render.space() == BL::VolumeRender::space_OBJECT); + volume->set_clipping(b_render.clipping()); + volume->set_step_size(b_render.step_size()); + volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT)); /* Find grid with matching name. */ BL::Volume::grids_iterator b_grid_iter; @@ -300,12 +300,9 @@ static void sync_volume_object(BL::BlendData &b_data, } } -void BlenderSync::sync_volume(BL::Object &b_ob, - Volume *volume, - const vector<Shader *> &used_shaders) +void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume) { - volume->clear(); - volume->used_shaders = used_shaders; + volume->clear(true); if (view_layer.use_volumes) { if (b_ob.type() == BL::Object::type_VOLUME) { diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 222c1c40f92..a51ac4cf4a9 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -209,30 +209,30 @@ void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility) /* Primitives. */ if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ - const Hair *hair = static_cast<const Hair *>(ob->geometry); + const Hair *hair = static_cast<const Hair *>(ob->get_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, &hair->curve_keys[0], &hair->curve_radius[0], bbox); + curve.bounds_grow(k, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], bbox); /* Motion curves. */ - if (hair->use_motion_blur) { + if (hair->get_use_motion_blur()) { Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr) { - size_t hair_size = hair->curve_keys.size(); - size_t steps = hair->motion_steps - 1; + size_t hair_size = hair->get_curve_keys().size(); + size_t steps = hair->get_motion_steps() - 1; float3 *key_steps = attr->data_float3(); for (size_t i = 0; i < steps; i++) - curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox); + curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox); } } } else { /* Triangles. */ - const Mesh *mesh = static_cast<const Mesh *>(ob->geometry); + const Mesh *mesh = static_cast<const Mesh *>(ob->get_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]; @@ -264,7 +264,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 = static_cast<const Mesh *>(objects[tob]->geometry); + const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->get_geometry()); int tidx = pack.prim_index[idx]; Mesh::Triangle t = mesh->get_triangle(tidx); @@ -329,7 +329,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) */ for (size_t i = 0; i < pack.prim_index.size(); i++) { if (pack.prim_index[i] != -1) { - pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset; + pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset; } } @@ -390,7 +390,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) /* merge */ foreach (Object *ob, objects) { - Geometry *geom = ob->geometry; + Geometry *geom = ob->get_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. diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 360cac59e9b..1727082b7ec 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -169,12 +169,12 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair const size_t num_curves = hair->num_curves(); for (uint j = 0; j < num_curves; j++) { const Hair::Curve curve = hair->get_curve(j); - const float *curve_radius = &hair->curve_radius[0]; + const float *curve_radius = &hair->get_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, &hair->curve_keys[0], curve_radius, bounds); + curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius, bounds); if (bounds.valid()) { int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k); references.push_back(BVHReference(bounds, j, i, packed_type)); @@ -189,9 +189,9 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair */ /* TODO(sergey): Support motion steps for spatially split BVH. */ BoundBox bounds = BoundBox::empty; - 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; + curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius, bounds); + const size_t num_keys = hair->get_curve_keys().size(); + const size_t num_steps = hair->get_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); @@ -210,10 +210,10 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair */ 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 = hair->motion_steps; - const float3 *curve_keys = &hair->curve_keys[0]; + const size_t num_steps = hair->get_motion_steps(); + const float3 *curve_keys = &hair->get_curve_keys()[0]; const float3 *key_steps = curve_attr_mP->data_float3(); - const size_t num_keys = hair->curve_keys.size(); + const size_t num_keys = hair->get_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. @@ -270,11 +270,11 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); add_reference_triangles(root, center, mesh, i); } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); add_reference_curves(root, center, hair, i); } @@ -299,11 +299,11 @@ static size_t count_curve_segments(Hair *hair) static size_t count_primitives(Geometry *geom) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); return mesh->num_triangles(); } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); return count_curve_segments(hair); } @@ -321,14 +321,14 @@ void BVHBuild::add_references(BVHRange &root) if (!ob->is_traceable()) { continue; } - if (!ob->geometry->is_instanced()) { - num_alloc_references += count_primitives(ob->geometry); + if (!ob->get_geometry()->is_instanced()) { + num_alloc_references += count_primitives(ob->get_geometry()); } else num_alloc_references++; } else { - num_alloc_references += count_primitives(ob->geometry); + num_alloc_references += count_primitives(ob->get_geometry()); } } @@ -344,13 +344,13 @@ void BVHBuild::add_references(BVHRange &root) ++i; continue; } - if (!ob->geometry->is_instanced()) - add_reference_geometry(bounds, center, ob->geometry, i); + if (!ob->get_geometry()->is_instanced()) + add_reference_geometry(bounds, center, ob->get_geometry(), i); else add_reference_object(bounds, center, ob, i); } else - add_reference_geometry(bounds, center, ob->geometry, i); + add_reference_geometry(bounds, center, ob->get_geometry(), i); i++; diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 53776a55257..910e3780b2e 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -300,11 +300,11 @@ static bool rtc_progress_func(void *user_ptr, const double n) static size_t count_primitives(Geometry *geom) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); return mesh->num_triangles(); } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); return hair->num_segments(); } @@ -402,15 +402,15 @@ void BVHEmbree::build(Progress &progress, Stats *stats_) if (!ob->is_traceable()) { continue; } - if (!ob->geometry->is_instanced()) { - prim_count += count_primitives(ob->geometry); + if (!ob->get_geometry()->is_instanced()) { + prim_count += count_primitives(ob->get_geometry()); } else { ++prim_count; } } else { - prim_count += count_primitives(ob->geometry); + prim_count += count_primitives(ob->get_geometry()); } } @@ -429,7 +429,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_) ++i; continue; } - if (!ob->geometry->is_instanced()) { + if (!ob->get_geometry()->is_instanced()) { add_object(ob, i); } else { @@ -480,15 +480,15 @@ BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/) void BVHEmbree::add_object(Object *ob, int i) { - Geometry *geom = ob->geometry; + Geometry *geom = ob->get_geometry(); - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); if (mesh->num_triangles() > 0) { add_triangles(ob, mesh, i); } } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); if (hair->num_curves() > 0) { add_curves(ob, hair, i); @@ -498,17 +498,17 @@ void BVHEmbree::add_object(Object *ob, int i) void BVHEmbree::add_instance(Object *ob, int i) { - if (!ob || !ob->geometry) { + if (!ob || !ob->get_geometry()) { assert(0); return; } - BVHEmbree *instance_bvh = (BVHEmbree *)(ob->geometry->bvh); + BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->bvh); if (instance_bvh->top_level != this) { instance_bvh->top_level = this; } - const size_t num_object_motion_steps = ob->use_motion() ? ob->motion.size() : 1; + const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1; const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT); assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT); @@ -517,8 +517,8 @@ void BVHEmbree::add_instance(Object *ob, int i) rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); if (ob->use_motion()) { - array<DecomposedTransform> decomp(ob->motion.size()); - transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size()); + array<DecomposedTransform> decomp(ob->get_motion().size()); + transform_motion_decompose(decomp.data(), ob->get_motion().data(), ob->get_motion().size()); for (size_t step = 0; step < num_motion_steps; ++step) { RTCQuaternionDecomposition rtc_decomp; rtcInitQuaternionDecomposition(&rtc_decomp); @@ -534,7 +534,8 @@ void BVHEmbree::add_instance(Object *ob, int i) } } else { - rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->tfm); + rtcSetGeometryTransform( + geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->get_tfm()); } pack.prim_index.push_back_slow(-1); @@ -558,7 +559,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) if (mesh->has_motion_blur()) { attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_geometry_motion_steps = mesh->motion_steps; + num_geometry_motion_steps = mesh->get_motion_steps(); } } @@ -620,7 +621,7 @@ void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, con if (mesh->has_motion_blur()) { attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = mesh->motion_steps; + num_motion_steps = mesh->get_motion_steps(); t_mid = (num_motion_steps - 1) / 2; if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { assert(0); @@ -672,7 +673,7 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c if (hair->has_motion_blur()) { attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = hair->motion_steps; + num_motion_steps = hair->get_motion_steps(); } } @@ -689,11 +690,11 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c /* Copy the CV data to Embree */ const int t_mid = (num_motion_steps - 1) / 2; - const float *curve_radius = &hair->curve_radius[0]; + const float *curve_radius = &hair->get_curve_radius()[0]; for (int t = 0; t < num_motion_steps; ++t) { const float3 *verts; if (t == t_mid || attr_mP == NULL) { - verts = &hair->curve_keys[0]; + verts = &hair->get_curve_keys()[0]; } else { int t_ = (t > t_mid) ? (t - 1) : t; @@ -741,7 +742,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) if (hair->has_motion_blur()) { attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_geometry_motion_steps = hair->motion_steps; + num_geometry_motion_steps = hair->get_motion_steps(); } } @@ -826,7 +827,7 @@ void BVHEmbree::pack_nodes(const BVHNode *) for (size_t i = 0; i < pack.prim_index.size(); ++i) { if (pack.prim_index[i] != -1) { - pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset; + pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset; } } @@ -843,7 +844,7 @@ void BVHEmbree::pack_nodes(const BVHNode *) map<Geometry *, int> geometry_map; foreach (Object *ob, objects) { - Geometry *geom = ob->geometry; + Geometry *geom = ob->get_geometry(); BVH *bvh = geom->bvh; if (geom->need_build_bvh(BVH_LAYOUT_EMBREE)) { @@ -873,7 +874,7 @@ void BVHEmbree::pack_nodes(const BVHNode *) /* merge */ foreach (Object *ob, objects) { - Geometry *geom = ob->geometry; + Geometry *geom = ob->get_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. @@ -948,10 +949,10 @@ 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->geometry->is_instanced())) { - Geometry *geom = ob->geometry; + if (!params.top_level || (ob->is_traceable() && !ob->get_geometry()->is_instanced())) { + Geometry *geom = ob->get_geometry(); - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); if (mesh->num_triangles() > 0) { RTCGeometry geom = rtcGetGeometry(scene, geom_id); @@ -959,7 +960,7 @@ void BVHEmbree::refit_nodes() rtcCommitGeometry(geom); } } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); if (hair->num_curves() > 0) { RTCGeometry geom = rtcGetGeometry(scene, geom_id + 1); diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp index 0527c0eeda8..52fc9c0a50d 100644 --- a/intern/cycles/bvh/bvh_optix.cpp +++ b/intern/cycles/bvh/bvh_optix.cpp @@ -37,6 +37,9 @@ BVHOptiX::BVHOptiX(const BVHParams ¶ms_, const vector<Object *> &objects_) : BVH(params_, geometry_, objects_) { + optix_handle = 0; + optix_data_handle = 0; + do_refit = false; } BVHOptiX::~BVHOptiX() @@ -66,7 +69,7 @@ void BVHOptiX::pack_blas() assert(geometry.size() == 1 && objects.size() == 1); // These are built per-mesh Geometry *const geom = geometry[0]; - if (geom->type == Geometry::HAIR) { + if (geom->geometry_type == Geometry::HAIR) { Hair *const hair = static_cast<Hair *const>(geom); if (hair->num_curves() > 0) { const size_t num_curves = hair->num_curves(); @@ -77,7 +80,7 @@ void BVHOptiX::pack_blas() // '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 = (hair->use_motion_blur && + uint type = (hair->get_use_motion_blur() && hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) ? ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : PRIMITIVE_MOTION_CURVE_THICK) : @@ -95,7 +98,7 @@ void BVHOptiX::pack_blas() } } } - else if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *const mesh = static_cast<Mesh *const>(geom); if (mesh->num_triangles() > 0) { const size_t num_triangles = mesh->num_triangles(); @@ -104,7 +107,7 @@ void BVHOptiX::pack_blas() 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)) + if (mesh->get_use_motion_blur() && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) type = PRIMITIVE_MOTION_TRIANGLE; for (size_t k = 0; k < num_triangles; ++k) { @@ -116,14 +119,14 @@ void BVHOptiX::pack_blas() } // Initialize visibility to zero and later update it during top-level build - uint prev_visibility = objects[0]->visibility; - objects[0]->visibility = 0; + uint prev_visibility = objects[0]->get_visibility(); + objects[0]->set_visibility(0); // Update 'pack.prim_tri_index', 'pack.prim_tri_verts' and 'pack.prim_visibility' pack_primitives(); // Reset visibility after packing - objects[0]->visibility = prev_visibility; + objects[0]->set_visibility(prev_visibility); } void BVHOptiX::pack_tlas() @@ -167,7 +170,7 @@ void BVHOptiX::pack_tlas() int object_index = 0; // Unused for instanced geometry int object_visibility = 0; foreach (Object *ob, objects) { - if (ob->geometry == geom) { + if (ob->get_geometry() == geom) { object_visibility |= ob->visibility_for_tracing(); if (!geom->is_instanced()) { object_index = ob->get_device_index(); @@ -216,8 +219,7 @@ void BVHOptiX::pack_nodes(const BVHNode *) void BVHOptiX::refit_nodes() { - // TODO(pmours): Implement? - VLOG(1) << "Refit is not yet implemented for OptiX BVH."; + do_refit = true; } BVHNode *BVHOptiX::widen_children_nodes(const BVHNode *) diff --git a/intern/cycles/bvh/bvh_optix.h b/intern/cycles/bvh/bvh_optix.h index e4745b093b5..663cba67260 100644 --- a/intern/cycles/bvh/bvh_optix.h +++ b/intern/cycles/bvh/bvh_optix.h @@ -33,6 +33,10 @@ class BVHOptiX : public BVH { friend class BVH; public: + uint64_t optix_handle; + uint64_t optix_data_handle; + bool do_refit; + BVHOptiX(const BVHParams ¶ms, const vector<Geometry *> &geometry, const vector<Object *> &objects); diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 2f1960d664e..834b07440d8 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -392,8 +392,8 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair, Hair::Curve curve = hair->get_curve(prim_index); const int k0 = curve.first_key + segment_index; const int k1 = k0 + 1; - float3 v0 = hair->curve_keys[k0]; - float3 v1 = hair->curve_keys[k1]; + float3 v0 = hair->get_curve_keys()[k0]; + float3 v1 = hair->get_curve_keys()[k1]; if (tfm != NULL) { v0 = transform_point(tfm, v0); @@ -456,21 +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) { - Geometry *geom = object->geometry; + Geometry *geom = object->get_geometry(); - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { 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); + split_triangle_primitive( + mesh, &object->get_tfm(), tri_idx, dim, pos, left_bounds, right_bounds); } } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { 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); + hair, &object->get_tfm(), curve_idx, segment_idx, dim, pos, left_bounds, right_bounds); } } } @@ -491,11 +492,11 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder, const Object *ob = builder.objects[ref.prim_object()]; if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { - Mesh *mesh = static_cast<Mesh *>(ob->geometry); + Mesh *mesh = static_cast<Mesh *>(ob->get_geometry()); split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds); } else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) { - Hair *hair = static_cast<Hair *>(ob->geometry); + Hair *hair = static_cast<Hair *>(ob->get_geometry()); split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds); } else { diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp index c969b361643..38e55307848 100644 --- a/intern/cycles/bvh/bvh_unaligned.cpp +++ b/intern/cycles/bvh/bvh_unaligned.cpp @@ -72,10 +72,10 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) { const int curve_index = ref.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); - const Hair *hair = static_cast<const Hair *>(object->geometry); + const Hair *hair = static_cast<const Hair *>(object->get_geometry()); const Hair::Curve &curve = hair->get_curve(curve_index); const int key = curve.first_key + segment; - const float3 v1 = hair->curve_keys[key], v2 = hair->curve_keys[key + 1]; + const float3 v1 = hair->get_curve_keys()[key], v2 = hair->get_curve_keys()[key + 1]; float length; const float3 axis = normalize_len(v2 - v1, &length); if (length > 1e-6f) { @@ -98,10 +98,10 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim, if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) { const int curve_index = prim.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); - const Hair *hair = static_cast<const Hair *>(object->geometry); + const Hair *hair = static_cast<const Hair *>(object->get_geometry()); const Hair::Curve &curve = hair->get_curve(curve_index); curve.bounds_grow( - segment, &hair->curve_keys[0], &hair->curve_radius[0], aligned_space, bounds); + segment, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], aligned_space, bounds); } else { bounds = prim.bounds().transformed(&aligned_space); diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index cc54f64b1bb..928249931a3 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC device_cpu.cpp device_cuda.cpp device_denoising.cpp + device_dummy.cpp device_memory.cpp device_multi.cpp device_opencl.cpp diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 407f73e8451..eb8fb8040e3 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -375,7 +375,7 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool } #endif - Device *device; + Device *device = NULL; switch (info.type) { case DEVICE_CPU: @@ -385,16 +385,12 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool case DEVICE_CUDA: if (device_cuda_init()) device = device_cuda_create(info, stats, profiler, background); - else - device = NULL; break; #endif #ifdef WITH_OPTIX case DEVICE_OPTIX: if (device_optix_init()) device = device_optix_create(info, stats, profiler, background); - else - device = NULL; break; #endif #ifdef WITH_NETWORK @@ -406,12 +402,14 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool case DEVICE_OPENCL: if (device_opencl_init()) device = device_opencl_create(info, stats, profiler, background); - else - device = NULL; break; #endif default: - return NULL; + break; + } + + if (device == NULL) { + device = device_dummy_create(info, stats, profiler, background); } return device; @@ -549,6 +547,14 @@ vector<DeviceInfo> Device::available_devices(uint mask) return devices; } +DeviceInfo Device::dummy_device(const string &error_msg) +{ + DeviceInfo info; + info.type = DEVICE_DUMMY; + info.error_msg = error_msg; + return info; +} + string Device::device_capabilities(uint mask) { thread_scoped_lock lock(device_mutex); diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index ddf608aa430..2006db02ce7 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -48,6 +48,7 @@ enum DeviceType { DEVICE_NETWORK, DEVICE_MULTI, DEVICE_OPTIX, + DEVICE_DUMMY, }; enum DeviceTypeMask { @@ -87,6 +88,7 @@ class DeviceInfo { int cpu_threads; vector<DeviceInfo> multi_devices; vector<DeviceInfo> denoising_devices; + string error_msg; DeviceInfo() { @@ -471,6 +473,7 @@ class Device { static string string_from_type(DeviceType type); static vector<DeviceType> available_types(); static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL); + static DeviceInfo dummy_device(const string &error_msg = ""); static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL); static DeviceInfo get_multi_device(const vector<DeviceInfo> &subdevices, int threads, diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 23aedcd0c48..6912ac1e638 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -932,6 +932,11 @@ class CPUDevice : public Device { break; } + if (tile.stealing_state == RenderTile::CAN_BE_STOLEN && task.get_tile_stolen()) { + tile.stealing_state = RenderTile::WAS_STOLEN; + break; + } + if (tile.task == RenderTile::PATH_TRACE) { for (int y = tile.y; y < tile.y + tile.h; y++) { for (int x = tile.x; x < tile.x + tile.w; x++) { diff --git a/intern/cycles/device/device_dummy.cpp b/intern/cycles/device/device_dummy.cpp new file mode 100644 index 00000000000..5112fc152e5 --- /dev/null +++ b/intern/cycles/device/device_dummy.cpp @@ -0,0 +1,83 @@ +/* + * 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 "device/device.h" +#include "device/device_intern.h" + +CCL_NAMESPACE_BEGIN + +/* Dummy device for when creating an appropriate rendering device fails. */ + +class DummyDevice : public Device { + public: + DummyDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_) + : Device(info_, stats_, profiler_, background_) + { + error_msg = info.error_msg; + } + + ~DummyDevice() + { + } + + virtual BVHLayoutMask get_bvh_layout_mask() const override + { + return 0; + } + + virtual void mem_alloc(device_memory &) override + { + } + + virtual void mem_copy_to(device_memory &) override + { + } + + virtual void mem_copy_from(device_memory &, int, int, int, int) override + { + } + + virtual void mem_zero(device_memory &) override + { + } + + virtual void mem_free(device_memory &) override + { + } + + virtual void const_copy_to(const char *, void *, size_t) override + { + } + + virtual void task_add(DeviceTask &) override + { + } + + virtual void task_wait() override + { + } + + virtual void task_cancel() override + { + } +}; + +Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background) +{ + return new DummyDevice(info, stats, profiler, background); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index 94d63e8f333..ecc79c5d7ee 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -35,6 +35,7 @@ bool device_cuda_init(); Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); bool device_optix_init(); Device *device_optix_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); +Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); Device *device_network_create(DeviceInfo &info, Stats &stats, diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 32654e62a6f..00b2aa864aa 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -450,6 +450,14 @@ template<typename T> class device_vector : public device_memory { device_zero(); } + void move_device(Device *new_device) + { + copy_from_device(); + device_free(); + device = new_device; + copy_to_device(); + } + protected: size_t size(size_t width, size_t height, size_t depth) { diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index 43b1fb30baf..95234845f98 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -18,6 +18,7 @@ #ifdef WITH_OPTIX # include "bvh/bvh.h" +# include "bvh/bvh_optix.h" # include "device/cuda/device_cuda.h" # include "device/device_denoising.h" # include "device/device_intern.h" @@ -137,9 +138,6 @@ class OptiXDevice : public CUDADevice { PG_HITD_MOTION, PG_HITS_MOTION, # endif -# ifdef WITH_CYCLES_DEBUG - PG_EXCP, -# endif PG_BAKE, // kernel_bake_evaluate PG_DISP, // kernel_displace_evaluate PG_BACK, // kernel_background_evaluate @@ -232,6 +230,9 @@ class OptiXDevice : public CUDADevice { } }; # endif +# if OPTIX_ABI_VERSION >= 41 && defined(WITH_CYCLES_DEBUG) + options.validationMode = OPTIX_DEVICE_CONTEXT_VALIDATION_MODE_ALL; +# endif check_result_optix(optixDeviceContextCreate(cuContext, &options, &context)); # ifdef WITH_CYCLES_LOGGING check_result_optix(optixDeviceContextSetLogCallback( @@ -368,6 +369,12 @@ class OptiXDevice : public CUDADevice { module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_3; module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO; # endif + +# if OPTIX_ABI_VERSION >= 41 + module_options.boundValues = nullptr; + module_options.numBoundValues = 0; +# endif + OptixPipelineCompileOptions pipeline_options; // Default to no motion blur and two-level graph, since it is the fastest option pipeline_options.usesMotionBlur = false; @@ -375,12 +382,7 @@ class OptiXDevice : public CUDADevice { OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING; pipeline_options.numPayloadValues = 6; pipeline_options.numAttributeValues = 2; // u, v -# ifdef WITH_CYCLES_DEBUG - pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_STACK_OVERFLOW | - OPTIX_EXCEPTION_FLAG_TRACE_DEPTH; -# else pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE; -# endif pipeline_options.pipelineLaunchParamsVariableName = "__params"; // See kernel_globals.h # if OPTIX_ABI_VERSION >= 36 @@ -505,12 +507,6 @@ class OptiXDevice : public CUDADevice { group_descs[PG_HITL].hitgroup.entryFunctionNameAH = "__anyhit__kernel_optix_local_hit"; } -# ifdef WITH_CYCLES_DEBUG - group_descs[PG_EXCP].kind = OPTIX_PROGRAM_GROUP_KIND_EXCEPTION; - group_descs[PG_EXCP].exception.module = optix_module; - group_descs[PG_EXCP].exception.entryFunctionName = "__exception__kernel_optix_exception"; -# endif - if (requested_features.use_baking) { group_descs[PG_BAKE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN; group_descs[PG_BAKE].raygen.module = optix_module; @@ -578,9 +574,6 @@ class OptiXDevice : public CUDADevice { groups[PG_HITD_MOTION], groups[PG_HITS_MOTION], # endif -# ifdef WITH_CYCLES_DEBUG - groups[PG_EXCP], -# endif }; check_result_optix_ret( optixPipelineCreate(context, @@ -618,9 +611,6 @@ class OptiXDevice : public CUDADevice { groups[PG_HITD_MOTION], groups[PG_HITS_MOTION], # endif -# ifdef WITH_CYCLES_DEBUG - groups[PG_EXCP], -# endif }; check_result_optix_ret( optixPipelineCreate(context, @@ -734,9 +724,6 @@ class OptiXDevice : public CUDADevice { OptixShaderBindingTable sbt_params = {}; sbt_params.raygenRecord = sbt_data.device_pointer + PG_RGEN * sizeof(SbtRecord); -# ifdef WITH_CYCLES_DEBUG - sbt_params.exceptionRecord = sbt_data.device_pointer + PG_EXCP * sizeof(SbtRecord); -# endif sbt_params.missRecordBase = sbt_data.device_pointer + PG_MISS * sizeof(SbtRecord); sbt_params.missRecordStrideInBytes = sizeof(SbtRecord); sbt_params.missRecordCount = 1; @@ -1064,9 +1051,6 @@ class OptiXDevice : public CUDADevice { OptixShaderBindingTable sbt_params = {}; sbt_params.raygenRecord = sbt_data.device_pointer + rgen_index * sizeof(SbtRecord); -# ifdef WITH_CYCLES_DEBUG - sbt_params.exceptionRecord = sbt_data.device_pointer + PG_EXCP * sizeof(SbtRecord); -# endif sbt_params.missRecordBase = sbt_data.device_pointer + PG_MISS * sizeof(SbtRecord); sbt_params.missRecordStrideInBytes = sizeof(SbtRecord); sbt_params.missRecordCount = 1; @@ -1095,23 +1079,23 @@ class OptiXDevice : public CUDADevice { bool build_optix_bvh(const OptixBuildInput &build_input, uint16_t num_motion_steps, - OptixTraversableHandle &out_handle) + OptixTraversableHandle &out_handle, + CUdeviceptr &out_data, + OptixBuildOperation operation) { - out_handle = 0; - const CUDAContextScope scope(cuContext); // Compute memory usage OptixAccelBufferSizes sizes = {}; OptixAccelBuildOptions options; - options.operation = OPTIX_BUILD_OPERATION_BUILD; + options.operation = operation; if (background) { // Prefer best performance and lowest memory consumption in background options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION; } else { // Prefer fast updates in viewport - options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD; + options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE; } options.motionOptions.numKeys = num_motion_steps; @@ -1136,8 +1120,10 @@ class OptiXDevice : public CUDADevice { move_textures_to_host(size - free, false); } - CUdeviceptr out_data = 0; - check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes)); + if (operation == OPTIX_BUILD_OPERATION_BUILD) { + check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes)); + } + as_mem.push_back(out_data); // Finally build the acceleration structure @@ -1204,23 +1190,49 @@ class OptiXDevice : public CUDADevice { unordered_map<Geometry *, OptixTraversableHandle> geometry; geometry.reserve(bvh->geometry.size()); - // Free all previous acceleration structures + // Free all previous acceleration structures which can not be refit + std::set<CUdeviceptr> refit_mem; + + for (Geometry *geom : bvh->geometry) { + if (static_cast<BVHOptiX *>(geom->bvh)->do_refit) { + refit_mem.insert(static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle); + } + } + for (CUdeviceptr mem : as_mem) { - cuMemFree(mem); + if (refit_mem.find(mem) == refit_mem.end()) { + cuMemFree(mem); + } } + as_mem.clear(); // Build bottom level acceleration structures (BLAS) // Note: Always keep this logic in sync with bvh_optix.cpp! for (Object *ob : bvh->objects) { // Skip geometry for which acceleration structure already exists - Geometry *geom = ob->geometry; + Geometry *geom = ob->get_geometry(); if (geometry.find(geom) != geometry.end()) continue; - if (geom->type == Geometry::HAIR) { + OptixTraversableHandle handle; + OptixBuildOperation operation; + CUdeviceptr out_data; + // Refit is only possible in viewport for now. + if (static_cast<BVHOptiX *>(geom->bvh)->do_refit && !background) { + out_data = static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle; + handle = static_cast<BVHOptiX *>(geom->bvh)->optix_handle; + operation = OPTIX_BUILD_OPERATION_UPDATE; + } + else { + out_data = 0; + handle = 0; + operation = OPTIX_BUILD_OPERATION_BUILD; + } + + if (geom->geometry_type == Geometry::HAIR) { // Build BLAS for curve primitives - Hair *const hair = static_cast<Hair *const>(ob->geometry); + Hair *const hair = static_cast<Hair *const>(ob->get_geometry()); if (hair->num_curves() == 0) { continue; } @@ -1229,8 +1241,8 @@ class OptiXDevice : public CUDADevice { size_t num_motion_steps = 1; 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; + if (motion_blur && hair->get_use_motion_blur() && motion_keys) { + num_motion_steps = hair->get_motion_steps(); } device_vector<OptixAabb> aabb_data(this, "temp_aabb_data", MEM_READ_ONLY); @@ -1250,16 +1262,19 @@ class OptiXDevice : public CUDADevice { // 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 = hair->curve_keys.data(); + const float3 *keys = hair->get_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 * hair->curve_keys.size(); + keys = motion_keys->data_float3() + attr_offset * hair->get_curve_keys().size(); } for (size_t j = 0, i = 0; j < hair->num_curves(); ++j) { const Hair::Curve curve = hair->get_curve(j); +# if OPTIX_ABI_VERSION >= 36 + const array<float> &curve_radius = hair->get_curve_radius(); +# endif for (int segment = 0; segment < curve.num_segments(); ++segment, ++i) { # if OPTIX_ABI_VERSION >= 36 @@ -1272,10 +1287,8 @@ class OptiXDevice : public CUDADevice { const float4 px = make_float4(keys[ka].x, keys[k0].x, keys[k1].x, keys[kb].x); const float4 py = make_float4(keys[ka].y, keys[k0].y, keys[k1].y, keys[kb].y); const float4 pz = make_float4(keys[ka].z, keys[k0].z, keys[k1].z, keys[kb].z); - const float4 pw = make_float4(hair->curve_radius[ka], - hair->curve_radius[k0], - hair->curve_radius[k1], - hair->curve_radius[kb]); + const float4 pw = make_float4( + curve_radius[ka], curve_radius[k0], curve_radius[k1], curve_radius[kb]); // Convert Catmull-Rom data to Bezier spline static const float4 cr2bsp0 = make_float4(+7, -4, +5, -2) / 6.f; @@ -1298,7 +1311,7 @@ class OptiXDevice : public CUDADevice { # endif { BoundBox bounds = BoundBox::empty; - curve.bounds_grow(segment, keys, hair->curve_radius.data(), bounds); + curve.bounds_grow(segment, keys, hair->get_curve_radius().data(), bounds); const size_t index = step * num_segments + i; aabb_data[index].minX = bounds.min.x; @@ -1381,37 +1394,41 @@ class OptiXDevice : public CUDADevice { } // Allocate memory for new BLAS and build it - OptixTraversableHandle handle; - if (build_optix_bvh(build_input, num_motion_steps, handle)) { - geometry.insert({ob->geometry, handle}); + if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) { + geometry.insert({ob->get_geometry(), handle}); + static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data; + static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle; + static_cast<BVHOptiX *>(geom->bvh)->do_refit = false; } else { return false; } } - else if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { // Build BLAS for triangle primitives - Mesh *const mesh = static_cast<Mesh *const>(ob->geometry); + Mesh *const mesh = static_cast<Mesh *const>(ob->get_geometry()); if (mesh->num_triangles() == 0) { continue; } - const size_t num_verts = mesh->verts.size(); + const size_t num_verts = mesh->get_verts().size(); size_t num_motion_steps = 1; Attribute *motion_keys = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (motion_blur && mesh->use_motion_blur && motion_keys) { - num_motion_steps = mesh->motion_steps; + if (motion_blur && mesh->get_use_motion_blur() && motion_keys) { + num_motion_steps = mesh->get_motion_steps(); } device_vector<int> index_data(this, "temp_index_data", MEM_READ_ONLY); - index_data.alloc(mesh->triangles.size()); - memcpy(index_data.data(), mesh->triangles.data(), mesh->triangles.size() * sizeof(int)); + index_data.alloc(mesh->get_triangles().size()); + memcpy(index_data.data(), + mesh->get_triangles().data(), + mesh->get_triangles().size() * sizeof(int)); device_vector<float3> vertex_data(this, "temp_vertex_data", MEM_READ_ONLY); vertex_data.alloc(num_verts * num_motion_steps); for (size_t step = 0; step < num_motion_steps; ++step) { - const float3 *verts = mesh->verts.data(); + const float3 *verts = mesh->get_verts().data(); size_t center_step = (num_motion_steps - 1) / 2; // The center step for motion vertices is not stored in the attribute @@ -1453,9 +1470,11 @@ class OptiXDevice : public CUDADevice { build_input.triangleArray.primitiveIndexOffset = mesh->optix_prim_offset; // Allocate memory for new BLAS and build it - OptixTraversableHandle handle; - if (build_optix_bvh(build_input, num_motion_steps, handle)) { - geometry.insert({ob->geometry, handle}); + if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) { + geometry.insert({ob->get_geometry(), handle}); + static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data; + static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle; + static_cast<BVHOptiX *>(geom->bvh)->do_refit = false; } else { return false; @@ -1464,8 +1483,10 @@ class OptiXDevice : public CUDADevice { } // Fill instance descriptions +# if OPTIX_ABI_VERSION < 41 device_vector<OptixAabb> aabbs(this, "tlas_aabbs", MEM_READ_ONLY); aabbs.alloc(bvh->objects.size()); +# endif device_vector<OptixInstance> instances(this, "tlas_instances", MEM_READ_ONLY); instances.alloc(bvh->objects.size()); @@ -1475,12 +1496,13 @@ class OptiXDevice : public CUDADevice { continue; // Create separate instance for triangle/curve meshes of an object - auto handle_it = geometry.find(ob->geometry); + const auto handle_it = geometry.find(ob->get_geometry()); if (handle_it == geometry.end()) { continue; } OptixTraversableHandle handle = handle_it->second; +# if OPTIX_ABI_VERSION < 41 OptixAabb &aabb = aabbs[num_instances]; aabb.minX = ob->bounds.min.x; aabb.minY = ob->bounds.min.y; @@ -1488,6 +1510,7 @@ class OptiXDevice : public CUDADevice { aabb.maxX = ob->bounds.max.x; aabb.maxY = ob->bounds.max.y; aabb.maxZ = ob->bounds.max.z; +# endif OptixInstance &instance = instances[num_instances++]; memset(&instance, 0, sizeof(instance)); @@ -1503,18 +1526,19 @@ class OptiXDevice : public CUDADevice { // Have to have at least one bit in the mask, or else instance would always be culled instance.visibilityMask = 1; - if (ob->geometry->has_volume) { + if (ob->get_geometry()->has_volume) { // Volumes have a special bit set in the visibility mask so a trace can mask only volumes instance.visibilityMask |= 2; } - if (ob->geometry->type == Geometry::HAIR) { + if (ob->get_geometry()->geometry_type == Geometry::HAIR) { // Same applies to curves (so they can be skipped in local trace calls) instance.visibilityMask |= 4; # if OPTIX_ABI_VERSION >= 36 - if (motion_blur && ob->geometry->has_motion_blur() && DebugFlags().optix.curves_api && - static_cast<const Hair *>(ob->geometry)->curve_shape == CURVE_THICK) { + if (motion_blur && ob->get_geometry()->has_motion_blur() && + DebugFlags().optix.curves_api && + static_cast<const Hair *>(ob->get_geometry())->curve_shape == CURVE_THICK) { // Select between motion blur and non-motion blur built-in intersection module instance.sbtOffset = PG_HITD_MOTION - PG_HITD; } @@ -1523,7 +1547,7 @@ class OptiXDevice : public CUDADevice { // 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_keys = max(ob->get_motion().size(), 2) - 2; size_t motion_transform_size = sizeof(OptixSRTMotionTransform) + motion_keys * sizeof(OptixSRTData); @@ -1537,16 +1561,17 @@ class OptiXDevice : public CUDADevice { 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.numKeys = ob->get_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()); + array<DecomposedTransform> decomp(ob->get_motion().size()); + transform_motion_decompose( + decomp.data(), ob->get_motion().data(), ob->get_motion().size()); - for (size_t i = 0; i < ob->motion.size(); ++i) { + for (size_t i = 0; i < ob->get_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 @@ -1593,9 +1618,9 @@ class OptiXDevice : public CUDADevice { else { instance.traversableHandle = handle; - if (ob->geometry->is_instanced()) { + if (ob->get_geometry()->is_instanced()) { // Set transform matrix - memcpy(instance.transform, &ob->tfm, sizeof(instance.transform)); + memcpy(instance.transform, &ob->get_tfm(), sizeof(instance.transform)); } else { // Disable instance transform if geometry already has it applied to vertex data @@ -1608,20 +1633,26 @@ class OptiXDevice : public CUDADevice { } // Upload instance descriptions +# if OPTIX_ABI_VERSION < 41 aabbs.resize(num_instances); aabbs.copy_to_device(); +# endif instances.resize(num_instances); instances.copy_to_device(); // Build top-level acceleration structure (TLAS) OptixBuildInput build_input = {}; build_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; - build_input.instanceArray.instances = instances.device_pointer; - build_input.instanceArray.numInstances = num_instances; +# if OPTIX_ABI_VERSION < 41 // Instance AABBs no longer need to be set since OptiX 7.2 build_input.instanceArray.aabbs = aabbs.device_pointer; build_input.instanceArray.numAabbs = num_instances; +# endif + build_input.instanceArray.instances = instances.device_pointer; + build_input.instanceArray.numInstances = num_instances; - return build_optix_bvh(build_input, 0, tlas_handle); + CUdeviceptr out_data = 0; + tlas_handle = 0; + return build_optix_bvh(build_input, 0, tlas_handle, out_data, OPTIX_BUILD_OPERATION_BUILD); } void const_copy_to(const char *name, void *host, size_t size) override @@ -1725,8 +1756,8 @@ bool device_optix_init() const OptixResult result = optixInit(); if (result == OPTIX_ERROR_UNSUPPORTED_ABI_VERSION) { - VLOG(1) << "OptiX initialization failed because driver does not support ABI version " - << OPTIX_ABI_VERSION; + VLOG(1) << "OptiX initialization failed because the installed NVIDIA driver is too old. " + "Please update to the latest driver first!"; return false; } else if (result != OPTIX_SUCCESS) { diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index fd380788282..f819f84eb43 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -159,6 +159,7 @@ class DeviceTask { function<void(RenderTile &)> update_tile_sample; function<void(RenderTile &)> release_tile; function<bool()> get_cancel; + function<bool()> get_tile_stolen; function<void(RenderTileNeighbors &, Device *)> map_neighbor_tiles; function<void(RenderTileNeighbors &, Device *)> unmap_neighbor_tiles; diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp index f239040ee3d..c926f6ab8ef 100644 --- a/intern/cycles/graph/node.cpp +++ b/intern/cycles/graph/node.cpp @@ -35,7 +35,7 @@ Node::Node(const NodeType *type_, ustring name_) : name(name_), type(type_) assert(type); owner = nullptr; - socket_modified = ~0; + tag_modified(); /* assign non-empty name, convenient for debugging */ if (name.empty()) { @@ -52,11 +52,6 @@ Node::~Node() { } -template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket) -{ - return (T &)*(((char *)node) + socket.struct_offset); -} - #ifndef NDEBUG static bool is_socket_float3(const SocketType &socket) { @@ -387,6 +382,87 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT } } +void Node::set_value(const SocketType &socket, const Node &other, const SocketType &other_socket) +{ + assert(socket.type == other_socket.type); + (void)other_socket; + + if (socket.is_array()) { + switch (socket.type) { + case SocketType::BOOLEAN_ARRAY: + set(socket, get_socket_value<array<bool>>(&other, socket)); + break; + case SocketType::FLOAT_ARRAY: + set(socket, get_socket_value<array<float>>(&other, socket)); + break; + case SocketType::INT_ARRAY: + set(socket, get_socket_value<array<int>>(&other, socket)); + break; + case SocketType::COLOR_ARRAY: + case SocketType::VECTOR_ARRAY: + case SocketType::POINT_ARRAY: + case SocketType::NORMAL_ARRAY: + set(socket, get_socket_value<array<float3>>(&other, socket)); + break; + case SocketType::POINT2_ARRAY: + set(socket, get_socket_value<array<float2>>(&other, socket)); + break; + case SocketType::STRING_ARRAY: + set(socket, get_socket_value<array<ustring>>(&other, socket)); + break; + case SocketType::TRANSFORM_ARRAY: + set(socket, get_socket_value<array<Transform>>(&other, socket)); + break; + case SocketType::NODE_ARRAY: + set(socket, get_socket_value<array<Node *>>(&other, socket)); + break; + default: + assert(0); + break; + } + } + else { + switch (socket.type) { + case SocketType::BOOLEAN: + set(socket, get_socket_value<bool>(&other, socket)); + break; + case SocketType::FLOAT: + set(socket, get_socket_value<float>(&other, socket)); + break; + case SocketType::INT: + set(socket, get_socket_value<int>(&other, socket)); + break; + case SocketType::UINT: + set(socket, get_socket_value<uint>(&other, socket)); + break; + case SocketType::COLOR: + case SocketType::VECTOR: + case SocketType::POINT: + case SocketType::NORMAL: + set(socket, get_socket_value<float3>(&other, socket)); + break; + case SocketType::POINT2: + set(socket, get_socket_value<float2>(&other, socket)); + break; + case SocketType::STRING: + set(socket, get_socket_value<ustring>(&other, socket)); + break; + case SocketType::ENUM: + set(socket, get_socket_value<int>(&other, socket)); + break; + case SocketType::TRANSFORM: + set(socket, get_socket_value<Transform>(&other, socket)); + break; + case SocketType::NODE: + set(socket, get_socket_value<Node *>(&other, socket)); + break; + default: + assert(0); + break; + } + } +} + template<typename T> static bool is_array_equal(const Node *node, const Node *other, const SocketType &socket) { @@ -709,7 +785,7 @@ bool Node::is_modified() void Node::tag_modified() { - socket_modified = ~0u; + socket_modified = ~0ull; } void Node::clear_modified() diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h index 16bd5e4358a..2fc9a1e0281 100644 --- a/intern/cycles/graph/node.h +++ b/intern/cycles/graph/node.h @@ -29,6 +29,66 @@ struct Node; struct NodeType; struct Transform; +/* Note: in the following macros we use "type const &" instead of "const type &" + * to avoid issues when pasting a pointer type. */ +#define NODE_SOCKET_API_BASE_METHODS(type_, name, string_name) \ + const SocketType *get_##name##_socket() const \ + { \ + static const SocketType *socket = type->find_input(ustring(string_name)); \ + return socket; \ + } \ + bool name##_is_modified() const \ + { \ + const SocketType *socket = get_##name##_socket(); \ + return socket_is_modified(*socket); \ + } \ + void tag_##name##_modified() \ + { \ + const SocketType *socket = get_##name##_socket(); \ + socket_modified |= socket->modified_flag_bit; \ + } \ + type_ const &get_##name() const \ + { \ + const SocketType *socket = get_##name##_socket(); \ + return get_socket_value<type_>(this, *socket); \ + } + +#define NODE_SOCKET_API_BASE(type_, name, string_name) \ + protected: \ + type_ name; \ +\ + public: \ + NODE_SOCKET_API_BASE_METHODS(type_, name, string_name) + +#define NODE_SOCKET_API(type_, name) \ + NODE_SOCKET_API_BASE(type_, name, #name) \ + void set_##name(type_ value) \ + { \ + const SocketType *socket = get_##name##_socket(); \ + this->set(*socket, value); \ + } + +#define NODE_SOCKET_API_ARRAY(type_, name) \ + NODE_SOCKET_API_BASE(type_, name, #name) \ + void set_##name(type_ &value) \ + { \ + const SocketType *socket = get_##name##_socket(); \ + this->set(*socket, value); \ + } \ + type_ &get_##name() \ + { \ + const SocketType *socket = get_##name##_socket(); \ + return get_socket_value<type_>(this, *socket); \ + } + +#define NODE_SOCKET_API_STRUCT_MEMBER(type_, name, member) \ + NODE_SOCKET_API_BASE_METHODS(type_, name##_##member, #name "." #member) \ + void set_##name##_##member(type_ value) \ + { \ + const SocketType *socket = get_##name##_##member##_socket(); \ + this->set(*socket, value); \ + } + /* Node */ struct NodeOwner { @@ -88,6 +148,7 @@ struct Node { void set_default_value(const SocketType &input); bool equals_value(const Node &other, const SocketType &input) const; void copy_value(const SocketType &input, const Node &other, const SocketType &other_input); + void set_value(const SocketType &input, const Node &other, const SocketType &other_input); /* equals */ bool equals(const Node &other) const; @@ -119,6 +180,11 @@ struct Node { protected: const NodeOwner *owner; + template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket) + { + return (T &)*(((char *)node) + socket.struct_offset); + } + SocketModifiedFlags socket_modified; template<typename T> void set_if_different(const SocketType &input, T value); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 26d7a7eee71..c39c67afb5a 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -649,13 +649,13 @@ include_directories(SYSTEM ${INC_SYS}) if(WITH_COMPILER_ASAN) if(CMAKE_COMPILER_IS_GNUCC AND (NOT WITH_CYCLES_KERNEL_ASAN)) # GCC hangs compiling the big kernel files with asan and release, so disable by default. - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-sanitize=all") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize=vptr") + string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -fno-sanitize=all") + string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-sanitize=vptr") elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") # With OSL, Cycles disables rtti in some modules, wich then breaks at linking # when trying to use vptr sanitizer (included into 'undefined' general option). - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-sanitize=vptr") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize=vptr") + string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -fno-sanitize=vptr") + string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-sanitize=vptr") endif() endif() diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h index e1b0e6fb81c..b37797ac21b 100644 --- a/intern/cycles/kernel/geom/geom_attribute.h +++ b/intern/cycles/kernel/geom/geom_attribute.h @@ -66,9 +66,17 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, while (attr_map.x != id) { if (UNLIKELY(attr_map.x == ATTR_STD_NONE)) { - return attribute_not_found(); + if (UNLIKELY(attr_map.y == 0)) { + return attribute_not_found(); + } + else { + /* Chain jump to a different part of the table. */ + attr_offset = attr_map.z; + } + } + else { + attr_offset += ATTR_PRIM_TYPES; } - attr_offset += ATTR_PRIM_TYPES; attr_map = kernel_tex_fetch(__attributes_map, attr_offset); } diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index 6ff0c7f2044..b5a62a31ca9 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -28,18 +28,7 @@ CCL_NAMESPACE_BEGIN ccl_device float curve_attribute_float( KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { - if (desc.element == ATTR_ELEMENT_CURVE) { -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; -# endif - - return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim); - } - else if (desc.element == ATTR_ELEMENT_CURVE_KEY || - desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { + if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { float4 curvedata = kernel_tex_fetch(__curves, sd->prim); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -56,16 +45,6 @@ ccl_device float curve_attribute_float( return (1.0f - sd->u) * f0 + sd->u * f1; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; -# endif - - return kernel_tex_fetch(__attributes_float, desc.offset); - } else { # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -74,7 +53,14 @@ ccl_device float curve_attribute_float( *dy = 0.0f; # endif - return 0.0f; + if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float, offset); + } + else { + return 0.0f; + } } } @@ -84,22 +70,7 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg, float2 *dx, float2 *dy) { - if (desc.element == ATTR_ELEMENT_CURVE) { - /* idea: we can't derive any useful differentials here, but for tiled - * mipmap image caching it would be useful to avoid reading the highest - * detail level always. maybe a derivative based on the hair density - * could be computed somehow? */ -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); -# endif - - return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim); - } - else if (desc.element == ATTR_ELEMENT_CURVE_KEY || - desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { + if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { float4 curvedata = kernel_tex_fetch(__curves, sd->prim); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -116,17 +87,11 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg, return (1.0f - sd->u) * f0 + sd->u * f1; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); -# endif - - return kernel_tex_fetch(__attributes_float2, desc.offset); - } else { + /* idea: we can't derive any useful differentials here, but for tiled + * mipmap image caching it would be useful to avoid reading the highest + * detail level always. maybe a derivative based on the hair density + * could be computed somehow? */ # ifdef __RAY_DIFFERENTIALS__ if (dx) *dx = make_float2(0.0f, 0.0f); @@ -134,7 +99,14 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg, *dy = make_float2(0.0f, 0.0f); # endif - return make_float2(0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float2, offset); + } + else { + return make_float2(0.0f, 0.0f); + } } } @@ -144,22 +116,7 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, float3 *dx, float3 *dy) { - if (desc.element == ATTR_ELEMENT_CURVE) { - /* idea: we can't derive any useful differentials here, but for tiled - * mipmap image caching it would be useful to avoid reading the highest - * detail level always. maybe a derivative based on the hair density - * could be computed somehow? */ -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); -# endif - - return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim)); - } - else if (desc.element == ATTR_ELEMENT_CURVE_KEY || - desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { + if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { float4 curvedata = kernel_tex_fetch(__curves, sd->prim); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -176,16 +133,6 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, return (1.0f - sd->u) * f0 + sd->u * f1; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); -# endif - - return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset)); - } else { # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -194,7 +141,14 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, *dy = make_float3(0.0f, 0.0f, 0.0f); # endif - return make_float3(0.0f, 0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : + desc.offset; + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset)); + } + else { + return make_float3(0.0f, 0.0f, 0.0f); + } } } @@ -204,22 +158,7 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg, float4 *dx, float4 *dy) { - if (desc.element == ATTR_ELEMENT_CURVE) { - /* idea: we can't derive any useful differentials here, but for tiled - * mipmap image caching it would be useful to avoid reading the highest - * detail level always. maybe a derivative based on the hair density - * could be computed somehow? */ -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); -# endif - - return kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim); - } - else if (desc.element == ATTR_ELEMENT_CURVE_KEY || - desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) { + if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { float4 curvedata = kernel_tex_fetch(__curves, sd->prim); int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -236,16 +175,6 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg, return (1.0f - sd->u) * f0 + sd->u * f1; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { -# ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); -# endif - - return kernel_tex_fetch(__attributes_float3, desc.offset); - } else { # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -254,7 +183,14 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg, *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); # endif - return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float3, offset); + } + else { + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } } } diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h index b996294c51f..9c1768f05db 100644 --- a/intern/cycles/kernel/geom/geom_patch.h +++ b/intern/cycles/kernel/geom/geom_patch.h @@ -380,6 +380,43 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg, return val; } +ccl_device float4 patch_eval_float4(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float4 *du, + float4 *dv) +{ + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (du) + *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dv) + *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + for (int i = 0; i < num_control; i++) { + float4 v = kernel_tex_fetch(__attributes_float3, offset + indices[i]); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; +} + ccl_device float4 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index 997abf438d0..2c31e5cee03 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -21,38 +21,11 @@ CCL_NAMESPACE_BEGIN -/* Generic primitive attribute reading functions */ -ccl_device_inline float primitive_attribute_float( - KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) -{ - if (sd->type & PRIMITIVE_ALL_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) - return triangle_attribute_float(kg, sd, desc, dx, dy); - else - return subd_triangle_attribute_float(kg, sd, desc, dx, dy); - } -#ifdef __HAIR__ - else if (sd->type & PRIMITIVE_ALL_CURVE) { - return curve_attribute_float(kg, sd, desc, dx, dy); - } -#endif -#ifdef __VOLUME__ - else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; - return volume_attribute_float(kg, sd, desc); - } -#endif - else { - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; - return 0.0f; - } -} +/* Surface Attributes + * + * Read geometry attributes for surface shading. This is distinct from volume + * attributes for performance, mainly for GPU performance to avoid bringing in + * heavy volume interpolation code. */ ccl_device_inline float primitive_surface_attribute_float( KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) @@ -77,25 +50,11 @@ ccl_device_inline float primitive_surface_attribute_float( } } -#ifdef __VOLUME__ -ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc) -{ - if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { - return volume_attribute_float(kg, sd, desc); - } - else { - return 0.0f; - } -} -#endif - -ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc, - float2 *dx, - float2 *dy) +ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float2 *dx, + float2 *dy) { if (sd->type & PRIMITIVE_ALL_TRIANGLE) { if (subd_triangle_patch(kg, sd) == ~0) @@ -108,16 +67,6 @@ ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg, return curve_attribute_float2(kg, sd, desc, dx, dy); } #endif -#ifdef __VOLUME__ - else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { - kernel_assert(0); - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); - return make_float2(0.0f, 0.0f); - } -#endif else { if (dx) *dx = make_float2(0.0f, 0.0f); @@ -127,11 +76,11 @@ ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg, } } -ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc, - float3 *dx, - float3 *dy) +ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float3 *dx, + float3 *dy) { if (sd->type & PRIMITIVE_ALL_TRIANGLE) { if (subd_triangle_patch(kg, sd) == ~0) @@ -144,15 +93,6 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, return curve_attribute_float3(kg, sd, desc, dx, dy); } #endif -#ifdef __VOLUME__ - else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); - return volume_attribute_float3(kg, sd, desc); - } -#endif else { if (dx) *dx = make_float3(0.0f, 0.0f, 0.0f); @@ -162,11 +102,11 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, } } -ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc, - float4 *dx, - float4 *dy) +ccl_device_inline float4 primitive_surface_attribute_float4(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float4 *dx, + float4 *dy) { if (sd->type & PRIMITIVE_ALL_TRIANGLE) { if (subd_triangle_patch(kg, sd) == ~0) @@ -188,68 +128,52 @@ ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg, } } -ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc, - float2 *dx, - float2 *dy) +#ifdef __VOLUME__ +/* Volume Attributes + * + * Read geometry attributes for volume shading. This is distinct from surface + * attributes for performance, mainly for GPU performance to avoid bringing in + * heavy volume interpolation code. */ + +ccl_device_inline bool primitive_is_volume_attribute(const ShaderData *sd, + const AttributeDescriptor desc) { - if (sd->type & PRIMITIVE_ALL_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) - return triangle_attribute_float2(kg, sd, desc, dx, dy); - else - return subd_triangle_attribute_float2(kg, sd, desc, dx, dy); - } -#ifdef __HAIR__ - else if (sd->type & PRIMITIVE_ALL_CURVE) { - return curve_attribute_float2(kg, sd, desc, dx, dy); + return (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL); +} + +ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc) +{ + if (primitive_is_volume_attribute(sd, desc)) { + return volume_attribute_value_to_float(volume_attribute_float4(kg, sd, desc)); } -#endif else { - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); - return make_float2(0.0f, 0.0f); + return 0.0f; } } -ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc, - float3 *dx, - float3 *dy) +ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc) { - if (sd->type & PRIMITIVE_ALL_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) - return triangle_attribute_float3(kg, sd, desc, dx, dy); - else - return subd_triangle_attribute_float3(kg, sd, desc, dx, dy); - } -#ifdef __HAIR__ - else if (sd->type & PRIMITIVE_ALL_CURVE) { - return curve_attribute_float3(kg, sd, desc, dx, dy); + if (primitive_is_volume_attribute(sd, desc)) { + return volume_attribute_value_to_float3(volume_attribute_float4(kg, sd, desc)); } -#endif else { - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f); } } -#ifdef __VOLUME__ -ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg, +ccl_device_inline float4 primitive_volume_attribute_float4(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc) { - if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) { - return volume_attribute_float3(kg, sd, desc); + if (primitive_is_volume_attribute(sd, desc)) { + return volume_attribute_float4(kg, sd, desc); } else { - return make_float3(0.0f, 0.0f, 0.0f); + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); } } #endif diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h index 317f3984a9a..9eceb996926 100644 --- a/intern/cycles/kernel/geom/geom_subd_triangle.h +++ b/intern/cycles/kernel/geom/geom_subd_triangle.h @@ -539,9 +539,13 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, /* p is [s, t] */ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2]; - float4 dads, dadt; - - float4 a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + float4 a, dads, dadt; + if (desc.type == NODE_ATTR_RGBA) { + a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } + else { + a = patch_eval_float4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } # ifdef __RAY_DIFFERENTIALS__ if (dx || dy) { @@ -570,25 +574,74 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, } } # endif + return a; } else #endif /* __PATCH_EVAL__ */ - if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { + if (desc.element == ATTR_ELEMENT_FACE) { + if (dx) + *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return kernel_tex_fetch(__attributes_float3, + desc.offset + subd_triangle_patch_face(kg, patch)); + } + else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { + float2 uv[3]; + subd_triangle_patch_uv(kg, sd, uv); + + uint4 v = subd_triangle_patch_indices(kg, patch); + + float4 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + v.x); + float4 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + v.y); + float4 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + v.z); + float4 f3 = kernel_tex_fetch(__attributes_float3, desc.offset + v.w); + + if (subd_triangle_patch_num_corners(kg, patch) != 4) { + f1 = (f1 + f0) * 0.5f; + f3 = (f3 + f0) * 0.5f; + } + + float4 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float4 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float4 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + +#ifdef __RAY_DIFFERENTIALS__ + if (dx) + *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c; + if (dy) + *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c; +#endif + + return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c; + } + else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); int corners[4]; subd_triangle_patch_corners(kg, patch, corners); - float4 f0 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset))); - float4 f1 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset))); - float4 f2 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset))); - float4 f3 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset))); + float4 f0, f1, f2, f3; + + if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { + f0 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset))); + f1 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset))); + f2 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset))); + f3 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset))); + } + else { + f0 = kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset); + f1 = kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset); + f2 = kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset); + f3 = kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset); + } if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -614,8 +667,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, if (dy) *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - return color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset))); + return kernel_tex_fetch(__attributes_float3, desc.offset); } else { if (dx) diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 5ecc2566815..e8e5d8c5b34 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -114,35 +114,21 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, ccl_device float triangle_attribute_float( KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy) { - if (desc.element == ATTR_ELEMENT_FACE) { - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; - - return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim); - } - else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - - float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x); - float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y); - float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z); - -#ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2; - if (dy) - *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2; -#endif - - return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; - } - else if (desc.element == ATTR_ELEMENT_CORNER) { - int tri = desc.offset + sd->prim * 3; - float f0 = kernel_tex_fetch(__attributes_float, tri + 0); - float f1 = kernel_tex_fetch(__attributes_float, tri + 1); - float f2 = kernel_tex_fetch(__attributes_float, tri + 2); + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) { + float f0, f1, f2; + + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { + const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x); + f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y); + f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z); + } + else { + const int tri = desc.offset + sd->prim * 3; + f0 = kernel_tex_fetch(__attributes_float, tri + 0); + f1 = kernel_tex_fetch(__attributes_float, tri + 1); + f2 = kernel_tex_fetch(__attributes_float, tri + 2); + } #ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -153,21 +139,22 @@ ccl_device float triangle_attribute_float( return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { - if (dx) - *dx = 0.0f; - if (dy) - *dy = 0.0f; - - return kernel_tex_fetch(__attributes_float, desc.offset); - } else { +#ifdef __RAY_DIFFERENTIALS__ if (dx) *dx = 0.0f; if (dy) *dy = 0.0f; +#endif - return 0.0f; + if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float, offset); + } + else { + return 0.0f; + } } } @@ -177,35 +164,17 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals *kg, float2 *dx, float2 *dy) { - if (desc.element == ATTR_ELEMENT_FACE) { - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); - - return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim); - } - else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - - float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x); - float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y); - float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z); - -#ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2; - if (dy) - *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2; -#endif - - return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; - } - else if (desc.element == ATTR_ELEMENT_CORNER) { - int tri = desc.offset + sd->prim * 3; + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) { float2 f0, f1, f2; - if (desc.element == ATTR_ELEMENT_CORNER) { + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { + const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x); + f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y); + f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z); + } + else { + const int tri = desc.offset + sd->prim * 3; f0 = kernel_tex_fetch(__attributes_float2, tri + 0); f1 = kernel_tex_fetch(__attributes_float2, tri + 1); f2 = kernel_tex_fetch(__attributes_float2, tri + 2); @@ -220,21 +189,22 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals *kg, return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { - if (dx) - *dx = make_float2(0.0f, 0.0f); - if (dy) - *dy = make_float2(0.0f, 0.0f); - - return kernel_tex_fetch(__attributes_float2, desc.offset); - } else { +#ifdef __RAY_DIFFERENTIALS__ if (dx) *dx = make_float2(0.0f, 0.0f); if (dy) *dy = make_float2(0.0f, 0.0f); +#endif - return make_float2(0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float2, offset); + } + else { + return make_float2(0.0f, 0.0f); + } } } @@ -244,40 +214,21 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, float3 *dx, float3 *dy) { - if (desc.element == ATTR_ELEMENT_FACE) { - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); - - return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim)); - } - else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - - float3 f0 = float4_to_float3( - kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x)); - float3 f1 = float4_to_float3( - kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y)); - float3 f2 = float4_to_float3( - kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z)); - -#ifdef __RAY_DIFFERENTIALS__ - if (dx) - *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2; - if (dy) - *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2; -#endif - - return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; - } - else if (desc.element == ATTR_ELEMENT_CORNER) { - int tri = desc.offset + sd->prim * 3; + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) { float3 f0, f1, f2; - f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); - f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); - f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { + const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z)); + } + else { + const int tri = desc.offset + sd->prim * 3; + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); + } #ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -288,21 +239,22 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { - if (dx) - *dx = make_float3(0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float3(0.0f, 0.0f, 0.0f); - - return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset)); - } else { +#ifdef __RAY_DIFFERENTIALS__ if (dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if (dy) *dy = make_float3(0.0f, 0.0f, 0.0f); +#endif - return make_float3(0.0f, 0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : + desc.offset; + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset)); + } + else { + return make_float3(0.0f, 0.0f, 0.0f); + } } } @@ -312,24 +264,32 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg, float4 *dx, float4 *dy) { - if (desc.element == ATTR_ELEMENT_CORNER_BYTE || desc.element == ATTR_ELEMENT_VERTEX) { + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER | + ATTR_ELEMENT_CORNER_BYTE)) { float4 f0, f1, f2; - if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { - int tri = desc.offset + sd->prim * 3; - f0 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0))); - f1 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1))); - f2 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2))); - } - else { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { + const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x); f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y); f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z); } + else { + const int tri = desc.offset + sd->prim * 3; + if (desc.element == ATTR_ELEMENT_CORNER) { + f0 = kernel_tex_fetch(__attributes_float3, tri + 0); + f1 = kernel_tex_fetch(__attributes_float3, tri + 1); + f2 = kernel_tex_fetch(__attributes_float3, tri + 2); + } + else { + f0 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0))); + f1 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1))); + f2 = color_srgb_to_linear_v4( + color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2))); + } + } #ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -340,22 +300,22 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg, return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; } - else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) { - if (dx) - *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - if (dy) - *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - - return color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset))); - } else { +#ifdef __RAY_DIFFERENTIALS__ if (dx) *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); if (dy) *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); +#endif - return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { + const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : + desc.offset; + return kernel_tex_fetch(__attributes_float3, offset); + } + else { + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } } } diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index f43a7841b46..13b027a5f6c 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -47,38 +47,39 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg, return P; } -ccl_device float volume_attribute_float(KernelGlobals *kg, - const ShaderData *sd, - const AttributeDescriptor desc) +ccl_device float volume_attribute_value_to_float(const float4 value) { - /* todo: optimize this so we don't have to transform both here and in - * kernel_tex_image_interp_3d when possible. Also could optimize for the - * common case where transform is translation/scale only. */ - float3 P = sd->P; - object_inverse_position_transform(kg, sd, &P); - InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC : - INTERPOLATION_NONE; - float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P, interp); - return average(float4_to_float3(r)); + return average(float4_to_float3(value)); } -ccl_device float3 volume_attribute_float3(KernelGlobals *kg, +ccl_device float volume_attribute_value_to_alpha(const float4 value) +{ + return value.w; +} + +ccl_device float3 volume_attribute_value_to_float3(const float4 value) +{ + if (value.w > 1e-6f && value.w != 1.0f) { + /* For RGBA colors, unpremultiply after interpolation. */ + return float4_to_float3(value) / value.w; + } + else { + return float4_to_float3(value); + } +} + +ccl_device float4 volume_attribute_float4(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc) { + /* todo: optimize this so we don't have to transform both here and in + * kernel_tex_image_interp_3d when possible. Also could optimize for the + * common case where transform is translation/scale only. */ float3 P = sd->P; object_inverse_position_transform(kg, sd, &P); InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC : INTERPOLATION_NONE; - float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P, interp); - - if (r.w > 1e-6f && r.w != 1.0f) { - /* For RGBA colors, unpremultiply after interpolation. */ - return float4_to_float3(r) / r.w; - } - else { - return float4_to_float3(r); - } + return kernel_tex_image_interp_3d(kg, desc.offset, P, interp); } #endif diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 4094e173da9..ea3b78b7cef 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -32,8 +32,12 @@ /* Manual definitions so we can compile without CUDA toolkit. */ +#ifdef __CUDACC_RTC__ typedef unsigned int uint32_t; typedef unsigned long long uint64_t; +#else +# include <stdint.h> +#endif typedef unsigned short half; typedef unsigned long long CUtexObject; diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index ba7ab43a47a..1848f6059b6 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -48,7 +48,7 @@ #define ccl_align(n) __attribute__((aligned(n))) #define ccl_optional_struct_init -#if __OPENCL_VERSION__ >= 200 +#if __OPENCL_VERSION__ >= 200 && !defined(__NV_CL_C_VERSION) # define ccl_loop_no_unroll __attribute__((opencl_unroll_hint(1))) #else # define ccl_loop_no_unroll diff --git a/intern/cycles/kernel/kernel_compat_optix.h b/intern/cycles/kernel/kernel_compat_optix.h index e58d8b2aa63..064c99ca100 100644 --- a/intern/cycles/kernel/kernel_compat_optix.h +++ b/intern/cycles/kernel/kernel_compat_optix.h @@ -31,8 +31,12 @@ # define ATTR_FALLTHROUGH #endif +#ifdef __CUDACC_RTC__ typedef unsigned int uint32_t; typedef unsigned long long uint64_t; +#else +# include <stdint.h> +#endif typedef unsigned short half; typedef unsigned long long CUtexObject; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 77e134da4b0..8e2b0e46a66 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -733,18 +733,18 @@ typedef enum AttributePrimitive { } AttributePrimitive; typedef enum AttributeElement { - ATTR_ELEMENT_NONE, - ATTR_ELEMENT_OBJECT, - ATTR_ELEMENT_MESH, - ATTR_ELEMENT_FACE, - ATTR_ELEMENT_VERTEX, - ATTR_ELEMENT_VERTEX_MOTION, - ATTR_ELEMENT_CORNER, - ATTR_ELEMENT_CORNER_BYTE, - ATTR_ELEMENT_CURVE, - ATTR_ELEMENT_CURVE_KEY, - ATTR_ELEMENT_CURVE_KEY_MOTION, - ATTR_ELEMENT_VOXEL + ATTR_ELEMENT_NONE = 0, + ATTR_ELEMENT_OBJECT = (1 << 0), + ATTR_ELEMENT_MESH = (1 << 1), + ATTR_ELEMENT_FACE = (1 << 2), + ATTR_ELEMENT_VERTEX = (1 << 3), + ATTR_ELEMENT_VERTEX_MOTION = (1 << 4), + ATTR_ELEMENT_CORNER = (1 << 5), + ATTR_ELEMENT_CORNER_BYTE = (1 << 6), + ATTR_ELEMENT_CURVE = (1 << 7), + ATTR_ELEMENT_CURVE_KEY = (1 << 8), + ATTR_ELEMENT_CURVE_KEY_MOTION = (1 << 9), + ATTR_ELEMENT_VOXEL = (1 << 10) } AttributeElement; typedef enum AttributeStandard { diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h index 347d0fec7f5..44c658d4cab 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h @@ -28,7 +28,6 @@ CCL_NAMESPACE_BEGIN * instruction sets. */ namespace { -template<typename T> struct TextureInterpolator { #define SET_CUBIC_SPLINE_WEIGHTS(u, t) \ { \ u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \ @@ -38,6 +37,15 @@ template<typename T> struct TextureInterpolator { } \ (void)0 +ccl_device_inline float frac(float x, int *ix) +{ + int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0); + *ix = i; + return x - (float)i; +} + +template<typename T> struct TextureInterpolator { + static ccl_always_inline float4 read(float4 r) { return r; @@ -106,13 +114,6 @@ template<typename T> struct TextureInterpolator { return clamp(x, 0, width - 1); } - static ccl_always_inline float frac(float x, int *ix) - { - int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0); - *ix = i; - return x - (float)i; - } - /* ******** 2D interpolation ******** */ static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y) @@ -370,7 +371,7 @@ template<typename T> struct TextureInterpolator { static ccl_never_inline #endif float4 - interp_3d_tricubic(const TextureInfo &info, float x, float y, float z) + interp_3d_cubic(const TextureInfo &info, float x, float y, float z) { int width = info.width; int height = info.height; @@ -469,14 +470,16 @@ template<typename T> struct TextureInterpolator { case INTERPOLATION_LINEAR: return interp_3d_linear(info, x, y, z); default: - return interp_3d_tricubic(info, x, y, z); + return interp_3d_cubic(info, x, y, z); } } -#undef SET_CUBIC_SPLINE_WEIGHTS }; #ifdef WITH_NANOVDB template<typename T> struct NanoVDBInterpolator { + + typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType; + static ccl_always_inline float4 read(float r) { return make_float4(r, r, r, 1.0f); @@ -487,30 +490,99 @@ template<typename T> struct NanoVDBInterpolator { return make_float4(r[0], r[1], r[2], 1.0f); } + static ccl_always_inline float4 interp_3d_closest(const AccessorType &acc, + float x, + float y, + float z) + { + const nanovdb::Vec3f xyz(x, y, z); + return read(nanovdb::SampleFromVoxels<AccessorType, 0, false>(acc)(xyz)); + } + + static ccl_always_inline float4 interp_3d_linear(const AccessorType &acc, + float x, + float y, + float z) + { + const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f); + return read(nanovdb::SampleFromVoxels<AccessorType, 1, false>(acc)(xyz)); + } + +# if defined(__GNUC__) || defined(__clang__) + static ccl_always_inline +# else + static ccl_never_inline +# endif + float4 + interp_3d_cubic(const AccessorType &acc, float x, float y, float z) + { + int ix, iy, iz; + int nix, niy, niz; + int pix, piy, piz; + int nnix, nniy, nniz; + /* Tricubic b-spline interpolation. */ + const float tx = frac(x - 0.5f, &ix); + const float ty = frac(y - 0.5f, &iy); + const float tz = frac(z - 0.5f, &iz); + pix = ix - 1; + piy = iy - 1; + piz = iz - 1; + nix = ix + 1; + niy = iy + 1; + niz = iz + 1; + nnix = ix + 2; + nniy = iy + 2; + nniz = iz + 2; + + const int xc[4] = {pix, ix, nix, nnix}; + const int yc[4] = {piy, iy, niy, nniy}; + const int zc[4] = {piz, iz, niz, nniz}; + float u[4], v[4], w[4]; + + /* Some helper macro to keep code reasonable size, + * let compiler to inline all the matrix multiplications. + */ +# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z])))) +# define COL_TERM(col, row) \ + (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \ + u[3] * DATA(3, col, row))) +# define ROW_TERM(row) \ + (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row))) + + SET_CUBIC_SPLINE_WEIGHTS(u, tx); + SET_CUBIC_SPLINE_WEIGHTS(v, ty); + SET_CUBIC_SPLINE_WEIGHTS(w, tz); + + /* Actual interpolation. */ + return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3); + +# undef COL_TERM +# undef ROW_TERM +# undef DATA + } + static ccl_always_inline float4 interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp) { - nanovdb::NanoGrid<T> *const grid = (nanovdb::NanoGrid<T> *)info.data; - const nanovdb::NanoRoot<T> &root = grid->tree().root(); + using namespace nanovdb; - const nanovdb::Coord off(root.bbox().min()); - const nanovdb::Coord dim(root.bbox().dim()); - const nanovdb::Vec3f xyz(off[0] + x * dim[0], off[1] + y * dim[1], off[2] + z * dim[2]); + NanoGrid<T> *const grid = (NanoGrid<T> *)info.data; + AccessorType acc = grid->getAccessor(); - typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT; switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) { - default: - case INTERPOLATION_LINEAR: - return read(nanovdb::SampleFromVoxels<ReadAccessorT, 1, false>(root)(xyz)); case INTERPOLATION_CLOSEST: - return read(nanovdb::SampleFromVoxels<ReadAccessorT, 0, false>(root)(xyz)); - case INTERPOLATION_CUBIC: - return read(nanovdb::SampleFromVoxels<ReadAccessorT, 3, false>(root)(xyz)); + return interp_3d_closest(acc, x, y, z); + case INTERPOLATION_LINEAR: + return interp_3d_linear(acc, x, y, z); + default: + return interp_3d_cubic(acc, x, y, z); } } }; #endif +#undef SET_CUBIC_SPLINE_WEIGHTS + ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y) { const TextureInfo &info = kernel_tex_fetch(__texture_info, id); diff --git a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h index 5a005a3f65b..001bc652810 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h +++ b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h @@ -24,17 +24,14 @@ ccl_device float cubic_w0(float a) { return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); } - ccl_device float cubic_w1(float a) { return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); } - ccl_device float cubic_w2(float a) { return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); } - ccl_device float cubic_w3(float a) { return (1.0f / 6.0f) * (a * a * a); @@ -45,7 +42,6 @@ ccl_device float cubic_g0(float a) { return cubic_w0(a) + cubic_w1(a); } - ccl_device float cubic_g1(float a) { return cubic_w2(a) + cubic_w3(a); @@ -54,13 +50,11 @@ ccl_device float cubic_g1(float a) /* h0 and h1 are the two offset functions */ ccl_device float cubic_h0(float a) { - /* Note +0.5 offset to compensate for CUDA linear filtering convention. */ - return -1.0f + cubic_w1(a) / (cubic_w0(a) + cubic_w1(a)) + 0.5f; + return (cubic_w1(a) / cubic_g0(a)) - 1.0f; } - ccl_device float cubic_h1(float a) { - return 1.0f + cubic_w3(a) / (cubic_w2(a) + cubic_w3(a)) + 0.5f; + return (cubic_w3(a) / cubic_g1(a)) + 1.0f; } /* Fast bicubic texture lookup using 4 bilinear lookups, adapted from CUDA samples. */ @@ -79,10 +73,11 @@ ccl_device T kernel_tex_image_interp_bicubic(const TextureInfo &info, float x, f float g0x = cubic_g0(fx); float g1x = cubic_g1(fx); - float x0 = (px + cubic_h0(fx)) / info.width; - float x1 = (px + cubic_h1(fx)) / info.width; - float y0 = (py + cubic_h0(fy)) / info.height; - float y1 = (py + cubic_h1(fy)) / info.height; + /* Note +0.5 offset to compensate for CUDA linear filtering convention. */ + float x0 = (px + cubic_h0(fx) + 0.5f) / info.width; + float x1 = (px + cubic_h1(fx) + 0.5f) / info.width; + float y0 = (py + cubic_h0(fy) + 0.5f) / info.height; + float y1 = (py + cubic_h1(fy) + 0.5f) / info.height; return cubic_g0(fy) * (g0x * tex2D<T>(tex, x0, y0) + g1x * tex2D<T>(tex, x1, y0)) + cubic_g1(fy) * (g0x * tex2D<T>(tex, x0, y1) + g1x * tex2D<T>(tex, x1, y1)); @@ -90,7 +85,7 @@ ccl_device T kernel_tex_image_interp_bicubic(const TextureInfo &info, float x, f /* Fast tricubic texture lookup using 8 trilinear lookups. */ template<typename T> -ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x, float y, float z) +ccl_device T kernel_tex_image_interp_tricubic(const TextureInfo &info, float x, float y, float z) { CUtexObject tex = (CUtexObject)info.data; @@ -112,12 +107,13 @@ ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x float g0z = cubic_g0(fz); float g1z = cubic_g1(fz); - float x0 = (px + cubic_h0(fx)) / info.width; - float x1 = (px + cubic_h1(fx)) / info.width; - float y0 = (py + cubic_h0(fy)) / info.height; - float y1 = (py + cubic_h1(fy)) / info.height; - float z0 = (pz + cubic_h0(fz)) / info.depth; - float z1 = (pz + cubic_h1(fz)) / info.depth; + /* Note +0.5 offset to compensate for CUDA linear filtering convention. */ + float x0 = (px + cubic_h0(fx) + 0.5f) / info.width; + float x1 = (px + cubic_h1(fx) + 0.5f) / info.width; + float y0 = (py + cubic_h0(fy) + 0.5f) / info.height; + float y1 = (py + cubic_h1(fy) + 0.5f) / info.height; + float z0 = (pz + cubic_h0(fz) + 0.5f) / info.depth; + float z1 = (pz + cubic_h1(fz) + 0.5f) / info.depth; return g0z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z0) + g1x * tex3D<T>(tex, x1, y0, z0)) + g1y * (g0x * tex3D<T>(tex, x0, y1, z0) + g1x * tex3D<T>(tex, x1, y1, z0))) + @@ -126,26 +122,56 @@ ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x } #ifdef WITH_NANOVDB +template<typename T, typename S> +ccl_device T kernel_tex_image_interp_tricubic_nanovdb(S &s, float x, float y, float z) +{ + float px = floor(x); + float py = floor(y); + float pz = floor(z); + float fx = x - px; + float fy = y - py; + float fz = z - pz; + + float g0x = cubic_g0(fx); + float g1x = cubic_g1(fx); + float g0y = cubic_g0(fy); + float g1y = cubic_g1(fy); + float g0z = cubic_g0(fz); + float g1z = cubic_g1(fz); + + float x0 = px + cubic_h0(fx); + float x1 = px + cubic_h1(fx); + float y0 = py + cubic_h0(fy); + float y1 = py + cubic_h1(fy); + float z0 = pz + cubic_h0(fz); + float z1 = pz + cubic_h1(fz); + + using namespace nanovdb; + + return g0z * (g0y * (g0x * s(Vec3f(x0, y0, z0)) + g1x * s(Vec3f(x1, y0, z0))) + + g1y * (g0x * s(Vec3f(x0, y1, z0)) + g1x * s(Vec3f(x1, y1, z0)))) + + g1z * (g0y * (g0x * s(Vec3f(x0, y0, z1)) + g1x * s(Vec3f(x1, y0, z1))) + + g1y * (g0x * s(Vec3f(x0, y1, z1)) + g1x * s(Vec3f(x1, y1, z1)))); +} + template<typename T> ccl_device_inline T kernel_tex_image_interp_nanovdb( const TextureInfo &info, float x, float y, float z, uint interpolation) { - nanovdb::NanoGrid<T> *const grid = (nanovdb::NanoGrid<T> *)info.data; - const nanovdb::NanoRoot<T> &root = grid->tree().root(); + using namespace nanovdb; - const nanovdb::Coord off(root.bbox().min()); - const nanovdb::Coord dim(root.bbox().dim()); - const nanovdb::Vec3f xyz(off[0] + x * dim[0], off[1] + y * dim[1], off[2] + z * dim[2]); + NanoGrid<T> *const grid = (NanoGrid<T> *)info.data; + typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType; + AccessorType acc = grid->getAccessor(); - typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT; switch (interpolation) { - default: - case INTERPOLATION_LINEAR: - return nanovdb::SampleFromVoxels<ReadAccessorT, 1, false>(root)(xyz); case INTERPOLATION_CLOSEST: - return nanovdb::SampleFromVoxels<ReadAccessorT, 0, false>(root)(xyz); - case INTERPOLATION_CUBIC: - return nanovdb::SampleFromVoxels<ReadAccessorT, 3, false>(root)(xyz); + return SampleFromVoxels<AccessorType, 0, false>(acc)(Vec3f(x, y, z)); + case INTERPOLATION_LINEAR: + return SampleFromVoxels<AccessorType, 1, false>(acc)(Vec3f(x - 0.5f, y - 0.5f, z - 0.5f)); + default: + SampleFromVoxels<AccessorType, 1, false> s(acc); + return kernel_tex_image_interp_tricubic_nanovdb<T>(s, x - 0.5f, y - 0.5f, z - 0.5f); } } #endif @@ -214,7 +240,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) { if (interpolation == INTERPOLATION_CUBIC) { - return kernel_tex_image_interp_bicubic_3d<float4>(info, x, y, z); + return kernel_tex_image_interp_tricubic<float4>(info, x, y, z); } else { CUtexObject tex = (CUtexObject)info.data; @@ -225,7 +251,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, float f; if (interpolation == INTERPOLATION_CUBIC) { - f = kernel_tex_image_interp_bicubic_3d<float>(info, x, y, z); + f = kernel_tex_image_interp_tricubic<float>(info, x, y, z); } else { CUtexObject tex = (CUtexObject)info.data; diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h index 2f44f249c5f..f39998299ef 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h +++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h @@ -16,7 +16,6 @@ #ifdef WITH_NANOVDB # include "nanovdb/CNanoVDB.h" -# include "nanovdb/util/CSampleFromVoxels.h" #endif /* For OpenCL we do manual lookup and interpolation. */ @@ -47,95 +46,128 @@ ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width) return clamp(x, 0, width - 1); } -ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg, - const ccl_global TextureInfo *info, - int id, - int offset) +ccl_device_inline float4 svm_image_texture_read( + KernelGlobals *kg, const ccl_global TextureInfo *info, void *acc, int x, int y, int z) { + const int data_offset = x + info->width * y + info->width * info->height * z; const int texture_type = info->data_type; /* Float4 */ if (texture_type == IMAGE_DATA_TYPE_FLOAT4) { - return tex_fetch(float4, info, offset); + return tex_fetch(float4, info, data_offset); } /* Byte4 */ else if (texture_type == IMAGE_DATA_TYPE_BYTE4) { - uchar4 r = tex_fetch(uchar4, info, offset); + uchar4 r = tex_fetch(uchar4, info, data_offset); float f = 1.0f / 255.0f; return make_float4(r.x * f, r.y * f, r.z * f, r.w * f); } /* Ushort4 */ else if (texture_type == IMAGE_DATA_TYPE_USHORT4) { - ushort4 r = tex_fetch(ushort4, info, offset); + ushort4 r = tex_fetch(ushort4, info, data_offset); float f = 1.0f / 65535.f; return make_float4(r.x * f, r.y * f, r.z * f, r.w * f); } /* Float */ else if (texture_type == IMAGE_DATA_TYPE_FLOAT) { - float f = tex_fetch(float, info, offset); + float f = tex_fetch(float, info, data_offset); return make_float4(f, f, f, 1.0f); } /* UShort */ else if (texture_type == IMAGE_DATA_TYPE_USHORT) { - ushort r = tex_fetch(ushort, info, offset); + ushort r = tex_fetch(ushort, info, data_offset); float f = r * (1.0f / 65535.0f); return make_float4(f, f, f, 1.0f); } - /* Byte */ +#ifdef WITH_NANOVDB + /* NanoVDB Float */ + else if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) { + cnanovdb_coord coord; + coord.mVec[0] = x; + coord.mVec[1] = y; + coord.mVec[2] = z; + float f = cnanovdb_readaccessor_getValueF((cnanovdb_readaccessor *)acc, &coord); + return make_float4(f, f, f, 1.0f); + } + /* NanoVDB Float3 */ + else if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) { + cnanovdb_coord coord; + coord.mVec[0] = x; + coord.mVec[1] = y; + coord.mVec[2] = z; + cnanovdb_Vec3F f = cnanovdb_readaccessor_getValueF3((cnanovdb_readaccessor *)acc, &coord); + return make_float4(f.mVec[0], f.mVec[1], f.mVec[2], 1.0f); + } +#endif #ifdef __KERNEL_CL_KHR_FP16__ - /* half and half4 are optional in OpenCL */ + /* Half and Half4 are optional in OpenCL */ else if (texture_type == IMAGE_DATA_TYPE_HALF) { - float f = tex_fetch(half, info, offset); + float f = tex_fetch(half, info, data_offset); return make_float4(f, f, f, 1.0f); } else if (texture_type == IMAGE_DATA_TYPE_HALF4) { - half4 r = tex_fetch(half4, info, offset); + half4 r = tex_fetch(half4, info, data_offset); return make_float4(r.x, r.y, r.z, r.w); } #endif + /* Byte */ else { - uchar r = tex_fetch(uchar, info, offset); + uchar r = tex_fetch(uchar, info, data_offset); float f = r * (1.0f / 255.0f); return make_float4(f, f, f, 1.0f); } } -ccl_device_inline float4 svm_image_texture_read_2d(KernelGlobals *kg, int id, int x, int y) +ccl_device_inline float4 +svm_image_texture_read_2d(KernelGlobals *kg, int id, void *acc, int x, int y) { const ccl_global TextureInfo *info = kernel_tex_info(kg, id); - /* Wrap */ - if (info->extension == EXTENSION_REPEAT) { - x = svm_image_texture_wrap_periodic(x, info->width); - y = svm_image_texture_wrap_periodic(y, info->height); - } - else { - x = svm_image_texture_wrap_clamp(x, info->width); - y = svm_image_texture_wrap_clamp(y, info->height); +#ifdef WITH_NANOVDB + if (info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT && + info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) { +#endif + /* Wrap */ + if (info->extension == EXTENSION_REPEAT) { + x = svm_image_texture_wrap_periodic(x, info->width); + y = svm_image_texture_wrap_periodic(y, info->height); + } + else { + x = svm_image_texture_wrap_clamp(x, info->width); + y = svm_image_texture_wrap_clamp(y, info->height); + } +#ifdef WITH_NANOVDB } +#endif - int offset = x + info->width * y; - return svm_image_texture_read(kg, info, id, offset); + return svm_image_texture_read(kg, info, acc, x, y, 0); } -ccl_device_inline float4 svm_image_texture_read_3d(KernelGlobals *kg, int id, int x, int y, int z) +ccl_device_inline float4 +svm_image_texture_read_3d(KernelGlobals *kg, int id, void *acc, int x, int y, int z) { const ccl_global TextureInfo *info = kernel_tex_info(kg, id); - /* Wrap */ - if (info->extension == EXTENSION_REPEAT) { - x = svm_image_texture_wrap_periodic(x, info->width); - y = svm_image_texture_wrap_periodic(y, info->height); - z = svm_image_texture_wrap_periodic(z, info->depth); - } - else { - x = svm_image_texture_wrap_clamp(x, info->width); - y = svm_image_texture_wrap_clamp(y, info->height); - z = svm_image_texture_wrap_clamp(z, info->depth); +#ifdef WITH_NANOVDB + if (info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT && + info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) { +#endif + /* Wrap */ + if (info->extension == EXTENSION_REPEAT) { + x = svm_image_texture_wrap_periodic(x, info->width); + y = svm_image_texture_wrap_periodic(y, info->height); + z = svm_image_texture_wrap_periodic(z, info->depth); + } + else { + x = svm_image_texture_wrap_clamp(x, info->width); + y = svm_image_texture_wrap_clamp(y, info->height); + z = svm_image_texture_wrap_clamp(z, info->depth); + } +#ifdef WITH_NANOVDB } +#endif - int offset = x + info->width * y + info->width * info->height * z; - return svm_image_texture_read(kg, info, id, offset); + return svm_image_texture_read(kg, info, acc, x, y, z); } ccl_device_inline float svm_image_texture_frac(float x, int *ix) @@ -170,7 +202,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl svm_image_texture_frac(x * info->width, &ix); svm_image_texture_frac(y * info->height, &iy); - return svm_image_texture_read_2d(kg, id, ix, iy); + return svm_image_texture_read_2d(kg, id, NULL, ix, iy); } else if (info->interpolation == INTERPOLATION_LINEAR) { /* Bilinear interpolation. */ @@ -179,10 +211,10 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy); float4 r; - r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy); - r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy); - r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy + 1); - r += ty * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy + 1); + r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, NULL, ix, iy); + r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, NULL, ix + 1, iy); + r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, NULL, ix, iy + 1); + r += ty * tx * svm_image_texture_read_2d(kg, id, NULL, ix + 1, iy + 1); return r; } else { @@ -200,7 +232,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { float weight = u[x] * v[y]; - r += weight * svm_image_texture_read_2d(kg, id, ix + x - 1, iy + y - 1); + r += weight * svm_image_texture_read_2d(kg, id, NULL, ix + x - 1, iy + y - 1); } } return r; @@ -216,113 +248,68 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float3 P P = transform_point(&tfm, P); } - const float x = P.x; - const float y = P.y; - const float z = P.z; - - if (info->extension == EXTENSION_CLIP) { - if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) { - return make_float4(0.0f, 0.0f, 0.0f, 0.0f); - } - } + float x = P.x; + float y = P.y; + float z = P.z; uint interpolation = (interp == INTERPOLATION_NONE) ? info->interpolation : interp; #ifdef WITH_NANOVDB - if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) { + cnanovdb_readaccessor acc; + if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT || + info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) { ccl_global cnanovdb_griddata *grid = (ccl_global cnanovdb_griddata *)(kg->buffers[info->cl_buffer] + info->data); - const ccl_global cnanovdb_rootdataF *root = cnanovdb_treedata_rootF( - cnanovdb_griddata_tree(grid)); - - cnanovdb_Vec3F xyz; - xyz.mVec[0] = root->mBBox_min.mVec[0] + - x * (root->mBBox_max.mVec[0] - root->mBBox_min.mVec[0]); - xyz.mVec[1] = root->mBBox_min.mVec[1] + - y * (root->mBBox_max.mVec[1] - root->mBBox_min.mVec[1]); - xyz.mVec[2] = root->mBBox_min.mVec[2] + - z * (root->mBBox_max.mVec[2] - root->mBBox_min.mVec[2]); - - cnanovdb_readaccessor acc; - cnanovdb_readaccessor_init(&acc, root); - - float value; - switch (interpolation) { - default: - case INTERPOLATION_LINEAR: - value = cnanovdb_sampleF_trilinear(&acc, &xyz); - break; - case INTERPOLATION_CLOSEST: - value = cnanovdb_sampleF_nearest(&acc, &xyz); - break; - } - return make_float4(value, value, value, 1.0f); + cnanovdb_readaccessor_init(&acc, cnanovdb_treedata_rootF(cnanovdb_griddata_tree(grid))); } - if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) { - ccl_global cnanovdb_griddata *grid = - (ccl_global cnanovdb_griddata *)(kg->buffers[info->cl_buffer] + info->data); - const ccl_global cnanovdb_rootdataF3 *root = cnanovdb_treedata_rootF3( - cnanovdb_griddata_tree(grid)); - - cnanovdb_Vec3F xyz; - xyz.mVec[0] = root->mBBox_min.mVec[0] + - x * (root->mBBox_max.mVec[0] - root->mBBox_min.mVec[0]); - xyz.mVec[1] = root->mBBox_min.mVec[1] + - y * (root->mBBox_max.mVec[1] - root->mBBox_min.mVec[1]); - xyz.mVec[2] = root->mBBox_min.mVec[2] + - z * (root->mBBox_max.mVec[2] - root->mBBox_min.mVec[2]); - - cnanovdb_readaccessor acc; - cnanovdb_readaccessor_init(&acc, root); - - cnanovdb_Vec3F value; - switch (interpolation) { - default: - case INTERPOLATION_LINEAR: - value = cnanovdb_sampleF3_trilinear(&acc, &xyz); - break; - case INTERPOLATION_CLOSEST: - value = cnanovdb_sampleF3_nearest(&acc, &xyz); - break; + else { + if (info->extension == EXTENSION_CLIP) { + if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) { + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } } - return make_float4(value.mVec[0], value.mVec[1], value.mVec[2], 1.0f); + + x *= info->width; + y *= info->height; + z *= info->depth; } #endif if (interpolation == INTERPOLATION_CLOSEST) { /* Closest interpolation. */ int ix, iy, iz; - svm_image_texture_frac(x * info->width, &ix); - svm_image_texture_frac(y * info->height, &iy); - svm_image_texture_frac(z * info->depth, &iz); + svm_image_texture_frac(x, &ix); + svm_image_texture_frac(y, &iy); + svm_image_texture_frac(z, &iz); - return svm_image_texture_read_3d(kg, id, ix, iy, iz); + return svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz); } else if (interpolation == INTERPOLATION_LINEAR) { - /* Bilinear interpolation. */ + /* Trilinear interpolation. */ int ix, iy, iz; - float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix); - float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy); - float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz); + float tx = svm_image_texture_frac(x - 0.5f, &ix); + float ty = svm_image_texture_frac(y - 0.5f, &iy); + float tz = svm_image_texture_frac(z - 0.5f, &iz); float4 r; - r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz); - r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz); - r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz); - r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz); - - r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz + 1); - r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz + 1); - r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz + 1); - r += tz * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz + 1); + r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * + svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz); + r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy, iz); + r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy + 1, iz); + r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy + 1, iz); + + r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz + 1); + r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy, iz + 1); + r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy + 1, iz + 1); + r += tz * ty * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy + 1, iz + 1); return r; } else { - /* Bicubic interpolation. */ + /* Tricubic interpolation. */ int ix, iy, iz; - float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix); - float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy); - float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz); + float tx = svm_image_texture_frac(x - 0.5f, &ix); + float ty = svm_image_texture_frac(y - 0.5f, &iy); + float tz = svm_image_texture_frac(z - 0.5f, &iz); float u[4], v[4], w[4]; SET_CUBIC_SPLINE_WEIGHTS(u, tx); @@ -335,7 +322,8 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float3 P for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { float weight = u[x] * v[y] * w[z]; - r += weight * svm_image_texture_read_3d(kg, id, ix + x - 1, iy + y - 1, iz + z - 1); + r += weight * + svm_image_texture_read_3d(kg, id, &acc, ix + x - 1, iy + y - 1, iz + z - 1); } } } diff --git a/intern/cycles/kernel/kernels/optix/kernel_optix.cu b/intern/cycles/kernel/kernels/optix/kernel_optix.cu index 3b166e59dfd..fd9065098dd 100644 --- a/intern/cycles/kernel/kernels/optix/kernel_optix.cu +++ b/intern/cycles/kernel/kernels/optix/kernel_optix.cu @@ -320,10 +320,3 @@ extern "C" __global__ void __intersection__curve_all() optix_intersection_curve(prim, type); } #endif - -#ifdef __KERNEL_DEBUG__ -extern "C" __global__ void __exception__kernel_optix_exception() -{ - printf("Unhandled exception occured: code %d!\n", optixGetExceptionCode()); -} -#endif diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 8144d480589..3b2d639f3a5 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -47,7 +47,7 @@ set(LIB ) # OSL and LLVM are built without RTTI -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}") +string(APPEND CMAKE_CXX_FLAGS " ${RTTI_DISABLE_FLAGS}") if(APPLE) # Disable allocation warning on macOS prior to 10.14: the OSLRenderServices @@ -55,7 +55,7 @@ if(APPLE) # unordered_map_concurrent). This is not something what the SDK supportsm, but # since we take care of allocations ourselves is is OK to ignore the # diagnostic message. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-allocation") + string(APPEND CMAKE_CXX_FLAGS " -faligned-allocation") endif() include_directories(${INC}) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index aee1e3a244e..2a4a1dfe325 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -403,8 +403,28 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { + float *fval = (float *)val; + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = 0.0f; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1].x; + fval[5] = f[1].y; + fval[6] = 0.0f; + fval[7] = 0.0f; + + fval[8] = f[2].x; + fval[9] = f[2].y; + fval[10] = 0.0f; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; fval[0] = f[0].x; @@ -438,10 +458,41 @@ static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, v return false; } +static bool set_attribute_float2(float2 f, TypeDesc type, bool derivatives, void *val) +{ + float2 fv[3]; + + fv[0] = f; + fv[1] = make_float2(0.0f, 0.0f); + fv[2] = make_float2(0.0f, 0.0f); + + return set_attribute_float2(fv, type, derivatives, val); +} + static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { + float *fval = (float *)val; + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1].x; + fval[5] = f[1].y; + fval[6] = f[1].z; + fval[7] = 0.0f; + + fval[8] = f[2].x; + fval[9] = f[2].y; + fval[10] = f[2].z; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; fval[0] = f[0].x; @@ -545,14 +596,45 @@ static bool set_attribute_float4(float4 f[3], TypeDesc type, bool derivatives, v return false; } +static bool set_attribute_float4(float4 f, TypeDesc type, bool derivatives, void *val) +{ + float4 fv[3]; + + fv[0] = f; + fv[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + fv[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return set_attribute_float4(fv, type, derivatives, val); +} + static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { float *fval = (float *)val; fval[0] = f[0]; - fval[1] = f[1]; - fval[2] = f[2]; + fval[1] = f[0]; + fval[2] = f[0]; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1]; + fval[5] = f[1]; + fval[6] = f[1]; + fval[7] = 0.0f; + + fval[8] = f[2]; + fval[9] = f[2]; + fval[10] = f[2]; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + float *fval = (float *)val; + fval[0] = f[0]; + fval[1] = f[0]; + fval[2] = f[0]; if (derivatives) { fval[3] = f[1]; @@ -675,26 +757,50 @@ static bool get_primitive_attribute(KernelGlobals *kg, if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { float3 fval[3]; - fval[0] = primitive_attribute_float3( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + if (primitive_is_volume_attribute(sd, attr.desc)) { + fval[0] = primitive_volume_attribute_float3(kg, sd, attr.desc); + } + else { + memset(fval, 0, sizeof(fval)); + fval[0] = primitive_surface_attribute_float3( + kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + } return set_attribute_float3(fval, type, derivatives, val); } else if (attr.type == TypeFloat2) { - float2 fval[3]; - fval[0] = primitive_attribute_float2( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - return set_attribute_float2(fval, type, derivatives, val); + if (primitive_is_volume_attribute(sd, attr.desc)) { + assert(!"Float2 attribute not support for volumes"); + return false; + } + else { + float2 fval[3]; + fval[0] = primitive_surface_attribute_float2( + kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + return set_attribute_float2(fval, type, derivatives, val); + } } else if (attr.type == TypeDesc::TypeFloat) { float fval[3]; - fval[0] = primitive_attribute_float( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + if (primitive_is_volume_attribute(sd, attr.desc)) { + memset(fval, 0, sizeof(fval)); + fval[0] = primitive_volume_attribute_float(kg, sd, attr.desc); + } + else { + fval[0] = primitive_surface_attribute_float( + kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + } return set_attribute_float(fval, type, derivatives, val); } - else if (attr.type == TypeRGBA) { + else if (attr.type == TypeDesc::TypeFloat4 || attr.type == TypeRGBA) { float4 fval[3]; - fval[0] = primitive_attribute_float4( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + if (primitive_is_volume_attribute(sd, attr.desc)) { + memset(fval, 0, sizeof(fval)); + fval[0] = primitive_volume_attribute_float4(kg, sd, attr.desc); + } + else { + fval[0] = primitive_surface_attribute_float4( + kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + } return set_attribute_float4(fval, type, derivatives, val); } else { @@ -718,13 +824,37 @@ static bool get_mesh_attribute(KernelGlobals *kg, } } -static void get_object_attribute(const OSLGlobals::Attribute &attr, bool derivatives, void *val) +static bool get_object_attribute(const OSLGlobals::Attribute &attr, + TypeDesc type, + bool derivatives, + void *val) { - size_t datasize = attr.value.datasize(); + if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { + return set_attribute_float3(*(float3 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeFloat2) { + return set_attribute_float2(*(float2 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeDesc::TypeFloat) { + return set_attribute_float(*(float *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeRGBA || attr.type == TypeDesc::TypeFloat4) { + return set_attribute_float4(*(float4 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == type) { + size_t datasize = attr.value.datasize(); + + memcpy(val, attr.value.data(), datasize); + if (derivatives) { + memset((char *)val + datasize, 0, datasize * 2); + } - memcpy(val, attr.value.data(), datasize); - if (derivatives) - memset((char *)val + datasize, 0, datasize * 2); + return true; + } + else { + return false; + } } bool OSLRenderServices::get_object_standard_attribute( @@ -987,8 +1117,7 @@ bool OSLRenderServices::get_attribute( } else { /* object attribute */ - get_object_attribute(attr, derivatives, val); - return true; + return get_object_attribute(attr, type, derivatives, val); } } else { diff --git a/intern/cycles/kernel/shaders/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl index abec8ebfbf0..205d0a21bed 100644 --- a/intern/cycles/kernel/shaders/node_attribute.osl +++ b/intern/cycles/kernel/shaders/node_attribute.osl @@ -20,20 +20,26 @@ shader node_attribute(string bump_offset = "center", string name = "", output point Vector = point(0.0, 0.0, 0.0), output color Color = 0.0, - output float Fac = 0.0) + output float Fac = 0.0, + output float Alpha = 0.0) { - getattribute(name, Color); + float data[4]; + getattribute(name, data); + Color = color(data[0], data[1], data[2]); Vector = point(Color); getattribute(name, Fac); + Alpha = data[3]; if (bump_offset == "dx") { Color += Dx(Color); Vector += Dx(Vector); Fac += Dx(Fac); + Alpha += Dx(Alpha); } else if (bump_offset == "dy") { Color += Dy(Color); Vector += Dy(Vector); Fac += Dy(Fac); + Alpha += Dy(Alpha); } } diff --git a/intern/cycles/kernel/shaders/node_clamp.osl b/intern/cycles/kernel/shaders/node_clamp.osl index ce9392a0d98..b600fb7c455 100644 --- a/intern/cycles/kernel/shaders/node_clamp.osl +++ b/intern/cycles/kernel/shaders/node_clamp.osl @@ -16,11 +16,12 @@ #include "stdcycles.h" -shader node_clamp(string type = "minmax", +shader node_clamp(string clamp_type = "minmax", float Value = 1.0, float Min = 0.0, float Max = 1.0, output float Result = 0.0) { - Result = (type == "range" && (Min > Max)) ? clamp(Value, Max, Min) : clamp(Value, Min, Max); + Result = (clamp_type == "range" && (Min > Max)) ? clamp(Value, Max, Min) : + clamp(Value, Min, Max); } diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl index e9acebc0572..c7faee0d022 100644 --- a/intern/cycles/kernel/shaders/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -62,7 +62,7 @@ float gradient(point p, string type) shader node_gradient_texture( int use_mapping = 0, matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - string type = "linear", + string gradient_type = "linear", point Vector = P, output float Fac = 0.0, output color Color = 0.0) @@ -72,6 +72,6 @@ shader node_gradient_texture( if (use_mapping) p = transform(mapping, p); - Fac = gradient(p, type); + Fac = gradient(p, gradient_type); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/node_map_range.osl b/intern/cycles/kernel/shaders/node_map_range.osl index 1c49027e6dd..2fcc664a80e 100644 --- a/intern/cycles/kernel/shaders/node_map_range.osl +++ b/intern/cycles/kernel/shaders/node_map_range.osl @@ -27,7 +27,7 @@ float smootherstep(float edge0, float edge1, float x) return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); } -shader node_map_range(string type = "linear", +shader node_map_range(string range_type = "linear", float Value = 1.0, float FromMin = 0.0, float FromMax = 1.0, @@ -38,15 +38,15 @@ shader node_map_range(string type = "linear", { if (FromMax != FromMin) { float Factor = Value; - if (type == "stepped") { + if (range_type == "stepped") { Factor = (Value - FromMin) / (FromMax - FromMin); Factor = (Steps > 0) ? floor(Factor * (Steps + 1.0)) / Steps : 0.0; } - else if (type == "smoothstep") { + else if (range_type == "smoothstep") { Factor = (FromMin > FromMax) ? 1.0 - smoothstep(FromMax, FromMin, Value) : smoothstep(FromMin, FromMax, Value); } - else if (type == "smootherstep") { + else if (range_type == "smootherstep") { Factor = (FromMin > FromMax) ? 1.0 - smootherstep(FromMax, FromMin, Value) : smootherstep(FromMin, FromMax, Value); } diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl index 8d204999630..131640685bc 100644 --- a/intern/cycles/kernel/shaders/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -47,24 +47,24 @@ matrix euler_to_mat(point euler) return mat; } -shader node_mapping(string type = "point", +shader node_mapping(string mapping_type = "point", point VectorIn = point(0.0, 0.0, 0.0), point Location = point(0.0, 0.0, 0.0), point Rotation = point(0.0, 0.0, 0.0), point Scale = point(1.0, 1.0, 1.0), output point VectorOut = point(0.0, 0.0, 0.0)) { - if (type == "point") { + if (mapping_type == "point") { VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale)) + Location; } - else if (type == "texture") { + else if (mapping_type == "texture") { VectorOut = safe_divide(transform(transpose(euler_to_mat(Rotation)), (VectorIn - Location)), Scale); } - else if (type == "vector") { + else if (mapping_type == "vector") { VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale)); } - else if (type == "normal") { + else if (mapping_type == "normal") { VectorOut = normalize((vector)transform(euler_to_mat(Rotation), safe_divide(VectorIn, Scale))); } else { diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl index dbaa7ccb60e..66884610561 100644 --- a/intern/cycles/kernel/shaders/node_math.osl +++ b/intern/cycles/kernel/shaders/node_math.osl @@ -18,91 +18,91 @@ #include "stdcycles.h" /* OSL asin, acos, and pow functions are safe by default. */ -shader node_math(string type = "add", +shader node_math(string math_type = "add", float Value1 = 0.5, float Value2 = 0.5, float Value3 = 0.5, output float Value = 0.0) { - if (type == "add") + if (math_type == "add") Value = Value1 + Value2; - else if (type == "subtract") + else if (math_type == "subtract") Value = Value1 - Value2; - else if (type == "multiply") + else if (math_type == "multiply") Value = Value1 * Value2; - else if (type == "divide") + else if (math_type == "divide") Value = safe_divide(Value1, Value2); - else if (type == "power") + else if (math_type == "power") Value = pow(Value1, Value2); - else if (type == "logarithm") + else if (math_type == "logarithm") Value = safe_log(Value1, Value2); - else if (type == "sqrt") + else if (math_type == "sqrt") Value = safe_sqrt(Value1); - else if (type == "inversesqrt") + else if (math_type == "inversesqrt") Value = inversesqrt(Value1); - else if (type == "absolute") + else if (math_type == "absolute") Value = fabs(Value1); - else if (type == "radians") + else if (math_type == "radians") Value = radians(Value1); - else if (type == "degrees") + else if (math_type == "degrees") Value = degrees(Value1); - else if (type == "minimum") + else if (math_type == "minimum") Value = min(Value1, Value2); - else if (type == "maximum") + else if (math_type == "maximum") Value = max(Value1, Value2); - else if (type == "less_than") + else if (math_type == "less_than") Value = Value1 < Value2; - else if (type == "greater_than") + else if (math_type == "greater_than") Value = Value1 > Value2; - else if (type == "round") + else if (math_type == "round") Value = floor(Value1 + 0.5); - else if (type == "floor") + else if (math_type == "floor") Value = floor(Value1); - else if (type == "ceil") + else if (math_type == "ceil") Value = ceil(Value1); - else if (type == "fraction") + else if (math_type == "fraction") Value = Value1 - floor(Value1); - else if (type == "modulo") + else if (math_type == "modulo") Value = safe_modulo(Value1, Value2); - else if (type == "trunc") + else if (math_type == "trunc") Value = trunc(Value1); - else if (type == "snap") + else if (math_type == "snap") Value = floor(safe_divide(Value1, Value2)) * Value2; - else if (type == "wrap") + else if (math_type == "wrap") Value = wrap(Value1, Value2, Value3); - else if (type == "pingpong") + else if (math_type == "pingpong") Value = pingpong(Value1, Value2); - else if (type == "sine") + else if (math_type == "sine") Value = sin(Value1); - else if (type == "cosine") + else if (math_type == "cosine") Value = cos(Value1); - else if (type == "tangent") + else if (math_type == "tangent") Value = tan(Value1); - else if (type == "sinh") + else if (math_type == "sinh") Value = sinh(Value1); - else if (type == "cosh") + else if (math_type == "cosh") Value = cosh(Value1); - else if (type == "tanh") + else if (math_type == "tanh") Value = tanh(Value1); - else if (type == "arcsine") + else if (math_type == "arcsine") Value = asin(Value1); - else if (type == "arccosine") + else if (math_type == "arccosine") Value = acos(Value1); - else if (type == "arctangent") + else if (math_type == "arctangent") Value = atan(Value1); - else if (type == "arctan2") + else if (math_type == "arctan2") Value = atan2(Value1, Value2); - else if (type == "sign") + else if (math_type == "sign") Value = sign(Value1); - else if (type == "exponent") + else if (math_type == "exponent") Value = exp(Value1); - else if (type == "compare") + else if (math_type == "compare") Value = ((Value1 == Value2) || (abs(Value1 - Value2) <= max(Value3, 1e-5))) ? 1.0 : 0.0; - else if (type == "multiply_add") + else if (math_type == "multiply_add") Value = Value1 * Value2 + Value3; - else if (type == "smoothmin") + else if (math_type == "smoothmin") Value = smoothmin(Value1, Value2, Value3); - else if (type == "smoothmax") + else if (math_type == "smoothmax") Value = -(smoothmin(-Value1, -Value2, Value3)); else warning("%s", "Unknown math operator!"); diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl index a13b4bb7b96..dcd9f014f3e 100644 --- a/intern/cycles/kernel/shaders/node_mix.osl +++ b/intern/cycles/kernel/shaders/node_mix.osl @@ -279,7 +279,7 @@ color node_mix_clamp(color col) return outcol; } -shader node_mix(string type = "mix", +shader node_mix(string mix_type = "mix", int use_clamp = 0, float Fac = 0.5, color Color1 = 0.0, @@ -288,41 +288,41 @@ shader node_mix(string type = "mix", { float t = clamp(Fac, 0.0, 1.0); - if (type == "mix") + if (mix_type == "mix") Color = node_mix_blend(t, Color1, Color2); - if (type == "add") + if (mix_type == "add") Color = node_mix_add(t, Color1, Color2); - if (type == "multiply") + if (mix_type == "multiply") Color = node_mix_mul(t, Color1, Color2); - if (type == "screen") + if (mix_type == "screen") Color = node_mix_screen(t, Color1, Color2); - if (type == "overlay") + if (mix_type == "overlay") Color = node_mix_overlay(t, Color1, Color2); - if (type == "subtract") + if (mix_type == "subtract") Color = node_mix_sub(t, Color1, Color2); - if (type == "divide") + if (mix_type == "divide") Color = node_mix_div(t, Color1, Color2); - if (type == "difference") + if (mix_type == "difference") Color = node_mix_diff(t, Color1, Color2); - if (type == "darken") + if (mix_type == "darken") Color = node_mix_dark(t, Color1, Color2); - if (type == "lighten") + if (mix_type == "lighten") Color = node_mix_light(t, Color1, Color2); - if (type == "dodge") + if (mix_type == "dodge") Color = node_mix_dodge(t, Color1, Color2); - if (type == "burn") + if (mix_type == "burn") Color = node_mix_burn(t, Color1, Color2); - if (type == "hue") + if (mix_type == "hue") Color = node_mix_hue(t, Color1, Color2); - if (type == "saturation") + if (mix_type == "saturation") Color = node_mix_sat(t, Color1, Color2); - if (type == "value") + if (mix_type == "value") Color = node_mix_val(t, Color1, Color2); - if (type == "color") + if (mix_type == "color") Color = node_mix_color(t, Color1, Color2); - if (type == "soft_light") + if (mix_type == "soft_light") Color = node_mix_soft(t, Color1, Color2); - if (type == "linear_light") + if (mix_type == "linear_light") Color = node_mix_linear(t, Color1, Color2); if (use_clamp) diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index d03b84c1ab4..0e71ce74c29 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -684,7 +684,7 @@ float noise_musgrave_ridged_multi_fractal_4d( shader node_musgrave_texture( int use_mapping = 0, matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - string type = "fBM", + string musgrave_type = "fBM", string dimensions = "3D", point Vector = P, float W = 0.0, @@ -707,21 +707,21 @@ shader node_musgrave_texture( if (dimensions == "1D") { float p = W * Scale; - if (type == "multifractal") { + if (musgrave_type == "multifractal") { Fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, octaves); } - else if (type == "fBM") { + else if (musgrave_type == "fBM") { Fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, octaves); } - else if (type == "hybrid_multifractal") { + else if (musgrave_type == "hybrid_multifractal") { Fac = noise_musgrave_hybrid_multi_fractal_1d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "ridged_multifractal") { + else if (musgrave_type == "ridged_multifractal") { Fac = noise_musgrave_ridged_multi_fractal_1d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "hetero_terrain") { + else if (musgrave_type == "hetero_terrain") { Fac = noise_musgrave_hetero_terrain_1d(p, dimension, lacunarity, octaves, Offset); } else { @@ -730,21 +730,21 @@ shader node_musgrave_texture( } else if (dimensions == "2D") { vector2 p = vector2(s[0], s[1]) * Scale; - if (type == "multifractal") { + if (musgrave_type == "multifractal") { Fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, octaves); } - else if (type == "fBM") { + else if (musgrave_type == "fBM") { Fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, octaves); } - else if (type == "hybrid_multifractal") { + else if (musgrave_type == "hybrid_multifractal") { Fac = noise_musgrave_hybrid_multi_fractal_2d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "ridged_multifractal") { + else if (musgrave_type == "ridged_multifractal") { Fac = noise_musgrave_ridged_multi_fractal_2d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "hetero_terrain") { + else if (musgrave_type == "hetero_terrain") { Fac = noise_musgrave_hetero_terrain_2d(p, dimension, lacunarity, octaves, Offset); } else { @@ -753,21 +753,21 @@ shader node_musgrave_texture( } else if (dimensions == "3D") { vector3 p = s * Scale; - if (type == "multifractal") { + if (musgrave_type == "multifractal") { Fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, octaves); } - else if (type == "fBM") { + else if (musgrave_type == "fBM") { Fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, octaves); } - else if (type == "hybrid_multifractal") { + else if (musgrave_type == "hybrid_multifractal") { Fac = noise_musgrave_hybrid_multi_fractal_3d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "ridged_multifractal") { + else if (musgrave_type == "ridged_multifractal") { Fac = noise_musgrave_ridged_multi_fractal_3d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "hetero_terrain") { + else if (musgrave_type == "hetero_terrain") { Fac = noise_musgrave_hetero_terrain_3d(p, dimension, lacunarity, octaves, Offset); } else { @@ -776,21 +776,21 @@ shader node_musgrave_texture( } else if (dimensions == "4D") { vector4 p = vector4(s[0], s[1], s[2], W) * Scale; - if (type == "multifractal") { + if (musgrave_type == "multifractal") { Fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, octaves); } - else if (type == "fBM") { + else if (musgrave_type == "fBM") { Fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, octaves); } - else if (type == "hybrid_multifractal") { + else if (musgrave_type == "hybrid_multifractal") { Fac = noise_musgrave_hybrid_multi_fractal_4d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "ridged_multifractal") { + else if (musgrave_type == "ridged_multifractal") { Fac = noise_musgrave_ridged_multi_fractal_4d( p, dimension, lacunarity, octaves, Offset, Gain); } - else if (type == "hetero_terrain") { + else if (musgrave_type == "hetero_terrain") { Fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, octaves, Offset); } else { diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index a12e7a9dc17..43d7bd36973 100644 --- a/intern/cycles/kernel/shaders/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -212,7 +212,7 @@ shader node_sky_texture( int use_mapping = 0, matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, - string type = "hosek_wilkie", + string sky_type = "hosek_wilkie", float theta = 0.0, float phi = 0.0, string filename = "", @@ -228,10 +228,10 @@ shader node_sky_texture( if (use_mapping) p = transform(mapping, p); - if (type == "nishita_improved") + if (sky_type == "nishita_improved") Color = sky_radiance_nishita(p, nishita_data, filename); - if (type == "hosek_wilkie") + if (sky_type == "hosek_wilkie") Color = sky_radiance_hosek(p, phi, theta, radiance, config_x, config_y, config_z); - if (type == "preetham") + if (sky_type == "preetham") Color = sky_radiance_preetham(p, phi, theta, radiance, config_x, config_y, config_z); } diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl index 218851598b4..30f0b1daf4c 100644 --- a/intern/cycles/kernel/shaders/node_vector_math.osl +++ b/intern/cycles/kernel/shaders/node_vector_math.osl @@ -17,7 +17,7 @@ #include "node_math.h" #include "stdcycles.h" -shader node_vector_math(string type = "add", +shader node_vector_math(string math_type = "add", vector Vector1 = vector(0.0, 0.0, 0.0), vector Vector2 = vector(0.0, 0.0, 0.0), vector Vector3 = vector(0.0, 0.0, 0.0), @@ -25,76 +25,76 @@ shader node_vector_math(string type = "add", output float Value = 0.0, output vector Vector = vector(0.0, 0.0, 0.0)) { - if (type == "add") { + if (math_type == "add") { Vector = Vector1 + Vector2; } - else if (type == "subtract") { + else if (math_type == "subtract") { Vector = Vector1 - Vector2; } - else if (type == "multiply") { + else if (math_type == "multiply") { Vector = Vector1 * Vector2; } - else if (type == "divide") { + else if (math_type == "divide") { Vector = safe_divide(Vector1, Vector2); } - else if (type == "cross_product") { + else if (math_type == "cross_product") { Vector = cross(Vector1, Vector2); } - else if (type == "project") { + else if (math_type == "project") { Vector = project(Vector1, Vector2); } - else if (type == "reflect") { + else if (math_type == "reflect") { Vector = reflect(Vector1, normalize(Vector2)); } - else if (type == "dot_product") { + else if (math_type == "dot_product") { Value = dot(Vector1, Vector2); } - else if (type == "distance") { + else if (math_type == "distance") { Value = distance(Vector1, Vector2); } - else if (type == "length") { + else if (math_type == "length") { Value = length(Vector1); } - else if (type == "scale") { + else if (math_type == "scale") { Vector = Vector1 * Scale; } - else if (type == "normalize") { + else if (math_type == "normalize") { Vector = normalize(Vector1); } - else if (type == "snap") { + else if (math_type == "snap") { Vector = snap(Vector1, Vector2); } - else if (type == "floor") { + else if (math_type == "floor") { Vector = floor(Vector1); } - else if (type == "ceil") { + else if (math_type == "ceil") { Vector = ceil(Vector1); } - else if (type == "modulo") { + else if (math_type == "modulo") { Vector = fmod(Vector1, Vector2); } - else if (type == "wrap") { + else if (math_type == "wrap") { Vector = wrap(Vector1, Vector2, Vector3); } - else if (type == "fraction") { + else if (math_type == "fraction") { Vector = Vector1 - floor(Vector1); } - else if (type == "absolute") { + else if (math_type == "absolute") { Vector = abs(Vector1); } - else if (type == "minimum") { + else if (math_type == "minimum") { Vector = min(Vector1, Vector2); } - else if (type == "maximum") { + else if (math_type == "maximum") { Vector = max(Vector1, Vector2); } - else if (type == "sine") { + else if (math_type == "sine") { Vector = sin(Vector1); } - else if (type == "cosine") { + else if (math_type == "cosine") { Vector = cos(Vector1); } - else if (type == "tangent") { + else if (math_type == "tangent") { Vector = tan(Vector1); } else { diff --git a/intern/cycles/kernel/shaders/node_vector_rotate.osl b/intern/cycles/kernel/shaders/node_vector_rotate.osl index 2efe3470ae2..e99bf7d81b0 100644 --- a/intern/cycles/kernel/shaders/node_vector_rotate.osl +++ b/intern/cycles/kernel/shaders/node_vector_rotate.osl @@ -18,7 +18,7 @@ #include "stdcycles.h" shader node_vector_rotate(int invert = 0, - string type = "axis", + string rotate_type = "axis", vector VectorIn = vector(0.0, 0.0, 0.0), point Center = point(0.0, 0.0, 0.0), point Rotation = point(0.0, 0.0, 0.0), @@ -26,19 +26,19 @@ shader node_vector_rotate(int invert = 0, float Angle = 0.0, output vector VectorOut = vector(0.0, 0.0, 0.0)) { - if (type == "euler_xyz") { + if (rotate_type == "euler_xyz") { matrix rmat = (invert) ? transpose(euler_to_mat(Rotation)) : euler_to_mat(Rotation); VectorOut = transform(rmat, VectorIn - Center) + Center; } else { float a = (invert) ? -Angle : Angle; - if (type == "x_axis") { + if (rotate_type == "x_axis") { VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(1.0, 0.0, 0.0)) + Center; } - else if (type == "y_axis") { + else if (rotate_type == "y_axis") { VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 1.0, 0.0)) + Center; } - else if (type == "z_axis") { + else if (rotate_type == "z_axis") { VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 0.0, 1.0)) + Center; } else { // axis diff --git a/intern/cycles/kernel/shaders/node_vector_transform.osl b/intern/cycles/kernel/shaders/node_vector_transform.osl index 1db799cfc9e..b71c6ec4824 100644 --- a/intern/cycles/kernel/shaders/node_vector_transform.osl +++ b/intern/cycles/kernel/shaders/node_vector_transform.osl @@ -16,18 +16,18 @@ #include "stdcycles.h" -shader node_vector_transform(string type = "vector", +shader node_vector_transform(string transform_type = "vector", string convert_from = "world", string convert_to = "object", vector VectorIn = vector(0.0, 0.0, 0.0), output vector VectorOut = vector(0.0, 0.0, 0.0)) { - if (type == "vector" || type == "normal") { + if (transform_type == "vector" || transform_type == "normal") { VectorOut = transform(convert_from, convert_to, VectorIn); - if (type == "normal") + if (transform_type == "normal") VectorOut = normalize(VectorOut); } - else if (type == "point") { + else if (transform_type == "point") { point Point = (point)VectorIn; VectorOut = transform(convert_from, convert_to, Point); } diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index 874bfb8d3af..71d81dff7ec 100644 --- a/intern/cycles/kernel/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -86,7 +86,7 @@ float wave(point p_input, shader node_wave_texture(int use_mapping = 0, matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - string type = "bands", + string wave_type = "bands", string bands_direction = "x", string rings_direction = "x", string profile = "sine", @@ -106,7 +106,7 @@ shader node_wave_texture(int use_mapping = 0, p = transform(mapping, p); Fac = wave(p * Scale, - type, + wave_type, bands_direction, rings_direction, profile, diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index fc7a3ba3f5a..f598bfb8f8f 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -19,10 +19,10 @@ CCL_NAMESPACE_BEGIN /* Attribute Node */ ccl_device AttributeDescriptor svm_node_attr_init( - KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, uint *out_offset) + KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeOutputType *type, uint *out_offset) { *out_offset = node.z; - *type = (NodeAttributeType)node.w; + *type = (NodeAttributeOutputType)node.w; AttributeDescriptor desc; @@ -46,144 +46,234 @@ ccl_device AttributeDescriptor svm_node_attr_init( ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - NodeAttributeType type = NODE_ATTR_FLOAT; + NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT; uint out_offset = 0; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); - /* fetch and store attribute */ - if (desc.type == NODE_ATTR_FLOAT) { - float f = primitive_attribute_float(kg, sd, desc, NULL, NULL); - if (type == NODE_ATTR_FLOAT) { +#ifdef __VOLUME__ + /* Volumes + * NOTE: moving this into its own node type might help improve performance. */ + if (primitive_is_volume_attribute(sd, desc)) { + const float4 value = volume_attribute_float4(kg, sd, desc); + + if (type == NODE_ATTR_OUTPUT_FLOAT) { + const float f = volume_attribute_value_to_float(value); stack_store_float(stack, out_offset, f); } + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { + const float3 f = volume_attribute_value_to_float3(value); + stack_store_float3(stack, out_offset, f); + } else { + const float f = volume_attribute_value_to_alpha(value); + stack_store_float(stack, out_offset, f); + } + return; + } +#endif + + /* Surface. */ + if (desc.type == NODE_ATTR_FLOAT) { + float f = primitive_surface_attribute_float(kg, sd, desc, NULL, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { + stack_store_float(stack, out_offset, f); + } + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f, f, f)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } else if (desc.type == NODE_ATTR_FLOAT2) { - float2 f = primitive_attribute_float2(kg, sd, desc, NULL, NULL); - if (type == NODE_ATTR_FLOAT) { + float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, f.x); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } - else if (desc.type == NODE_ATTR_RGBA) { - float4 f = primitive_attribute_float4(kg, sd, desc, NULL, NULL); - if (type == NODE_ATTR_FLOAT) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { + float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(float4_to_float3(f))); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, float4_to_float3(f)); } + else { + stack_store_float(stack, out_offset, f.w); + } } else { - float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL); - if (type == NODE_ATTR_FLOAT) { + float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(f)); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, f); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } } ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - NodeAttributeType type = NODE_ATTR_FLOAT; + NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT; uint out_offset = 0; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); - /* fetch and store attribute */ +#ifdef __VOLUME__ + /* Volume */ + if (primitive_is_volume_attribute(sd, desc)) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { + stack_store_float(stack, out_offset, 0.0f); + } + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { + stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f)); + } + else { + stack_store_float(stack, out_offset, 1.0f); + } + return; + } +#endif + + /* Surface */ if (desc.type == NODE_ATTR_FLOAT) { float dx; float f = primitive_surface_attribute_float(kg, sd, desc, &dx, NULL); - if (type == NODE_ATTR_FLOAT) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, f + dx); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f + dx, f + dx, f + dx)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } else if (desc.type == NODE_ATTR_FLOAT2) { float2 dx; - float2 f = primitive_attribute_float2(kg, sd, desc, &dx, NULL); - if (type == NODE_ATTR_FLOAT) { + float2 f = primitive_surface_attribute_float2(kg, sd, desc, &dx, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, f.x + dx.x); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } - else if (desc.type == NODE_ATTR_RGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 dx; - float4 f = primitive_attribute_float4(kg, sd, desc, &dx, NULL); - if (type == NODE_ATTR_FLOAT) { + float4 f = primitive_surface_attribute_float4(kg, sd, desc, &dx, NULL); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(float4_to_float3(f + dx))); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, float4_to_float3(f + dx)); } + else { + stack_store_float(stack, out_offset, f.w + dx.w); + } } else { float3 dx; float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL); - if (type == NODE_ATTR_FLOAT) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(f + dx)); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, f + dx); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } } ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - NodeAttributeType type = NODE_ATTR_FLOAT; + NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT; uint out_offset = 0; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset); - /* fetch and store attribute */ +#ifdef __VOLUME__ + /* Volume */ + if (primitive_is_volume_attribute(sd, desc)) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { + stack_store_float(stack, out_offset, 0.0f); + } + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { + stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f)); + } + else { + stack_store_float(stack, out_offset, 1.0f); + } + return; + } +#endif + + /* Surface */ if (desc.type == NODE_ATTR_FLOAT) { float dy; float f = primitive_surface_attribute_float(kg, sd, desc, NULL, &dy); - if (type == NODE_ATTR_FLOAT) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, f + dy); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f + dy, f + dy, f + dy)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } else if (desc.type == NODE_ATTR_FLOAT2) { float2 dy; - float2 f = primitive_attribute_float2(kg, sd, desc, NULL, &dy); - if (type == NODE_ATTR_FLOAT) { + float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, &dy); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, f.x + dy.x); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f)); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } - else if (desc.type == NODE_ATTR_RGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 dy; - float4 f = primitive_attribute_float4(kg, sd, desc, NULL, &dy); - if (type == NODE_ATTR_FLOAT) { + float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, &dy); + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(float4_to_float3(f + dy))); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, float4_to_float3(f + dy)); } + else { + stack_store_float(stack, out_offset, f.w + dy.w); + } } else { float3 dy; float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy); - if (type == NODE_ATTR_FLOAT) { + if (type == NODE_ATTR_OUTPUT_FLOAT) { stack_store_float(stack, out_offset, average(f + dy)); } - else { + else if (type == NODE_ATTR_OUTPUT_FLOAT3) { stack_store_float3(stack, out_offset, f + dy); } + else { + stack_store_float(stack, out_offset, 1.0f); + } } } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index f1ebb37e23e..c228df14985 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -157,10 +157,17 @@ typedef enum ShaderNodeType { * match the switch case order in svm.h. */ } ShaderNodeType; +typedef enum NodeAttributeOutputType { + NODE_ATTR_OUTPUT_FLOAT3 = 0, + NODE_ATTR_OUTPUT_FLOAT, + NODE_ATTR_OUTPUT_FLOAT_ALPHA, +} NodeAttributeOutputType; + typedef enum NodeAttributeType { NODE_ATTR_FLOAT = 0, NODE_ATTR_FLOAT2, NODE_ATTR_FLOAT3, + NODE_ATTR_FLOAT4, NODE_ATTR_RGBA, NODE_ATTR_MATRIX } NodeAttributeType; diff --git a/intern/cycles/kernel/svm/svm_vertex_color.h b/intern/cycles/kernel/svm/svm_vertex_color.h index 3c105b1cbfa..0aa45835522 100644 --- a/intern/cycles/kernel/svm/svm_vertex_color.h +++ b/intern/cycles/kernel/svm/svm_vertex_color.h @@ -25,7 +25,7 @@ ccl_device void svm_node_vertex_color(KernelGlobals *kg, { AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); if (descriptor.offset != ATTR_STD_NOT_FOUND) { - float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, NULL); + float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, NULL, NULL); stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); stack_store_float(stack, alpha_offset, vertex_color.w); } @@ -51,7 +51,7 @@ ccl_device_noinline AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); if (descriptor.offset != ATTR_STD_NOT_FOUND) { float4 dx; - float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, &dx, NULL); + float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, &dx, NULL); vertex_color += dx; stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); stack_store_float(stack, alpha_offset, vertex_color.w); @@ -78,7 +78,7 @@ ccl_device_noinline AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); if (descriptor.offset != ATTR_STD_NOT_FOUND) { float4 dy; - float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, &dy); + float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, NULL, &dy); vertex_color += dy; stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); stack_store_float(stack, alpha_offset, vertex_color.w); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index cdef1036647..b478aae9ae2 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -34,7 +34,7 @@ Attribute::Attribute( assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor || type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2 || - type == TypeRGBA); + type == TypeFloat4 || type == TypeRGBA); if (element == ATTR_ELEMENT_VOXEL) { buffer.resize(sizeof(ImageHandle)); @@ -167,62 +167,62 @@ size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const size = 1; break; case ATTR_ELEMENT_VERTEX: - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); - size = mesh->verts.size() + mesh->num_ngons; + size = mesh->get_verts().size() + mesh->get_num_ngons(); if (prim == ATTR_PRIM_SUBD) { - size -= mesh->num_subd_verts; + size -= mesh->get_num_subd_verts(); } } break; case ATTR_ELEMENT_VERTEX_MOTION: - if (geom->type == Geometry::MESH) { + if (geom->geometry_type == Geometry::MESH) { Mesh *mesh = static_cast<Mesh *>(geom); - size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1); + size = (mesh->get_verts().size() + mesh->get_num_ngons()) * (mesh->get_motion_steps() - 1); if (prim == ATTR_PRIM_SUBD) { - size -= mesh->num_subd_verts * (mesh->motion_steps - 1); + size -= mesh->get_num_subd_verts() * (mesh->get_motion_steps() - 1); } } break; case ATTR_ELEMENT_FACE: - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); if (prim == ATTR_PRIM_GEOMETRY) { size = mesh->num_triangles(); } else { - size = mesh->subd_faces.size() + mesh->num_ngons; + size = mesh->get_num_subd_faces() + mesh->get_num_ngons(); } } break; case ATTR_ELEMENT_CORNER: case ATTR_ELEMENT_CORNER_BYTE: - if (geom->type == Geometry::MESH) { + if (geom->geometry_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; + size = mesh->get_subd_face_corners().size() + mesh->get_num_ngons(); } } break; case ATTR_ELEMENT_CURVE: - if (geom->type == Geometry::HAIR) { + if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); size = hair->num_curves(); } break; case ATTR_ELEMENT_CURVE_KEY: - if (geom->type == Geometry::HAIR) { + if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); - size = hair->curve_keys.size(); + size = hair->get_curve_keys().size(); } break; case ATTR_ELEMENT_CURVE_KEY_MOTION: - if (geom->type == Geometry::HAIR) { + if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast<Hair *>(geom); - size = hair->curve_keys.size() * (hair->motion_steps - 1); + size = hair->get_curve_keys().size() * (hair->get_motion_steps() - 1); } break; default: @@ -445,7 +445,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) if (name == ustring()) name = Attribute::standard_name(std); - if (geometry->type == Geometry::MESH) { + if (geometry->geometry_type == Geometry::MESH) { switch (std) { case ATTR_STD_VERTEX_NORMAL: attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX); @@ -496,7 +496,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) break; } } - else if (geometry->type == Geometry::VOLUME) { + else if (geometry->geometry_type == Geometry::VOLUME) { switch (std) { case ATTR_STD_VERTEX_NORMAL: attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX); @@ -521,7 +521,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) break; } } - else if (geometry->type == Geometry::HAIR) { + else if (geometry->geometry_type == Geometry::HAIR) { switch (std) { case ATTR_STD_UV: attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE); diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 5871fa04a31..9990a1325a7 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -177,6 +177,7 @@ class AttributeSet { list<Attribute> attributes; AttributeSet(Geometry *geometry, AttributePrimitive prim); + AttributeSet(AttributeSet &&) = default; ~AttributeSet(); Attribute *add(ustring name, TypeDesc type, AttributeElement element); diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index d2463454522..7bdcb1578c3 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -54,7 +54,6 @@ NODE_DEFINE(Background) Background::Background() : Node(node_type) { - need_update = true; shader = NULL; } @@ -64,7 +63,7 @@ Background::~Background() void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene) { - if (!need_update) + if (!is_modified()) return; scoped_callback_timer timer([scene](double time) { @@ -102,7 +101,7 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene else kbackground->volume_shader = SHADER_NONE; - kbackground->volume_step_size = volume_step_size * scene->integrator->volume_step_rate; + kbackground->volume_step_size = volume_step_size * scene->integrator->get_volume_step_rate(); /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */ if (bg_shader->graph->nodes.size() <= 1) { @@ -122,22 +121,17 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA; } - need_update = false; + clear_modified(); } void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/) { } -bool Background::modified(const Background &background) -{ - return !Node::equals(background); -} - void Background::tag_update(Scene *scene) { scene->integrator->tag_update(scene); - need_update = true; + tag_modified(); } Shader *Background::get_shader(const Scene *scene) diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h index c2ca1f75179..e89ffbc2445 100644 --- a/intern/cycles/render/background.h +++ b/intern/cycles/render/background.h @@ -32,22 +32,20 @@ class Background : public Node { public: NODE_DECLARE - float ao_factor; - float ao_distance; + NODE_SOCKET_API(float, ao_factor) + NODE_SOCKET_API(float, ao_distance) - bool use_shader; - bool use_ao; + NODE_SOCKET_API(bool, use_shader) + NODE_SOCKET_API(bool, use_ao) - uint visibility; - Shader *shader; + NODE_SOCKET_API(uint, visibility) + NODE_SOCKET_API(Shader *, shader) - bool transparent; - bool transparent_glass; - float transparent_roughness_threshold; + NODE_SOCKET_API(bool, transparent) + NODE_SOCKET_API(bool, transparent_glass) + NODE_SOCKET_API(float, transparent_roughness_threshold) - float volume_step_size; - - bool need_update; + NODE_SOCKET_API(float, volume_step_size) Background(); ~Background(); @@ -55,7 +53,6 @@ class Background : public Node { void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene); - bool modified(const Background &background); void tag_update(Scene *scene); Shader *get_shader(const Scene *scene); diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 05f52159671..439ebdedb8e 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -33,10 +33,11 @@ static int aa_samples(Scene *scene, Object *object, ShaderEvalType type) } else if (type == SHADER_EVAL_NORMAL) { /* Only antialias normal if mesh has bump mapping. */ - if (object->geometry) { - foreach (Shader *shader, object->geometry->used_shaders) { + if (object->get_geometry()) { + foreach (Node *node, object->get_geometry()->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->has_bump) { - return scene->integrator->aa_samples; + return scene->integrator->get_aa_samples(); } } } @@ -44,7 +45,7 @@ static int aa_samples(Scene *scene, Object *object, ShaderEvalType type) return 1; } else { - return scene->integrator->aa_samples; + return scene->integrator->get_aa_samples(); } } @@ -112,7 +113,7 @@ void BakeManager::set(Scene *scene, } /* create device and update scene */ - scene->film->tag_update(scene); + scene->film->tag_modified(); scene->integrator->tag_update(scene); need_update = true; @@ -140,8 +141,8 @@ void BakeManager::device_update(Device * /*device*/, int object_index = 0; foreach (Object *object, scene->objects) { - const Geometry *geom = object->geometry; - if (object->name == object_name && geom->type == Geometry::MESH) { + const Geometry *geom = object->get_geometry(); + if (object->name == object_name && geom->geometry_type == Geometry::MESH) { kbake->object_index = object_index; kbake->tri_offset = geom->prim_offset; kintegrator->aa_samples = aa_samples(scene, object, type); diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 3607300cee6..045931ffdac 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -125,6 +125,7 @@ RenderTile::RenderTile() buffer = 0; buffers = NULL; + stealing_state = NO_STEALING; } /* Render Buffers */ diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index 425400a2c08..4ffc628bb52 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -146,6 +146,9 @@ class RenderTile { device_ptr buffer; int device_size; + typedef enum { NO_STEALING = 0, CAN_BE_STOLEN = 1, WAS_STOLEN = 2 } StealingState; + StealingState stealing_state; + RenderBuffers *buffers; RenderTile(); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 0f2befae320..92cf712d32a 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -98,7 +98,7 @@ NODE_DEFINE(Camera) type_enum.insert("perspective", CAMERA_PERSPECTIVE); type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC); type_enum.insert("panorama", CAMERA_PANORAMA); - SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE); + SOCKET_ENUM(camera_type, "Type", type_enum, CAMERA_PERSPECTIVE); static NodeEnum panorama_type_enum; panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR); @@ -148,8 +148,18 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(border.bottom, "Border Bottom", 0); SOCKET_FLOAT(border.top, "Border Top", 0); + SOCKET_FLOAT(viewport_camera_border.left, "Viewport Border Left", 0); + SOCKET_FLOAT(viewport_camera_border.right, "Viewport Border Right", 0); + SOCKET_FLOAT(viewport_camera_border.bottom, "Viewport Border Bottom", 0); + SOCKET_FLOAT(viewport_camera_border.top, "Viewport Border Top", 0); + SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f); + SOCKET_INT(full_width, "Full Width", 1024); + SOCKET_INT(full_height, "Full Height", 512); + + SOCKET_BOOLEAN(use_perspective_motion, "Use Perspective Motion", false); + return type; } @@ -182,7 +192,6 @@ Camera::Camera() : Node(node_type) dx = make_float3(0.0f, 0.0f, 0.0f); dy = make_float3(0.0f, 0.0f, 0.0f); - need_update = true; need_device_update = true; need_flags_update = true; previous_need_motion = -1; @@ -196,7 +205,7 @@ Camera::~Camera() void Camera::compute_auto_viewplane() { - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { viewplane.left = 0.0f; viewplane.right = 1.0f; viewplane.bottom = 0.0f; @@ -230,7 +239,7 @@ void Camera::update(Scene *scene) need_device_update = true; } - if (!need_update) + if (!is_modified()) return; scoped_callback_timer timer([scene](double time) { @@ -257,9 +266,9 @@ void Camera::update(Scene *scene) /* screen to camera */ ProjectionTransform cameratoscreen; - if (type == CAMERA_PERSPECTIVE) + if (camera_type == CAMERA_PERSPECTIVE) cameratoscreen = projection_perspective(fov, nearclip, farclip); - else if (type == CAMERA_ORTHOGRAPHIC) + else if (camera_type == CAMERA_ORTHOGRAPHIC) cameratoscreen = projection_orthographic(nearclip, farclip); else cameratoscreen = projection_identity(); @@ -284,13 +293,13 @@ void Camera::update(Scene *scene) worldtoraster = ndctoraster * worldtondc; /* differentials */ - if (type == CAMERA_ORTHOGRAPHIC) { + if (camera_type == CAMERA_ORTHOGRAPHIC) { dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0)); dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0)); full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0)); full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0)); } - else if (type == CAMERA_PERSPECTIVE) { + else if (camera_type == CAMERA_PERSPECTIVE) { dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) - transform_perspective(&rastertocamera, make_float3(0, 0, 0)); dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) - @@ -310,7 +319,7 @@ void Camera::update(Scene *scene) full_dx = transform_direction(&cameratoworld, full_dx); full_dy = transform_direction(&cameratoworld, full_dy); - if (type == CAMERA_PERSPECTIVE) { + if (camera_type == CAMERA_PERSPECTIVE) { float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 1.0f)); frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x)); @@ -348,7 +357,7 @@ void Camera::update(Scene *scene) if (need_motion == Scene::MOTION_PASS) { /* TODO(sergey): Support perspective (zoom, fov) motion. */ - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { if (have_motion) { kcam->motion_pass_pre = transform_inverse(motion[0]); kcam->motion_pass_post = transform_inverse(motion[motion.size() - 1]); @@ -377,7 +386,7 @@ void Camera::update(Scene *scene) } /* TODO(sergey): Support other types of camera. */ - if (use_perspective_motion && type == CAMERA_PERSPECTIVE) { + if (use_perspective_motion && camera_type == CAMERA_PERSPECTIVE) { /* TODO(sergey): Move to an utility function and de-duplicate with * calculation above. */ @@ -402,7 +411,7 @@ void Camera::update(Scene *scene) kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f; /* type */ - kcam->type = type; + kcam->type = camera_type; /* anamorphic lens bokeh */ kcam->inv_aperture_ratio = 1.0f / aperture_ratio; @@ -464,7 +473,7 @@ void Camera::update(Scene *scene) kcam->rolling_shutter_duration = rolling_shutter_duration; /* Set further update flags */ - need_update = false; + clear_modified(); need_device_update = true; need_flags_update = true; previous_need_motion = need_motion; @@ -527,7 +536,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen [&](const blocked_range<size_t> &r) { for (size_t i = r.begin(); i != r.end(); i++) { Object *object = scene->objects[i]; - if (object->geometry->has_volume && + if (object->get_geometry()->has_volume && viewplane_boundbox.intersects(object->bounds)) { /* TODO(sergey): Consider adding more grained check. */ VLOG(1) << "Detected camera inside volume."; @@ -553,25 +562,10 @@ void Camera::device_free(Device * /*device*/, DeviceScene *dscene, Scene *scene) dscene->camera_motion.free(); } -bool Camera::modified(const Camera &cam) -{ - return !Node::equals(cam); -} - -bool Camera::motion_modified(const Camera &cam) -{ - return !((motion == cam.motion) && (use_perspective_motion == cam.use_perspective_motion)); -} - -void Camera::tag_update() -{ - need_update = true; -} - float3 Camera::transform_raster_to_world(float raster_x, float raster_y) { float3 D, P; - if (type == CAMERA_PERSPECTIVE) { + if (camera_type == CAMERA_PERSPECTIVE) { D = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); float3 Pclip = normalize(D); P = make_float3(0.0f, 0.0f, 0.0f); @@ -584,7 +578,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y) */ P += nearclip * D / Pclip.z; } - else if (type == CAMERA_ORTHOGRAPHIC) { + else if (camera_type == CAMERA_ORTHOGRAPHIC) { D = make_float3(0.0f, 0.0f, 1.0f); /* TODO(sergey): Aperture support? */ P = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); @@ -603,7 +597,7 @@ BoundBox Camera::viewplane_bounds_get() * checks we need in a more clear and smart fashion? */ BoundBox bounds = BoundBox::empty; - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { if (use_spherical_stereo == false) { bounds.grow(make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w)); } @@ -628,7 +622,7 @@ BoundBox Camera::viewplane_bounds_get() bounds.grow(transform_raster_to_world(0.0f, (float)height)); bounds.grow(transform_raster_to_world((float)width, (float)height)); bounds.grow(transform_raster_to_world((float)width, 0.0f)); - if (type == CAMERA_PERSPECTIVE) { + if (camera_type == CAMERA_PERSPECTIVE) { /* Center point has the most distance in local Z axis, * use it to construct bounding box/ */ @@ -642,7 +636,7 @@ float Camera::world_to_raster_size(float3 P) { float res = 1.0f; - if (type == CAMERA_ORTHOGRAPHIC) { + if (camera_type == CAMERA_ORTHOGRAPHIC) { res = min(len(full_dx), len(full_dy)); if (offscreen_dicing_scale > 1.0f) { @@ -668,7 +662,7 @@ float Camera::world_to_raster_size(float3 P) } } } - else if (type == CAMERA_PERSPECTIVE) { + else if (camera_type == CAMERA_PERSPECTIVE) { /* Calculate as if point is directly ahead of the camera. */ float3 raster = make_float3(0.5f * full_width, 0.5f * full_height, 0.0f); float3 Pcamera = transform_perspective(&full_rastertocamera, raster); @@ -743,7 +737,7 @@ float Camera::world_to_raster_size(float3 P) } } } - else if (type == CAMERA_PANORAMA) { + else if (camera_type == CAMERA_PANORAMA) { float3 D = transform_point(&worldtocamera, P); float dist = len(D); @@ -794,6 +788,16 @@ bool Camera::use_motion() const return motion.size() > 1; } +void Camera::set_screen_size_and_resolution(int width_, int height_, int resolution_) +{ + if (width_ != width || height_ != height || resolution_ != resolution) { + width = width_; + height = height_; + resolution = resolution_; + tag_modified(); + } +} + float Camera::motion_time(int step) const { return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 21dad5eea3b..7970381f338 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -73,78 +73,92 @@ class Camera : public Node { }; /* motion blur */ - float shuttertime; - MotionPosition motion_position; - array<float> shutter_curve; + NODE_SOCKET_API(float, shuttertime) + NODE_SOCKET_API(MotionPosition, motion_position) + NODE_SOCKET_API_ARRAY(array<float>, shutter_curve) size_t shutter_table_offset; /* ** Rolling shutter effect. ** */ /* Defines rolling shutter effect type. */ - RollingShutterType rolling_shutter_type; + NODE_SOCKET_API(RollingShutterType, rolling_shutter_type) /* Specifies exposure time of scanlines when using * rolling shutter effect. */ - float rolling_shutter_duration; + NODE_SOCKET_API(float, rolling_shutter_duration) /* depth of field */ - float focaldistance; - float aperturesize; - uint blades; - float bladesrotation; + NODE_SOCKET_API(float, focaldistance) + NODE_SOCKET_API(float, aperturesize) + NODE_SOCKET_API(uint, blades) + NODE_SOCKET_API(float, bladesrotation) /* type */ - CameraType type; - float fov; + NODE_SOCKET_API(CameraType, camera_type) + NODE_SOCKET_API(float, fov) /* panorama */ - PanoramaType panorama_type; - float fisheye_fov; - float fisheye_lens; - float latitude_min; - float latitude_max; - float longitude_min; - float longitude_max; + NODE_SOCKET_API(PanoramaType, panorama_type) + NODE_SOCKET_API(float, fisheye_fov) + NODE_SOCKET_API(float, fisheye_lens) + NODE_SOCKET_API(float, latitude_min) + NODE_SOCKET_API(float, latitude_max) + NODE_SOCKET_API(float, longitude_min) + NODE_SOCKET_API(float, longitude_max) /* panorama stereo */ - StereoEye stereo_eye; - bool use_spherical_stereo; - float interocular_distance; - float convergence_distance; - bool use_pole_merge; - float pole_merge_angle_from; - float pole_merge_angle_to; + NODE_SOCKET_API(StereoEye, stereo_eye) + NODE_SOCKET_API(bool, use_spherical_stereo) + NODE_SOCKET_API(float, interocular_distance) + NODE_SOCKET_API(float, convergence_distance) + NODE_SOCKET_API(bool, use_pole_merge) + NODE_SOCKET_API(float, pole_merge_angle_from) + NODE_SOCKET_API(float, pole_merge_angle_to) /* anamorphic lens bokeh */ - float aperture_ratio; + NODE_SOCKET_API(float, aperture_ratio) /* sensor */ - float sensorwidth; - float sensorheight; + NODE_SOCKET_API(float, sensorwidth) + NODE_SOCKET_API(float, sensorheight) /* clipping */ - float nearclip; - float farclip; + NODE_SOCKET_API(float, nearclip) + NODE_SOCKET_API(float, farclip) /* screen */ - int width, height; - int resolution; BoundBox2D viewplane; + NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, left) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, right) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, bottom) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, top) + /* width and height change during preview, so we need these for calculating dice rates. */ - int full_width, full_height; + NODE_SOCKET_API(int, full_width) + NODE_SOCKET_API(int, full_height) /* controls how fast the dicing rate falls off for geometry out side of view */ - float offscreen_dicing_scale; + NODE_SOCKET_API(float, offscreen_dicing_scale) /* border */ BoundBox2D border; + NODE_SOCKET_API_STRUCT_MEMBER(float, border, left) + NODE_SOCKET_API_STRUCT_MEMBER(float, border, right) + NODE_SOCKET_API_STRUCT_MEMBER(float, border, bottom) + NODE_SOCKET_API_STRUCT_MEMBER(float, border, top) + BoundBox2D viewport_camera_border; + NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, left) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, right) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, bottom) + NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, top) /* transformation */ - Transform matrix; + NODE_SOCKET_API(Transform, matrix) /* motion */ - array<Transform> motion; - bool use_perspective_motion; - float fov_pre, fov_post; + NODE_SOCKET_API_ARRAY(array<Transform>, motion) + NODE_SOCKET_API(bool, use_perspective_motion) + NODE_SOCKET_API(float, fov_pre) + NODE_SOCKET_API(float, fov_post) /* computed camera parameters */ ProjectionTransform screentoworld; @@ -174,7 +188,6 @@ class Camera : public Node { float3 frustum_bottom_normal; /* update */ - bool need_update; bool need_device_update; bool need_flags_update; int previous_need_motion; @@ -183,6 +196,12 @@ class Camera : public Node { KernelCamera kernel_camera; array<DecomposedTransform> kernel_camera_motion; + private: + int width; + int height; + int resolution; + + public: /* functions */ Camera(); ~Camera(); @@ -195,10 +214,6 @@ class Camera : public Node { void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene, Scene *scene); - bool modified(const Camera &cam); - bool motion_modified(const Camera &cam); - void tag_update(); - /* Public utility functions. */ BoundBox viewplane_bounds_get(); @@ -210,6 +225,8 @@ class Camera : public Node { int motion_step(float time) const; bool use_motion() const; + void set_screen_size_and_resolution(int width_, int height_, int resolution_); + private: /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index e4c1e452bd5..5c3778f6ae5 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -40,10 +40,8 @@ static bool compare_pass_order(const Pass &a, const Pass &b) return (a.components > b.components); } -NODE_DEFINE(Pass) +static NodeEnum *get_pass_type_enum() { - NodeType *type = NodeType::add("pass", create); - static NodeEnum pass_type_enum; pass_type_enum.insert("combined", PASS_COMBINED); pass_type_enum.insert("depth", PASS_DEPTH); @@ -84,7 +82,15 @@ NODE_DEFINE(Pass) pass_type_enum.insert("bake_primitive", PASS_BAKE_PRIMITIVE); pass_type_enum.insert("bake_differential", PASS_BAKE_DIFFERENTIAL); - SOCKET_ENUM(type, "Type", pass_type_enum, PASS_COMBINED); + return &pass_type_enum; +} + +NODE_DEFINE(Pass) +{ + NodeType *type = NodeType::add("pass", create); + + NodeEnum *pass_type_enum = get_pass_type_enum(); + SOCKET_ENUM(type, "Type", *pass_type_enum, PASS_COMBINED); SOCKET_STRING(name, "Name", ustring()); return type; @@ -383,6 +389,21 @@ NODE_DEFINE(Film) SOCKET_INT(denoising_flags, "Denoising Flags", 0); SOCKET_BOOLEAN(use_adaptive_sampling, "Use Adaptive Sampling", false); + SOCKET_BOOLEAN(use_light_visibility, "Use Light Visibility", false); + + NodeEnum *pass_type_enum = get_pass_type_enum(); + SOCKET_ENUM(display_pass, "Display Pass", *pass_type_enum, PASS_COMBINED); + + static NodeEnum cryptomatte_passes_enum; + cryptomatte_passes_enum.insert("none", CRYPT_NONE); + cryptomatte_passes_enum.insert("object", CRYPT_OBJECT); + cryptomatte_passes_enum.insert("material", CRYPT_MATERIAL); + cryptomatte_passes_enum.insert("asset", CRYPT_ASSET); + cryptomatte_passes_enum.insert("accurate", CRYPT_ACCURATE); + SOCKET_ENUM(cryptomatte_passes, "Cryptomatte Passes", cryptomatte_passes_enum, CRYPT_NONE); + + SOCKET_INT(cryptomatte_depth, "Cryptomatte Depth", 0); + return type; } @@ -392,8 +413,6 @@ Film::Film() : Node(node_type) filter_table_offset = TABLE_OFFSET_INVALID; cryptomatte_passes = CRYPT_NONE; display_pass = PASS_COMBINED; - - need_update = true; } Film::~Film() @@ -407,7 +426,7 @@ void Film::add_default(Scene *scene) void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) { - if (!need_update) + if (!is_modified()) return; scoped_callback_timer timer([scene](double time) { @@ -658,7 +677,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) denoising_data_offset = kfilm->pass_denoising_data; denoising_clean_offset = kfilm->pass_denoising_clean; - need_update = false; + clear_modified(); } void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene) @@ -666,11 +685,6 @@ void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *sce scene->lookup_tables->remove_table(&filter_table_offset); } -bool Film::modified(const Film &film) -{ - return !Node::equals(film); -} - void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes) { if (Pass::contains(scene->passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) { @@ -691,11 +705,6 @@ void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool upd } } -void Film::tag_update(Scene * /*scene*/) -{ - need_update = true; -} - int Film::get_aov_offset(Scene *scene, string name, bool &is_color) { int num_color = 0, num_value = 0; @@ -719,4 +728,24 @@ int Film::get_aov_offset(Scene *scene, string name, bool &is_color) return -1; } +int Film::get_pass_stride() const +{ + return pass_stride; +} + +int Film::get_denoising_data_offset() const +{ + return denoising_data_offset; +} + +int Film::get_denoising_clean_offset() const +{ + return denoising_clean_offset; +} + +size_t Film::get_filter_table_offset() const +{ + return filter_table_offset; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 961058c008e..462a7275491 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -60,34 +60,35 @@ class Film : public Node { public: NODE_DECLARE - float exposure; - bool denoising_data_pass; - bool denoising_clean_pass; - bool denoising_prefiltered_pass; - int denoising_flags; - float pass_alpha_threshold; - - PassType display_pass; - int pass_stride; - int denoising_data_offset; - int denoising_clean_offset; + NODE_SOCKET_API(float, exposure) + NODE_SOCKET_API(bool, denoising_data_pass) + NODE_SOCKET_API(bool, denoising_clean_pass) + NODE_SOCKET_API(bool, denoising_prefiltered_pass) + NODE_SOCKET_API(int, denoising_flags) + NODE_SOCKET_API(float, pass_alpha_threshold) - FilterType filter_type; - float filter_width; - size_t filter_table_offset; + NODE_SOCKET_API(PassType, display_pass) - float mist_start; - float mist_depth; - float mist_falloff; + NODE_SOCKET_API(FilterType, filter_type) + NODE_SOCKET_API(float, filter_width) - bool use_light_visibility; - CryptomatteType cryptomatte_passes; - int cryptomatte_depth; + NODE_SOCKET_API(float, mist_start) + NODE_SOCKET_API(float, mist_depth) + NODE_SOCKET_API(float, mist_falloff) - bool use_adaptive_sampling; + NODE_SOCKET_API(bool, use_light_visibility) + NODE_SOCKET_API(CryptomatteType, cryptomatte_passes) + NODE_SOCKET_API(int, cryptomatte_depth) - bool need_update; + NODE_SOCKET_API(bool, use_adaptive_sampling) + private: + int pass_stride; + int denoising_data_offset; + int denoising_clean_offset; + size_t filter_table_offset; + + public: Film(); ~Film(); @@ -97,11 +98,14 @@ class Film : public Node { void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene, Scene *scene); - bool modified(const Film &film); void tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes = true); - void tag_update(Scene *scene); int get_aov_offset(Scene *scene, string name, bool &is_color); + + int get_pass_stride() const; + int get_denoising_data_offset() const; + int get_denoising_clean_offset() const; + size_t get_filter_table_offset() const; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 03f10075147..12f4eaf0b79 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -52,14 +52,14 @@ NODE_ABSTRACT_DEFINE(Geometry) SOCKET_UINT(motion_steps, "Motion Steps", 3); SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false); + SOCKET_NODE_ARRAY(used_shaders, "Shaders", &Shader::node_type); return type; } Geometry::Geometry(const NodeType *node_type, const Type type) - : Node(node_type), type(type), attributes(this, ATTR_PRIM_GEOMETRY) + : Node(node_type), geometry_type(type), attributes(this, ATTR_PRIM_GEOMETRY) { - need_update = true; need_update_rebuild = false; transform_applied = false; @@ -81,9 +81,11 @@ Geometry::~Geometry() delete bvh; } -void Geometry::clear() +void Geometry::clear(bool preserve_shaders) { - used_shaders.clear(); + if (!preserve_shaders) + used_shaders.clear(); + transform_applied = false; transform_negative_scaled = false; transform_normal = transform_identity(); @@ -97,9 +99,11 @@ bool Geometry::need_attribute(Scene *scene, AttributeStandard std) if (scene->need_global_attribute(std)) return true; - foreach (Shader *shader, used_shaders) + foreach (Node *node, used_shaders) { + Shader *shader = static_cast<Shader *>(node); if (shader->attributes.find(std)) return true; + } return false; } @@ -109,13 +113,27 @@ bool Geometry::need_attribute(Scene * /*scene*/, ustring name) if (name == ustring()) return false; - foreach (Shader *shader, used_shaders) + foreach (Node *node, used_shaders) { + Shader *shader = static_cast<Shader *>(node); if (shader->attributes.find(name)) return true; + } return false; } +AttributeRequestSet Geometry::needed_attributes() +{ + AttributeRequestSet result; + + foreach (Node *node, used_shaders) { + Shader *shader = static_cast<Shader *>(node); + result.add(shader->attributes); + } + + return result; +} + float Geometry::motion_time(int step) const { return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; @@ -159,8 +177,9 @@ bool Geometry::is_instanced() const bool Geometry::has_true_displacement() const { - foreach (Shader *shader, used_shaders) { - if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) { + foreach (Node *node, used_shaders) { + Shader *shader = static_cast<Shader *>(node); + if (shader->has_displacement && shader->get_displacement_method() != DISPLACE_BUMP) { return true; } } @@ -186,7 +205,7 @@ void Geometry::compute_bvh( msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total); Object object; - object.geometry = this; + object.set_geometry(this); vector<Geometry *> geometry; geometry.push_back(this); @@ -220,7 +239,7 @@ void Geometry::compute_bvh( } } - need_update = false; + clear_modified(); need_update_rebuild = false; } @@ -242,16 +261,18 @@ bool Geometry::has_voxel_attributes() const void Geometry::tag_update(Scene *scene, bool rebuild) { - need_update = true; + tag_modified(); if (rebuild) { need_update_rebuild = true; scene->light_manager->need_update = true; } else { - foreach (Shader *shader, used_shaders) + foreach (Node *node, used_shaders) { + Shader *shader = static_cast<Shader *>(node); if (shader->has_surface_emission) scene->light_manager->need_update = true; + } } scene->geometry_manager->need_update = true; @@ -305,15 +326,12 @@ void GeometryManager::update_osl_attributes(Device *device, } /* find geometry attributes */ - size_t j; - - for (j = 0; j < scene->geometry.size(); j++) - if (scene->geometry[j] == object->geometry) - break; + size_t j = object->geometry->index; + assert(j < scene->geometry.size() && scene->geometry[j] == object->geometry); AttributeRequestSet &attributes = geom_attributes[j]; - /* set object attributes */ + /* set mesh attributes */ foreach (AttributeRequest &req, attributes.requests) { OSLGlobals::Attribute osl_attr; @@ -375,10 +393,68 @@ void GeometryManager::update_osl_attributes(Device *device, #endif } +/* Generate a normal attribute map entry from an attribute descriptor. */ +static void emit_attribute_map_entry( + uint4 *attr_map, int index, uint id, TypeDesc type, const AttributeDescriptor &desc) +{ + attr_map[index].x = id; + attr_map[index].y = desc.element; + attr_map[index].z = as_uint(desc.offset); + + if (type == TypeDesc::TypeFloat) + attr_map[index].w = NODE_ATTR_FLOAT; + else if (type == TypeDesc::TypeMatrix) + attr_map[index].w = NODE_ATTR_MATRIX; + else if (type == TypeFloat2) + attr_map[index].w = NODE_ATTR_FLOAT2; + else if (type == TypeFloat4) + attr_map[index].w = NODE_ATTR_FLOAT4; + else if (type == TypeRGBA) + attr_map[index].w = NODE_ATTR_RGBA; + else + attr_map[index].w = NODE_ATTR_FLOAT3; + + attr_map[index].w |= desc.flags << 8; +} + +/* Generate an attribute map end marker, optionally including a link to another map. + * Links are used to connect object attribute maps to mesh attribute maps. */ +static void emit_attribute_map_terminator(uint4 *attr_map, int index, bool chain, uint chain_link) +{ + for (int j = 0; j < ATTR_PRIM_TYPES; j++) { + attr_map[index + j].x = ATTR_STD_NONE; + attr_map[index + j].y = chain; /* link is valid flag */ + attr_map[index + j].z = chain ? chain_link + j : 0; /* link to the correct sub-entry */ + attr_map[index + j].w = 0; + } +} + +/* Generate all necessary attribute map entries from the attribute request. */ +static void emit_attribute_mapping( + uint4 *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom) +{ + 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); + + emit_attribute_map_entry(attr_map, index, id, req.type, req.desc); + + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->get_num_subd_faces()) { + emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc); + } + } +} + void GeometryManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *scene, - vector<AttributeRequestSet> &geom_attributes) + vector<AttributeRequestSet> &geom_attributes, + vector<AttributeRequestSet> &object_attributes) { /* for SVM, the attributes_map table is used to lookup the offset of an * attribute, based on a unique shader attribute id. */ @@ -392,6 +468,19 @@ void GeometryManager::update_svm_attributes(Device *, attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES; } + for (size_t i = 0; i < scene->objects.size(); i++) { + Object *object = scene->objects[i]; + + /* only allocate a table for the object if it actually has attributes */ + if (object_attributes[i].size() == 0) { + object->attr_map_offset = 0; + } + else { + object->attr_map_offset = attr_map_size; + attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES; + } + } + if (attr_map_size == 0) return; @@ -403,69 +492,31 @@ void GeometryManager::update_svm_attributes(Device *, Geometry *geom = scene->geometry[i]; AttributeRequestSet &attributes = geom_attributes[i]; - /* set object attributes */ + /* set geometry 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); + emit_attribute_mapping(attr_map, index, scene, req, geom); + index += ATTR_PRIM_TYPES; + } - 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; + emit_attribute_map_terminator(attr_map, index, false, 0); + } - attr_map[index].w |= req.desc.flags << 8; + for (size_t i = 0; i < scene->objects.size(); i++) { + Object *object = scene->objects[i]; + AttributeRequestSet &attributes = object_attributes[i]; - index++; + /* set object attributes */ + if (attributes.size() > 0) { + int index = object->attr_map_offset; - 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; - } + foreach (AttributeRequest &req, attributes.requests) { + emit_attribute_mapping(attr_map, index, scene, req, object->geometry); + index += ATTR_PRIM_TYPES; } - 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++; + emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset); } } @@ -505,19 +556,19 @@ static void update_attribute_element_size(Geometry *geom, } } -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) +void GeometryManager::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 */ @@ -589,7 +640,7 @@ static void update_attribute_element_offset(Geometry *geom, /* mesh vertex/curve index is global, not per object, so we sneak * a correction for that in here */ - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && desc.flags & ATTR_SUBDIVIDED) { @@ -613,7 +664,7 @@ static void update_attribute_element_offset(Geometry *geom, offset -= mesh->corner_offset; } } - else if (geom->type == Geometry::HAIR) { + else if (geom->is_hair()) { Hair *hair = static_cast<Hair *>(geom); if (element == ATTR_ELEMENT_CURVE) offset -= hair->prim_offset; @@ -645,13 +696,48 @@ void GeometryManager::device_update_attributes(Device *device, for (size_t i = 0; i < scene->geometry.size(); i++) { Geometry *geom = scene->geometry[i]; + geom->index = i; scene->need_global_attributes(geom_attributes[i]); - foreach (Shader *shader, geom->used_shaders) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); geom_attributes[i].add(shader->attributes); } } + /* convert object attributes to use the same data structures as geometry ones */ + vector<AttributeRequestSet> object_attributes(scene->objects.size()); + vector<AttributeSet> object_attribute_values; + + object_attribute_values.reserve(scene->objects.size()); + + for (size_t i = 0; i < scene->objects.size(); i++) { + Object *object = scene->objects[i]; + Geometry *geom = object->geometry; + size_t geom_idx = geom->index; + + assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom); + + object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY)); + + AttributeRequestSet &geom_requests = geom_attributes[geom_idx]; + AttributeRequestSet &attributes = object_attributes[i]; + AttributeSet &values = object_attribute_values[i]; + + for (size_t j = 0; j < object->attributes.size(); j++) { + ParamValue ¶m = object->attributes[j]; + + /* add attributes that are requested and not already handled by the mesh */ + if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) { + attributes.add(param.name()); + + Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT); + assert(param.datasize() == attr->buffer.size()); + memcpy(attr->buffer.data(), param.data(), param.datasize()); + } + } + } + /* 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 */ @@ -663,6 +749,7 @@ void GeometryManager::device_update_attributes(Device *device, 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]; @@ -677,7 +764,7 @@ void GeometryManager::device_update_attributes(Device *device, &attr_float3_size, &attr_uchar4_size); - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); Attribute *subd_attr = mesh->subd_attributes.find(req); @@ -692,6 +779,20 @@ void GeometryManager::device_update_attributes(Device *device, } } + for (size_t i = 0; i < scene->objects.size(); i++) { + Object *object = scene->objects[i]; + + foreach (Attribute &attr, object_attribute_values[i].attributes) { + update_attribute_element_size(object->geometry, + &attr, + ATTR_PRIM_GEOMETRY, + &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); @@ -725,7 +826,7 @@ void GeometryManager::device_update_attributes(Device *device, req.type, req.desc); - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); Attribute *subd_attr = mesh->subd_attributes.find(req); @@ -749,11 +850,42 @@ void GeometryManager::device_update_attributes(Device *device, } } + for (size_t i = 0; i < scene->objects.size(); i++) { + Object *object = scene->objects[i]; + AttributeRequestSet &attributes = object_attributes[i]; + AttributeSet &values = object_attribute_values[i]; + + foreach (AttributeRequest &req, attributes.requests) { + Attribute *attr = values.find(req); + + update_attribute_element_offset(object->geometry, + 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); + + /* object attributes don't care about subdivision */ + req.subd_type = req.type; + req.subd_desc = req.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); + update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes); if (progress.get_cancel()) return; @@ -797,7 +929,7 @@ void GeometryManager::mesh_calc_offset(Scene *scene) size_t optix_prim_size = 0; foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); mesh->vert_offset = vert_size; @@ -810,8 +942,8 @@ void GeometryManager::mesh_calc_offset(Scene *scene) 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]; + if (mesh->get_num_subd_faces()) { + Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1); patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; /* patch tables are stored in same array so include them in patch_size */ @@ -821,19 +953,19 @@ void GeometryManager::mesh_calc_offset(Scene *scene) } } - face_size += mesh->subd_faces.size(); + face_size += mesh->get_num_subd_faces(); 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) { + else if (geom->is_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_key_size += hair->get_curve_keys().size(); curve_size += hair->num_curves(); hair->optix_prim_offset = optix_prim_size; @@ -855,14 +987,14 @@ void GeometryManager::device_update_mesh( size_t patch_size = 0; foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { 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]; + if (mesh->get_num_subd_faces()) { + Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1); patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; /* patch tables are stored in same array so include them in patch_size */ @@ -872,10 +1004,10 @@ void GeometryManager::device_update_mesh( } } } - else if (geom->type == Geometry::HAIR) { + else if (geom->is_hair()) { Hair *hair = static_cast<Hair *>(geom); - curve_key_size += hair->curve_keys.size(); + curve_key_size += hair->get_curve_keys().size(); curve_size += hair->num_curves(); } } @@ -889,7 +1021,7 @@ void GeometryManager::device_update_mesh( * really use same semantic of arrays. */ foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { 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); @@ -917,7 +1049,7 @@ void GeometryManager::device_update_mesh( float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); mesh->pack_normals(&vnormal[mesh->vert_offset]); @@ -949,7 +1081,7 @@ void GeometryManager::device_update_mesh( float4 *curves = dscene->curves.alloc(curve_size); foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::HAIR) { + if (geom->is_hair()) { Hair *hair = static_cast<Hair *>(geom); hair->pack_curves(scene, &curve_keys[hair->curvekey_offset], @@ -970,7 +1102,7 @@ void GeometryManager::device_update_mesh( uint *patch_data = dscene->patches.alloc(patch_size); foreach (Geometry *geom, scene->geometry) { - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); mesh->pack_patches(&patch_data[mesh->patch_offset], mesh->vert_offset, @@ -993,7 +1125,7 @@ void GeometryManager::device_update_mesh( 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 || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); for (size_t i = 0; i < mesh->num_triangles(); ++i) { Mesh::Triangle t = mesh->get_triangle(i); @@ -1120,7 +1252,8 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro foreach (Geometry *geom, scene->geometry) { geom->has_volume = false; - foreach (const Shader *shader, geom->used_shaders) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->has_volume) { geom->has_volume = true; } @@ -1132,7 +1265,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro /* Re-create volume mesh if we will rebuild or refit the BVH. Note we * should only do it in that case, otherwise the BVH and mesh can go * out of sync. */ - if (geom->need_update && geom->type == Geometry::VOLUME) { + if (geom->is_modified() && geom->geometry_type == Geometry::VOLUME) { /* Create volume meshes if there is voxel data. */ if (!volume_images_updated) { progress.set_status("Updating Meshes Volume Bounds"); @@ -1144,7 +1277,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro create_volume_mesh(volume, progress); } - if (geom->type == Geometry::HAIR) { + if (geom->is_hair()) { /* Set curve shape, still a global scene setting for now. */ Hair *hair = static_cast<Hair *>(geom); hair->curve_shape = scene->params.hair_shape; @@ -1163,9 +1296,10 @@ void GeometryManager::device_update_displacement_images(Device *device, 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) { + if (geom->is_modified()) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { continue; } foreach (ShaderNode *node, shader->graph->nodes) { @@ -1199,7 +1333,7 @@ void GeometryManager::device_update_volume_images(Device *device, Scene *scene, set<int> volume_images; foreach (Geometry *geom, scene->geometry) { - if (!geom->need_update) { + if (!geom->is_modified()) { continue; } @@ -1248,12 +1382,14 @@ void GeometryManager::device_update(Device *device, }); foreach (Geometry *geom, scene->geometry) { - foreach (Shader *shader, geom->used_shaders) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->need_update_geometry) - geom->need_update = true; + geom->tag_modified(); } - if (geom->need_update && (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME)) { + if (geom->is_modified() && + (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) { Mesh *mesh = static_cast<Mesh *>(geom); /* Update normals. */ @@ -1265,8 +1401,7 @@ void GeometryManager::device_update(Device *device, } /* Test if we need tessellation. */ - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 && - mesh->subd_params) { + if (mesh->need_tesselation()) { total_tess_needed++; } @@ -1296,17 +1431,18 @@ void GeometryManager::device_update(Device *device, }); Camera *dicing_camera = scene->dicing_camera; + dicing_camera->set_screen_size_and_resolution( + dicing_camera->get_full_width(), dicing_camera->get_full_height(), 1); dicing_camera->update(scene); size_t i = 0; foreach (Geometry *geom, scene->geometry) { - if (!(geom->need_update && geom->type == Geometry::MESH)) { + if (!(geom->is_modified() && geom->is_mesh())) { continue; } Mesh *mesh = static_cast<Mesh *>(geom); - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 && - mesh->subd_params) { + if (mesh->need_tesselation()) { string msg = "Tessellating "; if (mesh->name == "") msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed); @@ -1390,8 +1526,8 @@ void GeometryManager::device_update(Device *device, }); foreach (Geometry *geom, scene->geometry) { - if (geom->need_update) { - if (geom->type == Geometry::MESH) { + if (geom->is_modified()) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); if (displace(device, dscene, scene, mesh, progress)) { displacement_done = true; @@ -1439,7 +1575,7 @@ void GeometryManager::device_update(Device *device, size_t i = 0; foreach (Geometry *geom, scene->geometry) { - if (geom->need_update) { + if (geom->is_modified()) { pool.push(function_bind( &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh)); if (geom->need_build_bvh(bvh_layout)) { diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h index bcadb3a8051..1c101540464 100644 --- a/intern/cycles/render/geometry.h +++ b/intern/cycles/render/geometry.h @@ -56,13 +56,13 @@ class Geometry : public Node { VOLUME, }; - Type type; + Type geometry_type; /* Attributes */ AttributeSet attributes; /* Shaders */ - vector<Shader *> used_shaders; + NODE_SOCKET_API_ARRAY(array<Node *>, used_shaders) /* Transform */ BoundBox bounds; @@ -71,8 +71,8 @@ class Geometry : public Node { Transform transform_normal; /* Motion Blur */ - uint motion_steps; - bool use_motion_blur; + NODE_SOCKET_API(uint, motion_steps) + NODE_SOCKET_API(bool, use_motion_blur) /* Maximum number of motion steps supported (due to Embree). */ static const uint MAX_MOTION_STEPS = 129; @@ -88,15 +88,17 @@ class Geometry : public Node { bool has_surface_bssrdf; /* Set in the device_update_flags(). */ /* Update Flags */ - bool need_update; bool need_update_rebuild; + /* Index into scene->geometry (only valid during update) */ + size_t index; + /* Constructor/Destructor */ explicit Geometry(const NodeType *node_type, const Type type); virtual ~Geometry(); /* Geometry */ - virtual void clear(); + virtual void clear(bool preserve_shaders = false); virtual void compute_bounds() = 0; virtual void apply_transform(const Transform &tfm, const bool apply_to_motion) = 0; @@ -104,6 +106,8 @@ class Geometry : public Node { bool need_attribute(Scene *scene, AttributeStandard std); bool need_attribute(Scene *scene, ustring name); + AttributeRequestSet needed_attributes(); + /* UDIM */ virtual void get_uv_tiles(ustring map, unordered_set<int> &tiles) = 0; @@ -138,6 +142,16 @@ class Geometry : public Node { bool has_motion_blur() const; bool has_voxel_attributes() const; + bool is_mesh() const + { + return geometry_type == MESH; + } + + bool is_hair() const + { + return geometry_type == HAIR; + } + /* Updates */ void tag_update(Scene *scene, bool rebuild); }; @@ -177,7 +191,8 @@ class GeometryManager { void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, - vector<AttributeRequestSet> &geom_attributes); + vector<AttributeRequestSet> &geom_attributes, + vector<AttributeRequestSet> &object_attributes); /* Compute verts/triangles/curves offsets in global arrays. */ void mesh_calc_offset(Scene *scene); @@ -200,6 +215,21 @@ class GeometryManager { void device_update_displacement_images(Device *device, Scene *scene, Progress &progress); void device_update_volume_images(Device *device, Scene *scene, Progress &progress); + + private: + 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); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 088fda00abb..4adfebf80ae 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -273,8 +273,8 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) if (to->type() == SocketType::CLOSURE) { EmissionNode *emission = create_node<EmissionNode>(); - emission->color = make_float3(1.0f, 1.0f, 1.0f); - emission->strength = 1.0f; + emission->set_color(make_float3(1.0f, 1.0f, 1.0f)); + emission->set_strength(1.0f); convert = add(emission); /* Connect float inputs to Strength to save an additional Falue->Color conversion. */ if (from->type() == SocketType::FLOAT) { @@ -586,7 +586,7 @@ void ShaderGraph::constant_fold(Scene *scene) */ if (has_displacement && !output()->input("Displacement")->link) { ColorNode *value = (ColorNode *)add(create_node<ColorNode>()); - value->value = output()->displacement; + value->set_value(output()->get_displacement()); connect(value->output("Color"), output()->input("Displacement")); } @@ -1004,8 +1004,8 @@ void ShaderGraph::bump_from_displacement(bool use_object_space) /* add bump node and connect copied graphs to it */ BumpNode *bump = (BumpNode *)add(create_node<BumpNode>()); - bump->use_object_space = use_object_space; - bump->distance = 1.0f; + bump->set_use_object_space(use_object_space); + bump->set_distance(1.0f); ShaderOutput *out = displacement_in->link; ShaderOutput *out_center = nodes_center[out->parent]->output(out->name()); @@ -1017,9 +1017,9 @@ void ShaderGraph::bump_from_displacement(bool use_object_space) VectorMathNode *dot_dx = (VectorMathNode *)add(create_node<VectorMathNode>()); VectorMathNode *dot_dy = (VectorMathNode *)add(create_node<VectorMathNode>()); - dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT; - dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT; - dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT; + dot_center->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT); + dot_dx->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT); + dot_dy->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT); GeometryNode *geom = (GeometryNode *)add(create_node<GeometryNode>()); connect(geom->output("Normal"), dot_center->input("Vector2")); @@ -1073,7 +1073,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight if (fin->link) connect(fin->link, fac_in); else - mix_node->fac = node->get_float(fin->socket_type); + mix_node->set_fac(node->get_float(fin->socket_type)); if (weight_out) connect(weight_out, weight_in); @@ -1108,12 +1108,12 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight if (weight_in->link) connect(weight_in->link, math_node->input("Value1")); else - math_node->value1 = weight_value; + math_node->set_value1(weight_value); if (weight_out) connect(weight_out, math_node->input("Value2")); else - math_node->value2 = 1.0f; + math_node->set_value2(1.0f); weight_out = math_node->output("Value"); if (weight_in->link) diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp index 816c15cf4ef..d67bd209142 100644 --- a/intern/cycles/render/hair.cpp +++ b/intern/cycles/render/hair.cpp @@ -321,9 +321,9 @@ void Hair::reserve_curves(int numcurves, int numkeys) attributes.resize(true); } -void Hair::clear() +void Hair::clear(bool preserve_shaders) { - Geometry::clear(); + Geometry::clear(preserve_shaders); curve_keys.clear(); curve_radius.clear(); @@ -337,12 +337,18 @@ void Hair::add_curve_key(float3 co, float radius) { curve_keys.push_back_reserved(co); curve_radius.push_back_reserved(radius); + + tag_curve_keys_modified(); + tag_curve_radius_modified(); } void Hair::add_curve(int first_key, int shader) { curve_first_key.push_back_reserved(first_key); curve_shader.push_back_reserved(shader); + + tag_curve_first_key_modified(); + tag_curve_shader_modified(); } void Hair::copy_center_to_motion_step(const int motion_step) @@ -474,8 +480,9 @@ void Hair::pack_curves(Scene *scene, 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 *shader = (shader_id < used_shaders.size()) ? + static_cast<Shader *>(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), diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h index 39d6a34d799..32c5b00e879 100644 --- a/intern/cycles/render/hair.h +++ b/intern/cycles/render/hair.h @@ -89,10 +89,10 @@ class Hair : public Geometry { float4 r_keys[4]) const; }; - array<float3> curve_keys; - array<float> curve_radius; - array<int> curve_first_key; - array<int> curve_shader; + NODE_SOCKET_API(array<float3>, curve_keys) + NODE_SOCKET_API(array<float>, curve_radius) + NODE_SOCKET_API(array<int>, curve_first_key) + NODE_SOCKET_API(array<int>, curve_shader) /* BVH */ size_t curvekey_offset; @@ -103,7 +103,7 @@ class Hair : public Geometry { ~Hair(); /* Geometry */ - void clear() override; + void clear(bool preserve_shaders = false) override; void resize_curves(int numcurves, int numkeys); void reserve_curves(int numcurves, int numkeys); diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index e50e70c8591..3e6ff289c85 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -381,7 +381,7 @@ ImageHandle ImageManager::add_image(const string &filename, const ImageParams &p ImageHandle ImageManager::add_image(const string &filename, const ImageParams ¶ms, - const vector<int> &tiles) + const array<int> &tiles) { ImageHandle handle; handle.manager = this; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index c9eccb3468a..6ac1db9ed63 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -174,7 +174,7 @@ class ImageManager { ImageHandle add_image(const string &filename, const ImageParams ¶ms); ImageHandle add_image(const string &filename, const ImageParams ¶ms, - const vector<int> &tiles); + const array<int> &tiles); ImageHandle add_image(ImageLoader *loader, const ImageParams ¶ms, const bool builtin = true); void device_update(Device *device, Scene *scene, Progress &progress); diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp index fc2cfe9874e..70b3de5a939 100644 --- a/intern/cycles/render/image_vdb.cpp +++ b/intern/cycles/render/image_vdb.cpp @@ -48,7 +48,6 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata) /* Set dimensions. */ openvdb::Coord dim = bbox.dim(); - openvdb::Coord min = bbox.min(); metadata.width = dim.x(); metadata.height = dim.y(); metadata.depth = dim.z(); @@ -144,8 +143,13 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata) } } +# ifdef WITH_NANOVDB + Transform texture_to_index = transform_identity(); +# else + openvdb::Coord min = bbox.min(); Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) * transform_scale(dim.x(), dim.y(), dim.z()); +# endif metadata.transform_3d = transform_inverse(index_to_object * texture_to_index); metadata.use_transform_3d = true; @@ -159,10 +163,10 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata) bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) { -#if defined(WITH_NANOVDB) +#ifdef WITH_OPENVDB +# ifdef WITH_NANOVDB memcpy(pixels, nanogrid.data(), nanogrid.size()); - return true; -#elif defined(WITH_OPENVDB) +# else if (grid->isType<openvdb::FloatGrid>()) { openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense); @@ -202,7 +206,7 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense); } - +# endif return true; #else (void)pixels; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index cc085af20a0..3dc4b2fd4c5 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -96,7 +96,6 @@ NODE_DEFINE(Integrator) Integrator::Integrator() : Node(node_type) { - need_update = true; } Integrator::~Integrator() @@ -105,7 +104,7 @@ Integrator::~Integrator() void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene) { - if (!need_update) + if (!is_modified()) return; scoped_callback_timer timer([scene](double time) { @@ -144,7 +143,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->transparent_shadows = false; foreach (Shader *shader, scene->shaders) { /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */ - if ((shader->has_surface_transparent && shader->use_transparent_shadow) || + if ((shader->has_surface_transparent && shader->get_use_transparent_shadow()) || shader->has_volume) { kintegrator->transparent_shadows = true; break; @@ -227,7 +226,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene if (method == BRANCHED_PATH) { foreach (Light *light, scene->lights) - max_samples = max(max_samples, light->samples); + max_samples = max(max_samples, light->get_samples()); max_samples = max(max_samples, max(diffuse_samples, max(glossy_samples, transmission_samples))); @@ -265,7 +264,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene dscene->sample_pattern_lut.copy_to_device(); } - need_update = false; + clear_modified(); } void Integrator::device_free(Device *, DeviceScene *dscene) @@ -273,11 +272,6 @@ void Integrator::device_free(Device *, DeviceScene *dscene) dscene->sample_pattern_lut.free(); } -bool Integrator::modified(const Integrator &integrator) -{ - return !Node::equals(integrator); -} - void Integrator::tag_update(Scene *scene) { foreach (Shader *shader, scene->shaders) { @@ -286,7 +280,7 @@ void Integrator::tag_update(Scene *scene) break; } } - need_update = true; + tag_modified(); } CCL_NAMESPACE_END diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 9804caebe6e..9fe46ad591c 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -31,52 +31,52 @@ class Integrator : public Node { public: NODE_DECLARE - int min_bounce; - int max_bounce; + NODE_SOCKET_API(int, min_bounce) + NODE_SOCKET_API(int, max_bounce) - int max_diffuse_bounce; - int max_glossy_bounce; - int max_transmission_bounce; - int max_volume_bounce; + NODE_SOCKET_API(int, max_diffuse_bounce) + NODE_SOCKET_API(int, max_glossy_bounce) + NODE_SOCKET_API(int, max_transmission_bounce) + NODE_SOCKET_API(int, max_volume_bounce) - int transparent_min_bounce; - int transparent_max_bounce; + NODE_SOCKET_API(int, transparent_min_bounce) + NODE_SOCKET_API(int, transparent_max_bounce) - int ao_bounces; + NODE_SOCKET_API(int, ao_bounces) - int volume_max_steps; - float volume_step_rate; + NODE_SOCKET_API(int, volume_max_steps) + NODE_SOCKET_API(float, volume_step_rate) - bool caustics_reflective; - bool caustics_refractive; - float filter_glossy; + NODE_SOCKET_API(bool, caustics_reflective) + NODE_SOCKET_API(bool, caustics_refractive) + NODE_SOCKET_API(float, filter_glossy) - int seed; + NODE_SOCKET_API(int, seed) - float sample_clamp_direct; - float sample_clamp_indirect; - bool motion_blur; + NODE_SOCKET_API(float, sample_clamp_direct) + NODE_SOCKET_API(float, sample_clamp_indirect) + NODE_SOCKET_API(bool, motion_blur) /* Maximum number of samples, beyond which we are likely to run into * precision issues for sampling patterns. */ static const int MAX_SAMPLES = (1 << 24); - int aa_samples; - int diffuse_samples; - int glossy_samples; - int transmission_samples; - int ao_samples; - int mesh_light_samples; - int subsurface_samples; - int volume_samples; - int start_sample; + NODE_SOCKET_API(int, aa_samples) + NODE_SOCKET_API(int, diffuse_samples) + NODE_SOCKET_API(int, glossy_samples) + NODE_SOCKET_API(int, transmission_samples) + NODE_SOCKET_API(int, ao_samples) + NODE_SOCKET_API(int, mesh_light_samples) + NODE_SOCKET_API(int, subsurface_samples) + NODE_SOCKET_API(int, volume_samples) + NODE_SOCKET_API(int, start_sample) - bool sample_all_lights_direct; - bool sample_all_lights_indirect; - float light_sampling_threshold; + NODE_SOCKET_API(bool, sample_all_lights_direct) + NODE_SOCKET_API(bool, sample_all_lights_indirect) + NODE_SOCKET_API(float, light_sampling_threshold) - int adaptive_min_samples; - float adaptive_threshold; + NODE_SOCKET_API(int, adaptive_min_samples) + NODE_SOCKET_API(float, adaptive_threshold) enum Method { BRANCHED_PATH = 0, @@ -85,11 +85,9 @@ class Integrator : public Node { NUM_METHODS, }; - Method method; + NODE_SOCKET_API(Method, method) - SamplingPattern sampling_pattern; - - bool need_update; + NODE_SOCKET_API(SamplingPattern, sampling_pattern) Integrator(); ~Integrator(); @@ -97,7 +95,6 @@ class Integrator : public Node { void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene); - bool modified(const Integrator &integrator); void tag_update(Scene *scene); }; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 100530ffba6..80190dcbf82 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -114,7 +114,7 @@ NODE_DEFINE(Light) type_enum.insert("background", LIGHT_BACKGROUND); type_enum.insert("area", LIGHT_AREA); type_enum.insert("spot", LIGHT_SPOT); - SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT); + SOCKET_ENUM(light_type, "Type", type_enum, LIGHT_POINT); SOCKET_COLOR(strength, "Strength", make_float3(1.0f, 1.0f, 1.0f)); @@ -162,7 +162,7 @@ Light::Light() : Node(node_type) void Light::tag_update(Scene *scene) { - scene->light_manager->need_update = true; + scene->light_manager->need_update = is_modified(); } bool Light::has_contribution(Scene *scene) @@ -173,7 +173,7 @@ bool Light::has_contribution(Scene *scene) if (is_portal) { return false; } - if (type == LIGHT_BACKGROUND) { + if (light_type == LIGHT_BACKGROUND) { return true; } return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission; @@ -200,7 +200,7 @@ LightManager::~LightManager() bool LightManager::has_background_light(Scene *scene) { foreach (Light *light, scene->lights) { - if (light->type == LIGHT_BACKGROUND && light->is_enabled) { + if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) { return true; } } @@ -217,7 +217,7 @@ void LightManager::test_enabled_lights(Scene *scene) foreach (Light *light, scene->lights) { light->is_enabled = light->has_contribution(scene); has_portal |= light->is_portal; - has_background |= light->type == LIGHT_BACKGROUND; + has_background |= light->light_type == LIGHT_BACKGROUND; } bool background_enabled = false; @@ -232,7 +232,7 @@ void LightManager::test_enabled_lights(Scene *scene) const bool disable_mis = !(has_portal || shader->has_surface_spatial_varying); VLOG_IF(1, disable_mis) << "Background MIS has been disabled.\n"; foreach (Light *light, scene->lights) { - if (light->type == LIGHT_BACKGROUND) { + if (light->light_type == LIGHT_BACKGROUND) { light->is_enabled = !disable_mis; background_enabled = !disable_mis; background_resolution = light->map_resolution; @@ -250,8 +250,8 @@ void LightManager::test_enabled_lights(Scene *scene) bool LightManager::object_usable_as_light(Object *object) { - Geometry *geom = object->geometry; - if (geom->type != Geometry::MESH && geom->type != Geometry::VOLUME) { + Geometry *geom = object->get_geometry(); + if (geom->geometry_type != Geometry::MESH && geom->geometry_type != Geometry::VOLUME) { return false; } /* Skip objects with NaNs */ @@ -259,7 +259,7 @@ bool LightManager::object_usable_as_light(Object *object) return false; } /* Skip if we are not visible for BSDFs. */ - if (!(object->visibility & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) { + if (!(object->get_visibility() & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) { return false; } /* Skip if we have no emission shaders. */ @@ -267,8 +267,9 @@ bool LightManager::object_usable_as_light(Object *object) * iterate all geometry shaders twice (when counting and when calculating * triangle area. */ - foreach (const Shader *shader, geom->used_shaders) { - if (shader->use_mis && shader->has_surface_emission) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + if (shader->get_use_mis() && shader->has_surface_emission) { return true; } } @@ -308,15 +309,15 @@ void LightManager::device_update_distribution(Device *, } /* Count triangles. */ - Mesh *mesh = static_cast<Mesh *>(object->geometry); + Mesh *mesh = static_cast<Mesh *>(object->get_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]; - Shader *shader = (shader_index < mesh->used_shaders.size()) ? - mesh->used_shaders[shader_index] : + int shader_index = mesh->get_shader()[i]; + Shader *shader = (shader_index < mesh->get_used_shaders().size()) ? + static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) : scene->default_surface; - if (shader->use_mis && shader->has_surface_emission) { + if (shader->get_use_mis() && shader->has_surface_emission) { num_triangles++; } } @@ -342,37 +343,37 @@ void LightManager::device_update_distribution(Device *, continue; } /* Sum area. */ - Mesh *mesh = static_cast<Mesh *>(object->geometry); + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); bool transform_applied = mesh->transform_applied; - Transform tfm = object->tfm; + Transform tfm = object->get_tfm(); int object_id = j; int shader_flag = 0; - if (!(object->visibility & PATH_RAY_DIFFUSE)) { + if (!(object->get_visibility() & PATH_RAY_DIFFUSE)) { shader_flag |= SHADER_EXCLUDE_DIFFUSE; use_light_visibility = true; } - if (!(object->visibility & PATH_RAY_GLOSSY)) { + if (!(object->get_visibility() & PATH_RAY_GLOSSY)) { shader_flag |= SHADER_EXCLUDE_GLOSSY; use_light_visibility = true; } - if (!(object->visibility & PATH_RAY_TRANSMIT)) { + if (!(object->get_visibility() & PATH_RAY_TRANSMIT)) { shader_flag |= SHADER_EXCLUDE_TRANSMIT; use_light_visibility = true; } - if (!(object->visibility & PATH_RAY_VOLUME_SCATTER)) { + if (!(object->get_visibility() & PATH_RAY_VOLUME_SCATTER)) { shader_flag |= SHADER_EXCLUDE_SCATTER; use_light_visibility = true; } size_t mesh_num_triangles = mesh->num_triangles(); for (size_t i = 0; i < mesh_num_triangles; i++) { - int shader_index = mesh->shader[i]; - Shader *shader = (shader_index < mesh->used_shaders.size()) ? - mesh->used_shaders[shader_index] : + int shader_index = mesh->get_shader()[i]; + Shader *shader = (shader_index < mesh->get_used_shaders().size()) ? + static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) : scene->default_surface; - if (shader->use_mis && shader->has_surface_emission) { + if (shader->get_use_mis() && shader->has_surface_emission) { distribution[offset].totarea = totarea; distribution[offset].prim = i + mesh->prim_offset; distribution[offset].mesh_light.shader_flag = shader_flag; @@ -380,12 +381,12 @@ void LightManager::device_update_distribution(Device *, offset++; Mesh::Triangle t = mesh->get_triangle(i); - if (!t.valid(&mesh->verts[0])) { + if (!t.valid(&mesh->get_verts()[0])) { continue; } - float3 p1 = mesh->verts[t.v[0]]; - float3 p2 = mesh->verts[t.v[1]]; - float3 p3 = mesh->verts[t.v[2]]; + float3 p1 = mesh->get_verts()[t.v[0]]; + float3 p2 = mesh->get_verts()[t.v[1]]; + float3 p3 = mesh->get_verts()[t.v[2]]; if (!transform_applied) { p1 = transform_point(&tfm, p1); @@ -417,16 +418,16 @@ void LightManager::device_update_distribution(Device *, distribution[offset].lamp.size = light->size; totarea += lightarea; - if (light->type == LIGHT_DISTANT) { + if (light->light_type == LIGHT_DISTANT) { use_lamp_mis |= (light->angle > 0.0f && light->use_mis); } - else if (light->type == LIGHT_POINT || light->type == LIGHT_SPOT) { + else if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) { use_lamp_mis |= (light->size > 0.0f && light->use_mis); } - else if (light->type == LIGHT_AREA) { + else if (light->light_type == LIGHT_AREA) { use_lamp_mis |= light->use_mis; } - else if (light->type == LIGHT_BACKGROUND) { + else if (light->light_type == LIGHT_BACKGROUND) { num_background_lights++; background_mis |= light->use_mis; } @@ -576,7 +577,7 @@ void LightManager::device_update_background(Device *device, /* find background light */ foreach (Light *light, scene->lights) { - if (light->type == LIGHT_BACKGROUND) { + if (light->light_type == LIGHT_BACKGROUND) { background_light = light; break; } @@ -611,7 +612,7 @@ void LightManager::device_update_background(Device *device, } if (node->type == SkyTextureNode::node_type) { SkyTextureNode *sky = (SkyTextureNode *)node; - if (sky->type == NODE_SKY_NISHITA && sky->sun_disc) { + if (sky->get_sky_type() == NODE_SKY_NISHITA && sky->get_sun_disc()) { /* Ensure that the input coordinates aren't transformed before they reach the node. * If that is the case, the logic used for sampling the sun's location does not work * and we have to fall back to map-based sampling. */ @@ -627,8 +628,8 @@ void LightManager::device_update_background(Device *device, } /* Determine sun direction from lat/long and texture mapping. */ - float latitude = sky->sun_elevation; - float longitude = M_2PI_F - sky->sun_rotation + M_PI_2_F; + float latitude = sky->get_sun_elevation(); + float longitude = M_2PI_F - sky->get_sun_rotation() + M_PI_2_F; float3 sun_direction = make_float3( cosf(latitude) * cosf(longitude), cosf(latitude) * sinf(longitude), sinf(latitude)); Transform sky_transform = transform_inverse(sky->tex_mapping.compute_transform()); @@ -771,13 +772,13 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc use_light_visibility = true; } - klights[light_index].type = light->type; + klights[light_index].type = light->light_type; klights[light_index].samples = light->samples; klights[light_index].strength[0] = light->strength.x; klights[light_index].strength[1] = light->strength.y; klights[light_index].strength[2] = light->strength.z; - if (light->type == LIGHT_POINT) { + if (light->light_type == LIGHT_POINT) { shader_id &= ~SHADER_AREA_LIGHT; float radius = light->size; @@ -793,7 +794,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc klights[light_index].spot.radius = radius; klights[light_index].spot.invarea = invarea; } - else if (light->type == LIGHT_DISTANT) { + else if (light->light_type == LIGHT_DISTANT) { shader_id &= ~SHADER_AREA_LIGHT; float angle = light->angle / 2.0f; @@ -816,8 +817,8 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc klights[light_index].distant.radius = radius; klights[light_index].distant.cosangle = cosangle; } - else if (light->type == LIGHT_BACKGROUND) { - uint visibility = scene->background->visibility; + else if (light->light_type == LIGHT_BACKGROUND) { + uint visibility = scene->background->get_visibility(); shader_id &= ~SHADER_AREA_LIGHT; shader_id |= SHADER_USE_MIS; @@ -839,7 +840,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc use_light_visibility = true; } } - else if (light->type == LIGHT_AREA) { + else if (light->light_type == LIGHT_AREA) { float3 axisu = light->axisu * (light->sizeu * light->size); float3 axisv = light->axisv * (light->sizev * light->size); float area = len(axisu) * len(axisv); @@ -869,7 +870,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc klights[light_index].area.dir[1] = dir.y; klights[light_index].area.dir[2] = dir.z; } - else if (light->type == LIGHT_SPOT) { + else if (light->light_type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; float radius = light->size; @@ -913,7 +914,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc foreach (Light *light, scene->lights) { if (!light->is_portal) continue; - assert(light->type == LIGHT_AREA); + assert(light->light_type == LIGHT_AREA); float3 co = light->co; float3 axisu = light->axisu * (light->sizeu * light->size); @@ -995,10 +996,7 @@ void LightManager::device_update(Device *device, if (progress.get_cancel()) return; - if (use_light_visibility != scene->film->use_light_visibility) { - scene->film->use_light_visibility = use_light_visibility; - scene->film->tag_update(scene); - } + scene->film->set_use_light_visibility(use_light_visibility); need_update = false; need_update_background = false; diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index d136e8f1a08..e590e13b489 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -21,6 +21,10 @@ #include "graph/node.h" +/* included as Light::set_shader defined through NODE_SOCKET_API does not select + * the right Node::set overload as it does not know that Shader is a Node */ +#include "render/shader.h" + #include "util/util_ies.h" #include "util/util_thread.h" #include "util/util_types.h" @@ -41,46 +45,48 @@ class Light : public Node { Light(); - LightType type; - float3 strength; - float3 co; + NODE_SOCKET_API(LightType, light_type) + NODE_SOCKET_API(float3, strength) + NODE_SOCKET_API(float3, co) - float3 dir; - float size; - float angle; + NODE_SOCKET_API(float3, dir) + NODE_SOCKET_API(float, size) + NODE_SOCKET_API(float, angle) - float3 axisu; - float sizeu; - float3 axisv; - float sizev; - bool round; + NODE_SOCKET_API(float3, axisu) + NODE_SOCKET_API(float, sizeu) + NODE_SOCKET_API(float3, axisv) + NODE_SOCKET_API(float, sizev) + NODE_SOCKET_API(bool, round) - Transform tfm; + NODE_SOCKET_API(Transform, tfm) - int map_resolution; + NODE_SOCKET_API(int, map_resolution) - float spot_angle; - float spot_smooth; + NODE_SOCKET_API(float, spot_angle) + NODE_SOCKET_API(float, spot_smooth) - bool cast_shadow; - bool use_mis; - bool use_diffuse; - bool use_glossy; - bool use_transmission; - bool use_scatter; + NODE_SOCKET_API(bool, cast_shadow) + NODE_SOCKET_API(bool, use_mis) + NODE_SOCKET_API(bool, use_diffuse) + NODE_SOCKET_API(bool, use_glossy) + NODE_SOCKET_API(bool, use_transmission) + NODE_SOCKET_API(bool, use_scatter) - bool is_portal; - bool is_enabled; + NODE_SOCKET_API(bool, is_portal) + NODE_SOCKET_API(bool, is_enabled) - Shader *shader; - int samples; - int max_bounces; - uint random_id; + NODE_SOCKET_API(Shader *, shader) + NODE_SOCKET_API(int, samples) + NODE_SOCKET_API(int, max_bounces) + NODE_SOCKET_API(uint, random_id) void tag_update(Scene *scene); /* Check whether the light has contribution the scene. */ bool has_contribution(Scene *scene); + + friend class LightManager; }; class LightManager { diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 3015ac5e569..11c8e240afd 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -132,11 +132,58 @@ NODE_DEFINE(Mesh) SOCKET_INT_ARRAY(shader, "Shader", array<int>()); SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>()); + SOCKET_INT_ARRAY(triangle_patch, "Triangle Patch", array<int>()); + SOCKET_POINT2_ARRAY(vert_patch_uv, "Patch UVs", array<float2>()); + + static NodeEnum subdivision_type_enum; + subdivision_type_enum.insert("none", SUBDIVISION_NONE); + subdivision_type_enum.insert("linear", SUBDIVISION_LINEAR); + subdivision_type_enum.insert("catmull_clark", SUBDIVISION_CATMULL_CLARK); + SOCKET_ENUM(subdivision_type, "Subdivision Type", subdivision_type_enum, SUBDIVISION_NONE); + + SOCKET_INT_ARRAY(subd_creases_edge, "Subdivision Crease Edges", array<int>()); + SOCKET_FLOAT_ARRAY(subd_creases_weight, "Subdivision Crease Weights", array<float>()); + SOCKET_INT_ARRAY(subd_face_corners, "Subdivision Face Corners", array<int>()); + SOCKET_INT_ARRAY(subd_start_corner, "Subdivision Face Start Corner", array<int>()); + SOCKET_INT_ARRAY(subd_num_corners, "Subdivision Face Corner Count", array<int>()); + SOCKET_INT_ARRAY(subd_shader, "Subdivision Face Shader", array<int>()); + SOCKET_BOOLEAN_ARRAY(subd_smooth, "Subdivision Face Smooth", array<bool>()); + SOCKET_INT_ARRAY(subd_ptex_offset, "Subdivision Face PTex Offset", array<int>()); + SOCKET_INT(num_ngons, "NGons Number", 0); + + /* Subdivisions parameters */ + SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 0.0f) + SOCKET_INT(subd_max_level, "Subdivision Dicing Rate", 0); + SOCKET_TRANSFORM(subd_objecttoworld, "Subdivision Object Transform", transform_identity()); + return type; } -Mesh::Mesh(const NodeType *node_type_, Type geom_type_) - : Geometry(node_type_, geom_type_), subd_attributes(this, ATTR_PRIM_SUBD) +SubdParams *Mesh::get_subd_params() +{ + if (subdivision_type == SubdivisionType::SUBDIVISION_NONE) { + return nullptr; + } + + if (!subd_params) { + subd_params = new SubdParams(this); + } + + subd_params->dicing_rate = subd_dicing_rate; + subd_params->max_level = subd_max_level; + subd_params->objecttoworld = subd_objecttoworld; + + return subd_params; +} + +bool Mesh::need_tesselation() +{ + return get_subd_params() && (verts_is_modified() || subd_dicing_rate_is_modified() || + subd_objecttoworld_is_modified() || subd_max_level_is_modified()); +} + +Mesh::Mesh(const NodeType *node_type, Type geom_type_) + : Geometry(node_type, geom_type_), subd_attributes(this, ATTR_PRIM_SUBD) { vert_offset = 0; @@ -145,6 +192,7 @@ Mesh::Mesh(const NodeType *node_type_, Type geom_type_) corner_offset = 0; num_subd_verts = 0; + num_subd_faces = 0; num_ngons = 0; @@ -171,7 +219,7 @@ void Mesh::resize_mesh(int numverts, int numtris) shader.resize(numtris); smooth.resize(numtris); - if (subd_faces.size()) { + if (get_num_subd_faces()) { triangle_patch.resize(numtris); vert_patch_uv.resize(numverts); } @@ -187,7 +235,7 @@ void Mesh::reserve_mesh(int numverts, int numtris) shader.reserve(numtris); smooth.reserve(numtris); - if (subd_faces.size()) { + if (get_num_subd_faces()) { triangle_patch.reserve(numtris); vert_patch_uv.reserve(numverts); } @@ -197,25 +245,41 @@ void Mesh::reserve_mesh(int numverts, int numtris) void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners) { - subd_faces.resize(numfaces); + subd_start_corner.resize(numfaces); + subd_num_corners.resize(numfaces); + subd_shader.resize(numfaces); + subd_smooth.resize(numfaces); + subd_ptex_offset.resize(numfaces); subd_face_corners.resize(numcorners); num_ngons = num_ngons_; + num_subd_faces = numfaces; subd_attributes.resize(); } void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners) { - subd_faces.reserve(numfaces); + subd_start_corner.reserve(numfaces); + subd_num_corners.reserve(numfaces); + subd_shader.reserve(numfaces); + subd_smooth.reserve(numfaces); + subd_ptex_offset.reserve(numfaces); subd_face_corners.reserve(numcorners); num_ngons = num_ngons_; + num_subd_faces = numfaces; subd_attributes.resize(true); } -void Mesh::clear(bool preserve_voxel_data) +void Mesh::reserve_subd_creases(size_t num_creases) { - Geometry::clear(); + subd_creases_edge.reserve(num_creases * 2); + subd_creases_weight.reserve(num_creases); +} + +void Mesh::clear(bool preserve_shaders, bool preserve_voxel_data) +{ + Geometry::clear(preserve_shaders); /* clear all verts and triangles */ verts.clear(); @@ -226,12 +290,18 @@ void Mesh::clear(bool preserve_voxel_data) triangle_patch.clear(); vert_patch_uv.clear(); - subd_faces.clear(); + subd_start_corner.clear(); + subd_num_corners.clear(); + subd_shader.clear(); + subd_smooth.clear(); + subd_ptex_offset.clear(); subd_face_corners.clear(); num_subd_verts = 0; + num_subd_faces = 0; - subd_creases.clear(); + subd_creases_edge.clear(); + subd_creases_weight.clear(); subd_attributes.clear(); attributes.clear(preserve_voxel_data); @@ -239,30 +309,36 @@ void Mesh::clear(bool preserve_voxel_data) vert_to_stitching_key_map.clear(); vert_stitching_map.clear(); + subdivision_type = SubdivisionType::SUBDIVISION_NONE; + delete patch_table; patch_table = NULL; } -void Mesh::clear() +void Mesh::clear(bool preserve_shaders) { - clear(false); + clear(preserve_shaders, false); } void Mesh::add_vertex(float3 P) { verts.push_back_reserved(P); + tag_verts_modified(); - if (subd_faces.size()) { + if (get_num_subd_faces()) { vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f)); + tag_vert_patch_uv_modified(); } } void Mesh::add_vertex_slow(float3 P) { verts.push_back_slow(P); + tag_verts_modified(); - if (subd_faces.size()) { + if (get_num_subd_faces()) { vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f)); + tag_vert_patch_uv_modified(); } } @@ -274,8 +350,13 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) shader.push_back_reserved(shader_); smooth.push_back_reserved(smooth_); - if (subd_faces.size()) { + tag_triangles_modified(); + tag_shader_modified(); + tag_smooth_modified(); + + if (get_num_subd_faces()) { triangle_patch.push_back_reserved(-1); + tag_triangle_patch_modified(); } } @@ -288,14 +369,47 @@ void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth } int ptex_offset = 0; - - if (subd_faces.size()) { - SubdFace &s = subd_faces[subd_faces.size() - 1]; + // cannot use get_num_subd_faces here as it holds the total number of subd_faces, but we do not + // have the total amount of data yet + if (subd_shader.size()) { + SubdFace s = get_subd_face(subd_shader.size() - 1); ptex_offset = s.ptex_offset + s.num_ptex_faces(); } - SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset}; - subd_faces.push_back_reserved(face); + subd_start_corner.push_back_reserved(start_corner); + subd_num_corners.push_back_reserved(num_corners); + subd_shader.push_back_reserved(shader_); + subd_smooth.push_back_reserved(smooth_); + subd_ptex_offset.push_back_reserved(ptex_offset); + + tag_subd_face_corners_modified(); + tag_subd_start_corner_modified(); + tag_subd_num_corners_modified(); + tag_subd_shader_modified(); + tag_subd_smooth_modified(); + tag_subd_ptex_offset_modified(); +} + +Mesh::SubdFace Mesh::get_subd_face(size_t index) const +{ + Mesh::SubdFace s; + s.shader = subd_shader[index]; + s.num_corners = subd_num_corners[index]; + s.smooth = subd_smooth[index]; + s.ptex_offset = subd_ptex_offset[index]; + s.start_corner = subd_start_corner[index]; + return s; +} + +void Mesh::add_crease(int v0, int v1, float weight) +{ + subd_creases_edge.push_back_slow(v0); + subd_creases_edge.push_back_slow(v1); + subd_creases_weight.push_back_slow(weight); + + tag_subd_creases_edge_modified(); + tag_subd_creases_edge_modified(); + tag_subd_creases_weight_modified(); } void Mesh::copy_center_to_motion_step(const int motion_step) @@ -505,7 +619,7 @@ void Mesh::add_vertex_normals() } /* subd vertex normals */ - if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) { + if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && get_num_subd_faces()) { /* get attributes */ Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL); float3 *vN = attr_vN->data_float3(); @@ -513,8 +627,8 @@ void Mesh::add_vertex_normals() /* compute vertex normals */ memset(vN, 0, verts.size() * sizeof(float3)); - for (size_t i = 0; i < subd_faces.size(); i++) { - SubdFace &face = subd_faces[i]; + for (size_t i = 0; i < get_num_subd_faces(); i++) { + SubdFace face = get_subd_face(i); float3 fN = face.normal(this); for (size_t j = 0; j < face.num_corners; j++) { @@ -574,8 +688,9 @@ void Mesh::pack_shaders(Scene *scene, uint *tri_shader) if (shader_ptr[i] != last_shader || last_smooth != smooth[i]) { last_shader = shader_ptr[i]; last_smooth = smooth[i]; - Shader *shader = (last_shader < used_shaders.size()) ? used_shaders[last_shader] : - scene->default_surface; + Shader *shader = (last_shader < used_shaders.size()) ? + static_cast<Shader *>(used_shaders[last_shader]) : + scene->default_surface; shader_id = scene->shader_manager->get_shader_id(shader, last_smooth); } @@ -616,7 +731,7 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index, { size_t verts_size = verts.size(); - if (verts_size && subd_faces.size()) { + if (verts_size && get_num_subd_faces()) { float2 *vert_patch_uv_ptr = vert_patch_uv.data(); for (size_t i = 0; i < verts_size; i++) { @@ -633,17 +748,17 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index, t.v[2] + vert_offset, tri_prim_index[i + tri_offset]); - tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i] * 8 + patch_offset); + tri_patch[i] = (!get_num_subd_faces()) ? -1 : (triangle_patch[i] * 8 + patch_offset); } } void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset) { - size_t num_faces = subd_faces.size(); + size_t num_faces = get_num_subd_faces(); int ngons = 0; for (size_t f = 0; f < num_faces; f++) { - SubdFace face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (face.is_quad()) { int c[4]; diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index c8286a01e2c..6630dcd8a35 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -118,36 +118,57 @@ class Mesh : public Geometry { float crease; }; + SubdEdgeCrease get_subd_crease(size_t i) const + { + SubdEdgeCrease s; + s.v[0] = subd_creases_edge[i * 2]; + s.v[1] = subd_creases_edge[i * 2 + 1]; + s.crease = subd_creases_weight[i]; + return s; + } + + bool need_tesselation(); + enum SubdivisionType { SUBDIVISION_NONE, SUBDIVISION_LINEAR, SUBDIVISION_CATMULL_CLARK, }; - SubdivisionType subdivision_type; + NODE_SOCKET_API(SubdivisionType, subdivision_type) /* Mesh Data */ - array<int> triangles; - array<float3> verts; - array<int> shader; - array<bool> smooth; + NODE_SOCKET_API_ARRAY(array<int>, triangles) + NODE_SOCKET_API_ARRAY(array<float3>, verts) + NODE_SOCKET_API_ARRAY(array<int>, shader) + NODE_SOCKET_API_ARRAY(array<bool>, smooth) /* used for storing patch info for subd triangles, only allocated if there are patches */ - array<int> triangle_patch; /* must be < 0 for non subd triangles */ - array<float2> vert_patch_uv; + NODE_SOCKET_API_ARRAY(array<int>, triangle_patch) /* must be < 0 for non subd triangles */ + NODE_SOCKET_API_ARRAY(array<float2>, vert_patch_uv) + + /* SubdFaces */ + NODE_SOCKET_API_ARRAY(array<int>, subd_start_corner) + NODE_SOCKET_API_ARRAY(array<int>, subd_num_corners) + NODE_SOCKET_API_ARRAY(array<int>, subd_shader) + NODE_SOCKET_API_ARRAY(array<bool>, subd_smooth) + NODE_SOCKET_API_ARRAY(array<int>, subd_ptex_offset) - array<SubdFace> subd_faces; - array<int> subd_face_corners; - int num_ngons; + NODE_SOCKET_API_ARRAY(array<int>, subd_face_corners) + NODE_SOCKET_API(int, num_ngons) - array<SubdEdgeCrease> subd_creases; + NODE_SOCKET_API_ARRAY(array<int>, subd_creases_edge) + NODE_SOCKET_API_ARRAY(array<float>, subd_creases_weight) - SubdParams *subd_params; + /* Subdivisions parameters */ + NODE_SOCKET_API(float, subd_dicing_rate) + NODE_SOCKET_API(int, subd_max_level) + NODE_SOCKET_API(Transform, subd_objecttoworld) AttributeSet subd_attributes; + private: PackedPatchTable *patch_table; - /* BVH */ size_t vert_offset; @@ -157,13 +178,22 @@ class Mesh : public Geometry { size_t corner_offset; size_t num_subd_verts; + size_t num_subd_faces; - private: unordered_map<int, int> vert_to_stitching_key_map; /* real vert index -> stitching index */ unordered_multimap<int, int> vert_stitching_map; /* stitching index -> multiple real vert indices */ + + friend class BVH; + friend class BVHBuild; + friend class BVHEmbree; + friend class BVHSpatialSplit; friend class DiagSplit; + friend class EdgeDice; friend class GeometryManager; + friend class ObjectManager; + + SubdParams *subd_params = nullptr; public: /* Functions */ @@ -174,12 +204,13 @@ class Mesh : public Geometry { void reserve_mesh(int numverts, int numfaces); 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); - void clear() override; + void reserve_subd_creases(size_t num_creases); + void clear(bool preserve_shaders = false) 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_subd_face(int *corners, int num_corners, int shader_, bool smooth_); + void add_crease(int v0, int v1, float weight); void copy_center_to_motion_step(const int motion_step); @@ -202,6 +233,28 @@ class Mesh : public Geometry { void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset); void tessellate(DiagSplit *split); + + SubdFace get_subd_face(size_t index) const; + + SubdParams *get_subd_params(); + + size_t get_num_subd_faces() const + { + return num_subd_faces; + } + + void set_num_subd_faces(size_t num_subd_faces_) + { + num_subd_faces = num_subd_faces_; + } + + size_t get_num_subd_verts() + { + return num_subd_verts; + } + + protected: + void clear(bool preserve_shaders, bool preserve_voxel_data); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp index 467810f9273..b4fb5dcdea2 100644 --- a/intern/cycles/render/mesh_displace.cpp +++ b/intern/cycles/render/mesh_displace.cpp @@ -58,7 +58,7 @@ bool GeometryManager::displace( size_t object_index = OBJECT_NONE; for (size_t i = 0; i < scene->objects.size(); i++) { - if (scene->objects[i]->geometry == mesh) { + if (scene->objects[i]->get_geometry() == mesh) { object_index = i; break; } @@ -76,10 +76,10 @@ bool GeometryManager::displace( Mesh::Triangle t = mesh->get_triangle(i); int shader_index = mesh->shader[i]; Shader *shader = (shader_index < mesh->used_shaders.size()) ? - mesh->used_shaders[shader_index] : + static_cast<Shader *>(mesh->used_shaders[shader_index]) : scene->default_surface; - if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { + if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { continue; } @@ -160,10 +160,10 @@ bool GeometryManager::displace( Mesh::Triangle t = mesh->get_triangle(i); int shader_index = mesh->shader[i]; Shader *shader = (shader_index < mesh->used_shaders.size()) ? - mesh->used_shaders[shader_index] : + static_cast<Shader *>(mesh->used_shaders[shader_index]) : scene->default_surface; - if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { + if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { continue; } @@ -227,8 +227,9 @@ bool GeometryManager::displace( bool need_recompute_vertex_normals = false; - foreach (Shader *shader, mesh->used_shaders) { - if (shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) { + foreach (Node *node, mesh->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + if (shader->has_displacement && shader->get_displacement_method() == DISPLACE_TRUE) { need_recompute_vertex_normals = true; break; } @@ -241,11 +242,11 @@ bool GeometryManager::displace( for (size_t i = 0; i < num_triangles; i++) { int shader_index = mesh->shader[i]; Shader *shader = (shader_index < mesh->used_shaders.size()) ? - mesh->used_shaders[shader_index] : + static_cast<Shader *>(mesh->used_shaders[shader_index]) : scene->default_surface; tri_has_true_disp[i] = shader->has_displacement && - shader->displacement_method == DISPLACE_TRUE; + shader->get_displacement_method() == DISPLACE_TRUE; } /* static vertex normals */ diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp index 3d72b2fab91..7408ee2dbdf 100644 --- a/intern/cycles/render/mesh_subdivision.cpp +++ b/intern/cycles/render/mesh_subdivision.cpp @@ -46,13 +46,11 @@ template<> bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner, ccl::Mesh const &mesh) { - setNumBaseVertices(refiner, mesh.verts.size()); - setNumBaseFaces(refiner, mesh.subd_faces.size()); + setNumBaseVertices(refiner, mesh.get_verts().size()); + setNumBaseFaces(refiner, mesh.get_num_subd_faces()); - const ccl::Mesh::SubdFace *face = mesh.subd_faces.data(); - - for (int i = 0; i < mesh.subd_faces.size(); i++, face++) { - setNumBaseFaceVertices(refiner, i, face->num_corners); + for (int i = 0; i < mesh.get_num_subd_faces(); i++) { + setNumBaseFaceVertices(refiner, i, mesh.get_subd_num_corners()[i]); } return true; @@ -62,14 +60,17 @@ template<> bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner, ccl::Mesh const &mesh) { - const ccl::Mesh::SubdFace *face = mesh.subd_faces.data(); + const ccl::array<int> &subd_face_corners = mesh.get_subd_face_corners(); + const ccl::array<int> &subd_start_corner = mesh.get_subd_start_corner(); + const ccl::array<int> &subd_num_corners = mesh.get_subd_num_corners(); - for (int i = 0; i < mesh.subd_faces.size(); i++, face++) { + for (int i = 0; i < mesh.get_num_subd_faces(); i++) { IndexArray face_verts = getBaseFaceVertices(refiner, i); - int *corner = &mesh.subd_face_corners[face->start_corner]; + int start_corner = subd_start_corner[i]; + int *corner = &subd_face_corners[start_corner]; - for (int j = 0; j < face->num_corners; j++, corner++) { + for (int j = 0; j < subd_num_corners[i]; j++, corner++) { face_verts[j] = *corner; } } @@ -81,17 +82,18 @@ template<> bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner, ccl::Mesh const &mesh) { - const ccl::Mesh::SubdEdgeCrease *crease = mesh.subd_creases.data(); + size_t num_creases = mesh.get_subd_creases_weight().size(); - for (int i = 0; i < mesh.subd_creases.size(); i++, crease++) { - Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]); + for (int i = 0; i < num_creases; i++) { + ccl::Mesh::SubdEdgeCrease crease = mesh.get_subd_crease(i); + Index edge = findBaseEdge(refiner, crease.v[0], crease.v[1]); if (edge != INDEX_INVALID) { - setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f); + setBaseEdgeSharpness(refiner, edge, crease.crease * 10.0f); } } - for (int i = 0; i < mesh.verts.size(); i++) { + for (int i = 0; i < mesh.get_verts().size(); i++) { ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i); if (vert_edges.size() == 2) { @@ -203,8 +205,8 @@ class OsdData { int num_local_points = patch_table->GetNumLocalPoints(); verts.resize(num_refiner_verts + num_local_points); - for (int i = 0; i < mesh->verts.size(); i++) { - verts[i].value = mesh->verts[i]; + for (int i = 0; i < mesh->get_verts().size(); i++) { + verts[i].value = mesh->get_verts()[i]; } OsdValue<float3> *src = verts.data(); @@ -278,16 +280,17 @@ class OsdData { { /* loop over all edges to find longest in screen space */ const Far::TopologyLevel &level = refiner->GetLevel(0); - Transform objecttoworld = mesh->subd_params->objecttoworld; - Camera *cam = mesh->subd_params->camera; + const SubdParams *subd_params = mesh->get_subd_params(); + Transform objecttoworld = subd_params->objecttoworld; + Camera *cam = subd_params->camera; float longest_edge = 0.0f; for (size_t i = 0; i < level.GetNumEdges(); i++) { Far::ConstIndexArray verts = level.GetEdgeVertices(i); - float3 a = mesh->verts[verts[0]]; - float3 b = mesh->verts[verts[1]]; + float3 a = mesh->get_verts()[verts[0]]; + float3 b = mesh->get_verts()[verts[1]]; float edge_len; @@ -305,7 +308,7 @@ class OsdData { } /* calculate isolation level */ - int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f); + int isolation = (int)(log2f(max(longest_edge / subd_params->dicing_rate, 1.0f)) + 1.0f); return min(isolation, 10); } @@ -368,12 +371,16 @@ struct OsdPatch : Patch { void Mesh::tessellate(DiagSplit *split) { + /* reset the number of subdivision vertices, in case the Mesh was not cleared + * between calls or data updates */ + num_subd_verts = 0; + #ifdef WITH_OPENSUBDIV OsdData osd_data; bool need_packed_patch_table = false; if (subdivision_type == SUBDIVISION_CATMULL_CLARK) { - if (subd_faces.size()) { + if (get_num_subd_faces()) { osd_data.build_from_mesh(this); } } @@ -391,7 +398,7 @@ void Mesh::tessellate(DiagSplit *split) } } - int num_faces = subd_faces.size(); + int num_faces = get_num_subd_faces(); Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL); float3 *vN = (attr_vN) ? attr_vN->data_float3() : NULL; @@ -399,7 +406,7 @@ void Mesh::tessellate(DiagSplit *split) /* count patches */ int num_patches = 0; for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (face.is_quad()) { num_patches++; @@ -416,7 +423,7 @@ void Mesh::tessellate(DiagSplit *split) OsdPatch *patch = osd_patches.data(); for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (face.is_quad()) { patch->patch_index = face.ptex_offset; @@ -444,7 +451,7 @@ void Mesh::tessellate(DiagSplit *split) LinearQuadPatch *patch = linear_patches.data(); for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (face.is_quad()) { float3 *hull = patch->hull; @@ -542,7 +549,7 @@ void Mesh::tessellate(DiagSplit *split) /* keep subdivision for corner attributes disabled for now */ attr.flags &= ~ATTR_SUBDIVIDED; } - else if (subd_faces.size()) { + else if (get_num_subd_faces()) { osd_data.subdivide_attribute(attr); need_packed_patch_table = true; @@ -558,7 +565,7 @@ void Mesh::tessellate(DiagSplit *split) switch (attr.element) { case ATTR_ELEMENT_VERTEX: { for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (!face.is_quad()) { char *center = data + (verts.size() - num_subd_verts + ngons) * stride; @@ -581,7 +588,7 @@ void Mesh::tessellate(DiagSplit *split) } break; case ATTR_ELEMENT_CORNER: { for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (!face.is_quad()) { char *center = data + (subd_face_corners.size() + ngons) * stride; @@ -600,7 +607,7 @@ void Mesh::tessellate(DiagSplit *split) } break; case ATTR_ELEMENT_CORNER_BYTE: { for (int f = 0; f < num_faces; f++) { - SubdFace &face = subd_faces[f]; + SubdFace face = get_subd_face(f); if (!face.is_quad()) { uchar *center = (uchar *)data + (subd_face_corners.size() + ngons) * stride; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 5e21ad15cc8..b59dd124040 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -247,6 +247,9 @@ NODE_DEFINE(ImageTextureNode) SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f); + SOCKET_INT_ARRAY(tiles, "Tiles", array<int>()); + SOCKET_BOOLEAN(animated, "Animated", false); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV); SOCKET_OUT_COLOR(color, "Color"); @@ -259,7 +262,7 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type) { colorspace = u_colorspace_raw; animated = false; - tiles.push_back(1001); + tiles.push_back_slow(1001); } ShaderNode *ImageTextureNode::clone(ShaderGraph *graph) const @@ -286,7 +289,7 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph) * 1001 tile, so there's no point in loading any others. */ if (projection == NODE_IMAGE_PROJ_BOX) { tiles.clear(); - tiles.push_back(1001); + tiles.push_back_slow(1001); return; } @@ -308,7 +311,7 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph) ShaderNode *node = vector_in->link->parent; if (node->type == UVMapNode::node_type) { UVMapNode *uvmap = (UVMapNode *)node; - attribute = uvmap->attribute; + attribute = uvmap->get_attribute(); } else if (node->type == TextureCoordinateNode::node_type) { if (vector_in->link != node->output("UV")) { @@ -325,20 +328,21 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph) * be to have a cache in each mesh that is indexed by attribute. * Additionally, building a graph-to-meshes list once could help. */ foreach (Geometry *geom, scene->geometry) { - foreach (Shader *shader, geom->used_shaders) { + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->graph == graph) { geom->get_uv_tiles(attribute, used_tiles); } } } - ccl::vector<int> new_tiles; + array<int> new_tiles; foreach (int tile, tiles) { if (used_tiles.count(tile)) { - new_tiles.push_back(tile); + new_tiles.push_back_slow(tile); } } - tiles.swap(new_tiles); + tiles.steal_data(new_tiles); } void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -511,6 +515,8 @@ NODE_DEFINE(EnvironmentTextureNode) projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL); SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR); + SOCKET_BOOLEAN(animated, "Animated", false); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); SOCKET_OUT_COLOR(color, "Color"); @@ -790,7 +796,7 @@ NODE_DEFINE(SkyTextureNode) type_enum.insert("preetham", NODE_SKY_PREETHAM); type_enum.insert("hosek_wilkie", NODE_SKY_HOSEK); type_enum.insert("nishita_improved", NODE_SKY_NISHITA); - SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NISHITA); + SOCKET_ENUM(sky_type, "Type", type_enum, NODE_SKY_NISHITA); SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f)); SOCKET_FLOAT(turbidity, "Turbidity", 2.2f); @@ -823,11 +829,11 @@ void SkyTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); SunSky sunsky; - if (type == NODE_SKY_PREETHAM) + if (sky_type == NODE_SKY_PREETHAM) sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); - else if (type == NODE_SKY_HOSEK) + else if (sky_type == NODE_SKY_HOSEK) sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); - else if (type == NODE_SKY_NISHITA) { + else if (sky_type == NODE_SKY_NISHITA) { /* Clamp altitude to reasonable values. * Below 1m causes numerical issues and above 60km is space. */ float clamped_altitude = clamp(altitude, 1.0f, 59999.0f); @@ -860,9 +866,9 @@ void SkyTextureNode::compile(SVMCompiler &compiler) int vector_offset = tex_mapping.compile_begin(compiler, vector_in); compiler.stack_assign(color_out); - compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type); + compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_type); /* nishita doesn't need this data */ - if (type != NODE_SKY_NISHITA) { + if (sky_type != NODE_SKY_NISHITA) { compiler.add_node(__float_as_uint(sunsky.phi), __float_as_uint(sunsky.theta), __float_as_uint(sunsky.radiance_x), @@ -919,11 +925,11 @@ void SkyTextureNode::compile(OSLCompiler &compiler) tex_mapping.compile(compiler); SunSky sunsky; - if (type == NODE_SKY_PREETHAM) + if (sky_type == NODE_SKY_PREETHAM) sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); - else if (type == NODE_SKY_HOSEK) + else if (sky_type == NODE_SKY_HOSEK) sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); - else if (type == NODE_SKY_NISHITA) { + else if (sky_type == NODE_SKY_NISHITA) { /* Clamp altitude to reasonable values. * Below 1m causes numerical issues and above 60km is space. */ float clamped_altitude = clamp(altitude, 1.0f, 59999.0f); @@ -953,7 +959,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler) else assert(false); - compiler.parameter(this, "type"); + compiler.parameter(this, "sky_type"); compiler.parameter("theta", sunsky.theta); compiler.parameter("phi", sunsky.phi); compiler.parameter_color("radiance", @@ -963,7 +969,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler) compiler.parameter_array("config_z", sunsky.config_z, 9); compiler.parameter_array("nishita_data", sunsky.nishita_data, 10); /* nishita texture */ - if (type == NODE_SKY_NISHITA) { + if (sky_type == NODE_SKY_NISHITA) { compiler.parameter_texture("filename", handle.svm_slot()); } compiler.add(this, "node_sky_texture"); @@ -985,7 +991,7 @@ NODE_DEFINE(GradientTextureNode) type_enum.insert("radial", NODE_BLEND_RADIAL); type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE); type_enum.insert("spherical", NODE_BLEND_SPHERICAL); - SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR); + SOCKET_ENUM(gradient_type, "Type", type_enum, NODE_BLEND_LINEAR); SOCKET_IN_POINT( vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); @@ -1009,7 +1015,7 @@ void GradientTextureNode::compile(SVMCompiler &compiler) int vector_offset = tex_mapping.compile_begin(compiler, vector_in); compiler.add_node(NODE_TEX_GRADIENT, - compiler.encode_uchar4(type, + compiler.encode_uchar4(gradient_type, vector_offset, compiler.stack_assign_if_linked(fac_out), compiler.stack_assign_if_linked(color_out))); @@ -1021,7 +1027,7 @@ void GradientTextureNode::compile(OSLCompiler &compiler) { tex_mapping.compile(compiler); - compiler.parameter(this, "type"); + compiler.parameter(this, "gradient_type"); compiler.add(this, "node_gradient_texture"); } @@ -1369,7 +1375,7 @@ NODE_DEFINE(MusgraveTextureNode) type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL); type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL); type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN); - SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM); + SOCKET_ENUM(musgrave_type, "Type", type_enum, NODE_MUSGRAVE_FBM); SOCKET_IN_POINT( vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); @@ -1414,7 +1420,7 @@ void MusgraveTextureNode::compile(SVMCompiler &compiler) compiler.add_node( NODE_TEX_MUSGRAVE, - compiler.encode_uchar4(type, dimensions, vector_stack_offset, w_stack_offset), + compiler.encode_uchar4(musgrave_type, dimensions, vector_stack_offset, w_stack_offset), compiler.encode_uchar4(scale_stack_offset, detail_stack_offset, dimension_stack_offset, @@ -1431,7 +1437,7 @@ void MusgraveTextureNode::compile(OSLCompiler &compiler) { tex_mapping.compile(compiler); - compiler.parameter(this, "type"); + compiler.parameter(this, "musgrave_type"); compiler.parameter(this, "dimensions"); compiler.add(this, "node_musgrave_texture"); } @@ -1447,7 +1453,7 @@ NODE_DEFINE(WaveTextureNode) static NodeEnum type_enum; type_enum.insert("bands", NODE_WAVE_BANDS); type_enum.insert("rings", NODE_WAVE_RINGS); - SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS); + SOCKET_ENUM(wave_type, "Type", type_enum, NODE_WAVE_BANDS); static NodeEnum bands_direction_enum; bands_direction_enum.insert("x", NODE_WAVE_BANDS_DIRECTION_X); @@ -1504,7 +1510,7 @@ void WaveTextureNode::compile(SVMCompiler &compiler) int vector_offset = tex_mapping.compile_begin(compiler, vector_in); compiler.add_node(NODE_TEX_WAVE, - compiler.encode_uchar4(type, bands_direction, rings_direction, profile), + compiler.encode_uchar4(wave_type, bands_direction, rings_direction, profile), compiler.encode_uchar4(vector_offset, compiler.stack_assign_if_linked(scale_in), compiler.stack_assign_if_linked(distortion_in)), @@ -1531,7 +1537,7 @@ void WaveTextureNode::compile(OSLCompiler &compiler) { tex_mapping.compile(compiler); - compiler.parameter(this, "type"); + compiler.parameter(this, "wave_type"); compiler.parameter(this, "bands_direction"); compiler.parameter(this, "rings_direction"); compiler.parameter(this, "profile"); @@ -1926,7 +1932,7 @@ NODE_DEFINE(MappingNode) type_enum.insert("texture", NODE_MAPPING_TYPE_TEXTURE); type_enum.insert("vector", NODE_MAPPING_TYPE_VECTOR); type_enum.insert("normal", NODE_MAPPING_TYPE_NORMAL); - SOCKET_ENUM(type, "Type", type_enum, NODE_MAPPING_TYPE_POINT); + SOCKET_ENUM(mapping_type, "Type", type_enum, NODE_MAPPING_TYPE_POINT); SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_IN_POINT(location, "Location", make_float3(0.0f, 0.0f, 0.0f)); @@ -1945,11 +1951,11 @@ MappingNode::MappingNode() : ShaderNode(node_type) void MappingNode::constant_fold(const ConstantFolder &folder) { if (folder.all_inputs_constant()) { - float3 result = svm_mapping((NodeMappingType)type, vector, location, rotation, scale); + float3 result = svm_mapping((NodeMappingType)mapping_type, vector, location, rotation, scale); folder.make_constant(result); } else { - folder.fold_mapping((NodeMappingType)type); + folder.fold_mapping((NodeMappingType)mapping_type); } } @@ -1969,7 +1975,7 @@ void MappingNode::compile(SVMCompiler &compiler) compiler.add_node( NODE_MAPPING, - type, + mapping_type, compiler.encode_uchar4( vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset), result_stack_offset); @@ -1977,7 +1983,7 @@ void MappingNode::compile(SVMCompiler &compiler) void MappingNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "mapping_type"); compiler.add(this, "node_mapping"); } @@ -2385,7 +2391,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene) } Integrator *integrator = scene->integrator; ShaderInput *roughness_input = input("Roughness"); - if (integrator->filter_glossy == 0.0f) { + if (integrator->get_filter_glossy() == 0.0f) { /* Fallback to Sharp closure for Roughness close to 0. * Note: Keep the epsilon in sync with kernel! */ @@ -2478,7 +2484,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene) } Integrator *integrator = scene->integrator; ShaderInput *roughness_input = input("Roughness"); - if (integrator->filter_glossy == 0.0f) { + if (integrator->get_filter_glossy() == 0.0f) { /* Fallback to Sharp closure for Roughness close to 0. * Note: Keep the epsilon in sync with kernel! */ @@ -2571,7 +2577,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene) } Integrator *integrator = scene->integrator; ShaderInput *roughness_input = input("Roughness"); - if (integrator->filter_glossy == 0.0f) { + if (integrator->get_filter_glossy() == 0.0f) { /* Fallback to Sharp closure for Roughness close to 0. * Note: Keep the epsilon in sync with kernel! */ @@ -3754,7 +3760,7 @@ void GeometryNode::compile(SVMCompiler &compiler) if (!out->links.empty()) { if (compiler.output_type() != SHADER_TYPE_VOLUME) { compiler.add_node( - attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_FLOAT); + attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT); } else { compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out)); @@ -3764,8 +3770,10 @@ void GeometryNode::compile(SVMCompiler &compiler) out = output("Random Per Island"); if (!out->links.empty()) { if (compiler.output_type() != SHADER_TYPE_VOLUME) { - compiler.add_node( - attr_node, ATTR_STD_RANDOM_PER_ISLAND, compiler.stack_assign(out), NODE_ATTR_FLOAT); + compiler.add_node(attr_node, + ATTR_STD_RANDOM_PER_ISLAND, + compiler.stack_assign(out), + NODE_ATTR_OUTPUT_FLOAT); } else { compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out)); @@ -3883,7 +3891,7 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler) } else { int attr = compiler.attribute(ATTR_STD_GENERATED); - compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3); + compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3); } } } @@ -3900,7 +3908,7 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler) } else { int attr = compiler.attribute(ATTR_STD_UV); - compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3); + compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3); } } @@ -4018,7 +4026,7 @@ void UVMapNode::compile(SVMCompiler &compiler) else attr = compiler.attribute(ATTR_STD_UV); - compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3); + compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3); } } } @@ -4414,7 +4422,7 @@ void HairInfoNode::compile(SVMCompiler &compiler) out = output("Intercept"); if (!out->links.empty()) { int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT); - compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT); + compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT); } out = output("Thickness"); @@ -4435,7 +4443,7 @@ void HairInfoNode::compile(SVMCompiler &compiler) out = output("Random"); if (!out->links.empty()) { int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM); - compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT); + compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT); } } @@ -4490,7 +4498,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *color_out = output("Color"); if (!color_out->links.empty()) { AttributeNode *attr = graph->create_node<AttributeNode>(); - attr->attribute = "color"; + attr->set_attribute(ustring("color")); graph->add(attr); graph->relink(color_out, attr->output("Color")); } @@ -4498,7 +4506,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *density_out = output("Density"); if (!density_out->links.empty()) { AttributeNode *attr = graph->create_node<AttributeNode>(); - attr->attribute = "density"; + attr->set_attribute(ustring("density")); graph->add(attr); graph->relink(density_out, attr->output("Fac")); } @@ -4506,7 +4514,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *flame_out = output("Flame"); if (!flame_out->links.empty()) { AttributeNode *attr = graph->create_node<AttributeNode>(); - attr->attribute = "flame"; + attr->set_attribute(ustring("flame")); graph->add(attr); graph->relink(flame_out, attr->output("Fac")); } @@ -4514,7 +4522,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *temperature_out = output("Temperature"); if (!temperature_out->links.empty()) { AttributeNode *attr = graph->create_node<AttributeNode>(); - attr->attribute = "temperature"; + attr->set_attribute(ustring("temperature")); graph->add(attr); graph->relink(temperature_out, attr->output("Fac")); } @@ -4891,7 +4899,7 @@ NODE_DEFINE(MixNode) type_enum.insert("color", NODE_MIX_COLOR); type_enum.insert("soft_light", NODE_MIX_SOFT); type_enum.insert("linear_light", NODE_MIX_LINEAR); - SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND); + SOCKET_ENUM(mix_type, "Type", type_enum, NODE_MIX_BLEND); SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); @@ -4919,7 +4927,7 @@ void MixNode::compile(SVMCompiler &compiler) compiler.stack_assign(fac_in), compiler.stack_assign(color1_in), compiler.stack_assign(color2_in)); - compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out)); + compiler.add_node(NODE_MIX, mix_type, compiler.stack_assign(color_out)); if (use_clamp) { compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out)); @@ -4929,7 +4937,7 @@ void MixNode::compile(SVMCompiler &compiler) void MixNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "mix_type"); compiler.parameter(this, "use_clamp"); compiler.add(this, "node_mix"); } @@ -4937,10 +4945,10 @@ void MixNode::compile(OSLCompiler &compiler) void MixNode::constant_fold(const ConstantFolder &folder) { if (folder.all_inputs_constant()) { - folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp); + folder.make_constant_clamp(svm_mix(mix_type, fac, color1, color2), use_clamp); } else { - folder.fold_mix(type, use_clamp); + folder.fold_mix(mix_type, use_clamp); } } @@ -5397,6 +5405,7 @@ NODE_DEFINE(AttributeNode) SOCKET_OUT_COLOR(color, "Color"); SOCKET_OUT_VECTOR(vector, "Vector"); SOCKET_OUT_FLOAT(fac, "Fac"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); return type; } @@ -5410,8 +5419,10 @@ void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes) ShaderOutput *color_out = output("Color"); ShaderOutput *vector_out = output("Vector"); ShaderOutput *fac_out = output("Fac"); + ShaderOutput *alpha_out = output("Alpha"); - if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) { + if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty() || + !alpha_out->links.empty()) { attributes->add_standard(attribute); } @@ -5427,6 +5438,7 @@ void AttributeNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *vector_out = output("Vector"); ShaderOutput *fac_out = output("Fac"); + ShaderOutput *alpha_out = output("Alpha"); ShaderNodeType attr_node = NODE_ATTR; int attr = compiler.attribute_standard(attribute); @@ -5437,15 +5449,22 @@ void AttributeNode::compile(SVMCompiler &compiler) if (!color_out->links.empty() || !vector_out->links.empty()) { if (!color_out->links.empty()) { - compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3); + compiler.add_node( + attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3); } if (!vector_out->links.empty()) { - compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3); + compiler.add_node( + attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3); } } if (!fac_out->links.empty()) { - compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT); + compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT); + } + + if (!alpha_out->links.empty()) { + compiler.add_node( + attr_node, attr, compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA); } } @@ -5759,7 +5778,7 @@ NODE_DEFINE(MapRangeNode) type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED); type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP); type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP); - SOCKET_ENUM(type, "Type", type_enum, NODE_MAP_RANGE_LINEAR); + SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR); SOCKET_IN_FLOAT(value, "Value", 1.0f); SOCKET_IN_FLOAT(from_min, "From Min", 0.0f); @@ -5784,7 +5803,7 @@ void MapRangeNode::expand(ShaderGraph *graph) ShaderOutput *result_out = output("Result"); if (!result_out->links.empty()) { ClampNode *clamp_node = graph->create_node<ClampNode>(); - clamp_node->type = NODE_CLAMP_RANGE; + clamp_node->set_clamp_type(NODE_CLAMP_RANGE); graph->add(clamp_node); graph->relink(result_out, clamp_node->output("Result")); graph->connect(result_out, clamp_node->input("Value")); @@ -5792,13 +5811,13 @@ void MapRangeNode::expand(ShaderGraph *graph) graph->connect(input("To Min")->link, clamp_node->input("Min")); } else { - clamp_node->min = to_min; + clamp_node->set_min(to_min); } if (input("To Max")->link) { graph->connect(input("To Max")->link, clamp_node->input("Max")); } else { - clamp_node->max = to_max; + clamp_node->set_max(to_max); } } } @@ -5827,7 +5846,7 @@ void MapRangeNode::compile(SVMCompiler &compiler) value_stack_offset, compiler.encode_uchar4( from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset), - compiler.encode_uchar4(type, steps_stack_offset, result_stack_offset)); + compiler.encode_uchar4(range_type, steps_stack_offset, result_stack_offset)); compiler.add_node(__float_as_int(from_min), __float_as_int(from_max), @@ -5838,7 +5857,7 @@ void MapRangeNode::compile(SVMCompiler &compiler) void MapRangeNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "range_type"); compiler.add(this, "node_map_range"); } @@ -5851,7 +5870,7 @@ NODE_DEFINE(ClampNode) static NodeEnum type_enum; type_enum.insert("minmax", NODE_CLAMP_MINMAX); type_enum.insert("range", NODE_CLAMP_RANGE); - SOCKET_ENUM(type, "Type", type_enum, NODE_CLAMP_MINMAX); + SOCKET_ENUM(clamp_type, "Type", type_enum, NODE_CLAMP_MINMAX); SOCKET_IN_FLOAT(value, "Value", 1.0f); SOCKET_IN_FLOAT(min, "Min", 0.0f); @@ -5869,7 +5888,7 @@ ClampNode::ClampNode() : ShaderNode(node_type) void ClampNode::constant_fold(const ConstantFolder &folder) { if (folder.all_inputs_constant()) { - if (type == NODE_CLAMP_RANGE && (min > max)) { + if (clamp_type == NODE_CLAMP_RANGE && (min > max)) { folder.make_constant(clamp(value, max, min)); } else { @@ -5892,14 +5911,14 @@ void ClampNode::compile(SVMCompiler &compiler) compiler.add_node(NODE_CLAMP, value_stack_offset, - compiler.encode_uchar4(min_stack_offset, max_stack_offset, type), + compiler.encode_uchar4(min_stack_offset, max_stack_offset, clamp_type), result_stack_offset); compiler.add_node(__float_as_int(min), __float_as_int(max)); } void ClampNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "clamp_type"); compiler.add(this, "node_clamp"); } @@ -6002,7 +6021,7 @@ NODE_DEFINE(MathNode) type_enum.insert("smoothmin", NODE_MATH_SMOOTH_MIN); type_enum.insert("smoothmax", NODE_MATH_SMOOTH_MAX); type_enum.insert("compare", NODE_MATH_COMPARE); - SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD); + SOCKET_ENUM(math_type, "Type", type_enum, NODE_MATH_ADD); SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); @@ -6025,9 +6044,9 @@ void MathNode::expand(ShaderGraph *graph) ShaderOutput *result_out = output("Value"); if (!result_out->links.empty()) { ClampNode *clamp_node = graph->create_node<ClampNode>(); - clamp_node->type = NODE_CLAMP_MINMAX; - clamp_node->min = 0.0f; - clamp_node->max = 1.0f; + clamp_node->set_clamp_type(NODE_CLAMP_MINMAX); + clamp_node->set_min(0.0f); + clamp_node->set_max(1.0f); graph->add(clamp_node); graph->relink(result_out, clamp_node->output("Result")); graph->connect(result_out, clamp_node->input("Value")); @@ -6038,10 +6057,10 @@ void MathNode::expand(ShaderGraph *graph) void MathNode::constant_fold(const ConstantFolder &folder) { if (folder.all_inputs_constant()) { - folder.make_constant(svm_math(type, value1, value2, value3)); + folder.make_constant(svm_math(math_type, value1, value2, value3)); } else { - folder.fold_math(type); + folder.fold_math(math_type); } } @@ -6059,14 +6078,14 @@ void MathNode::compile(SVMCompiler &compiler) compiler.add_node( NODE_MATH, - type, + math_type, compiler.encode_uchar4(value1_stack_offset, value2_stack_offset, value3_stack_offset), value_stack_offset); } void MathNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "math_type"); compiler.add(this, "node_math"); } @@ -6105,7 +6124,7 @@ NODE_DEFINE(VectorMathNode) type_enum.insert("sine", NODE_VECTOR_MATH_SINE); type_enum.insert("cosine", NODE_VECTOR_MATH_COSINE); type_enum.insert("tangent", NODE_VECTOR_MATH_TANGENT); - SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD); + SOCKET_ENUM(math_type, "Type", type_enum, NODE_VECTOR_MATH_ADD); SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f)); @@ -6128,7 +6147,7 @@ void VectorMathNode::constant_fold(const ConstantFolder &folder) float3 vector = make_float3(0.0f, 0.0f, 0.0f); if (folder.all_inputs_constant()) { - svm_vector_math(&value, &vector, type, vector1, vector2, vector3, scale); + svm_vector_math(&value, &vector, math_type, vector1, vector2, vector3, scale); if (folder.output == output("Value")) { folder.make_constant(value); } @@ -6137,7 +6156,7 @@ void VectorMathNode::constant_fold(const ConstantFolder &folder) } } else { - folder.fold_vector_math(type); + folder.fold_vector_math(math_type); } } @@ -6156,12 +6175,12 @@ void VectorMathNode::compile(SVMCompiler &compiler) int vector_stack_offset = compiler.stack_assign_if_linked(vector_out); /* 3 Vector Operators */ - if (type == NODE_VECTOR_MATH_WRAP) { + if (math_type == NODE_VECTOR_MATH_WRAP) { ShaderInput *vector3_in = input("Vector3"); int vector3_stack_offset = compiler.stack_assign(vector3_in); compiler.add_node( NODE_VECTOR_MATH, - type, + math_type, compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset), compiler.encode_uchar4(value_stack_offset, vector_stack_offset)); compiler.add_node(vector3_stack_offset); @@ -6169,7 +6188,7 @@ void VectorMathNode::compile(SVMCompiler &compiler) else { compiler.add_node( NODE_VECTOR_MATH, - type, + math_type, compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset), compiler.encode_uchar4(value_stack_offset, vector_stack_offset)); } @@ -6177,7 +6196,7 @@ void VectorMathNode::compile(SVMCompiler &compiler) void VectorMathNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "math_type"); compiler.add(this, "node_vector_math"); } @@ -6193,7 +6212,7 @@ NODE_DEFINE(VectorRotateNode) type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y); type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z); type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ); - SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS); + SOCKET_ENUM(rotate_type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS); SOCKET_BOOLEAN(invert, "Invert", false); @@ -6220,19 +6239,20 @@ void VectorRotateNode::compile(SVMCompiler &compiler) ShaderInput *angle_in = input("Angle"); ShaderOutput *vector_out = output("Vector"); - compiler.add_node( - NODE_VECTOR_ROTATE, - compiler.encode_uchar4( - type, compiler.stack_assign(vector_in), compiler.stack_assign(rotation_in), invert), - compiler.encode_uchar4(compiler.stack_assign(center_in), - compiler.stack_assign(axis_in), - compiler.stack_assign(angle_in)), - compiler.stack_assign(vector_out)); + compiler.add_node(NODE_VECTOR_ROTATE, + compiler.encode_uchar4(rotate_type, + compiler.stack_assign(vector_in), + compiler.stack_assign(rotation_in), + invert), + compiler.encode_uchar4(compiler.stack_assign(center_in), + compiler.stack_assign(axis_in), + compiler.stack_assign(angle_in)), + compiler.stack_assign(vector_out)); } void VectorRotateNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "rotate_type"); compiler.parameter(this, "invert"); compiler.add(this, "node_vector_rotate"); } @@ -6247,7 +6267,7 @@ NODE_DEFINE(VectorTransformNode) type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR); type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT); type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL); - SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR); + SOCKET_ENUM(transform_type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR); static NodeEnum space_enum; space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD); @@ -6273,13 +6293,13 @@ void VectorTransformNode::compile(SVMCompiler &compiler) compiler.add_node( NODE_VECTOR_TRANSFORM, - compiler.encode_uchar4(type, convert_from, convert_to), + compiler.encode_uchar4(transform_type, convert_from, convert_to), compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out))); } void VectorTransformNode::compile(OSLCompiler &compiler) { - compiler.parameter(this, "type"); + compiler.parameter(this, "transform_type"); compiler.parameter(this, "convert_from"); compiler.parameter(this, "convert_to"); compiler.add(this, "node_vector_transform"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 62dd9d843a8..4d51b4fccaf 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -70,6 +70,17 @@ class TextureNode : public ShaderNode { { } TextureMapping tex_mapping; + NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, translation) + NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, rotation) + NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, scale) + NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, min) + NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, max) + NODE_SOCKET_API_STRUCT_MEMBER(bool, tex_mapping, use_minmax) + NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Type, tex_mapping, type) + NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, x_mapping) + NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, y_mapping) + NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, z_mapping) + NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Projection, tex_mapping, projection) }; /* Any node which uses image manager's slot should be a subclass of this one. */ @@ -108,16 +119,16 @@ class ImageTextureNode : public ImageSlotTextureNode { ImageParams image_params() const; /* Parameters. */ - ustring filename; - ustring colorspace; - ImageAlphaType alpha_type; - NodeImageProjection projection; - InterpolationType interpolation; - ExtensionType extension; - float projection_blend; - bool animated; - float3 vector; - ccl::vector<int> tiles; + NODE_SOCKET_API(ustring, filename) + NODE_SOCKET_API(ustring, colorspace) + NODE_SOCKET_API(ImageAlphaType, alpha_type) + NODE_SOCKET_API(NodeImageProjection, projection) + NODE_SOCKET_API(InterpolationType, interpolation) + NODE_SOCKET_API(ExtensionType, extension) + NODE_SOCKET_API(float, projection_blend) + NODE_SOCKET_API(bool, animated) + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(array<int>, tiles) protected: void cull_tiles(Scene *scene, ShaderGraph *graph); @@ -146,13 +157,13 @@ class EnvironmentTextureNode : public ImageSlotTextureNode { ImageParams image_params() const; /* Parameters. */ - ustring filename; - ustring colorspace; - ImageAlphaType alpha_type; - NodeEnvironmentProjection projection; - InterpolationType interpolation; - bool animated; - float3 vector; + NODE_SOCKET_API(ustring, filename) + NODE_SOCKET_API(ustring, colorspace) + NODE_SOCKET_API(ImageAlphaType, alpha_type) + NODE_SOCKET_API(NodeEnvironmentProjection, projection) + NODE_SOCKET_API(InterpolationType, interpolation) + NODE_SOCKET_API(bool, animated) + NODE_SOCKET_API(float3, vector) }; class SkyTextureNode : public TextureNode { @@ -164,20 +175,20 @@ class SkyTextureNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - NodeSkyType type; - float3 sun_direction; - float turbidity; - float ground_albedo; - bool sun_disc; - float sun_size; - float sun_intensity; - float sun_elevation; - float sun_rotation; - float altitude; - float air_density; - float dust_density; - float ozone_density; - float3 vector; + NODE_SOCKET_API(NodeSkyType, sky_type) + NODE_SOCKET_API(float3, sun_direction) + NODE_SOCKET_API(float, turbidity) + NODE_SOCKET_API(float, ground_albedo) + NODE_SOCKET_API(bool, sun_disc) + NODE_SOCKET_API(float, sun_size) + NODE_SOCKET_API(float, sun_intensity) + NODE_SOCKET_API(float, sun_elevation) + NODE_SOCKET_API(float, sun_rotation) + NODE_SOCKET_API(float, altitude) + NODE_SOCKET_API(float, air_density) + NODE_SOCKET_API(float, dust_density) + NODE_SOCKET_API(float, ozone_density) + NODE_SOCKET_API(float3, vector) ImageHandle handle; float get_sun_size() @@ -191,10 +202,10 @@ class OutputNode : public ShaderNode { public: SHADER_NODE_CLASS(OutputNode) - void *surface; - void *volume; - float3 displacement; - float3 normal; + NODE_SOCKET_API(Node *, surface) + NODE_SOCKET_API(Node *, volume) + NODE_SOCKET_API(float3, displacement) + NODE_SOCKET_API(float3, normal) /* Don't allow output node de-duplication. */ virtual bool equals(const ShaderNode & /*other*/) @@ -208,10 +219,10 @@ class OutputAOVNode : public ShaderNode { SHADER_NODE_CLASS(OutputAOVNode) virtual void simplify_settings(Scene *scene); - float value; - float3 color; + NODE_SOCKET_API(float, value) + NODE_SOCKET_API(float3, color) - ustring name; + NODE_SOCKET_API(ustring, name) virtual int get_group() { @@ -237,17 +248,21 @@ class GradientTextureNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - NodeGradientType type; - float3 vector; + NODE_SOCKET_API(NodeGradientType, gradient_type) + NODE_SOCKET_API(float3, vector) }; class NoiseTextureNode : public TextureNode { public: SHADER_NODE_CLASS(NoiseTextureNode) - int dimensions; - float w, scale, detail, roughness, distortion; - float3 vector; + NODE_SOCKET_API(int, dimensions) + NODE_SOCKET_API(float, w) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, detail) + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(float, distortion) + NODE_SOCKET_API(float3, vector) }; class VoronoiTextureNode : public TextureNode { @@ -271,11 +286,15 @@ class VoronoiTextureNode : public TextureNode { return result; } - int dimensions; - NodeVoronoiDistanceMetric metric; - NodeVoronoiFeature feature; - float w, scale, exponent, smoothness, randomness; - float3 vector; + NODE_SOCKET_API(int, dimensions) + NODE_SOCKET_API(NodeVoronoiDistanceMetric, metric) + NODE_SOCKET_API(NodeVoronoiFeature, feature) + NODE_SOCKET_API(float, w) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, exponent) + NODE_SOCKET_API(float, smoothness) + NODE_SOCKET_API(float, randomness) + NODE_SOCKET_API(float3, vector) }; class MusgraveTextureNode : public TextureNode { @@ -287,10 +306,16 @@ class MusgraveTextureNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - int dimensions; - NodeMusgraveType type; - float w, scale, detail, dimension, lacunarity, offset, gain; - float3 vector; + NODE_SOCKET_API(int, dimensions) + NODE_SOCKET_API(NodeMusgraveType, musgrave_type) + NODE_SOCKET_API(float, w) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, detail) + NODE_SOCKET_API(float, dimension) + NODE_SOCKET_API(float, lacunarity) + NODE_SOCKET_API(float, offset) + NODE_SOCKET_API(float, gain) + NODE_SOCKET_API(float3, vector) }; class WaveTextureNode : public TextureNode { @@ -302,13 +327,18 @@ class WaveTextureNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - NodeWaveType type; - NodeWaveBandsDirection bands_direction; - NodeWaveRingsDirection rings_direction; - NodeWaveProfile profile; + NODE_SOCKET_API(NodeWaveType, wave_type) + NODE_SOCKET_API(NodeWaveBandsDirection, bands_direction) + NODE_SOCKET_API(NodeWaveRingsDirection, rings_direction) + NODE_SOCKET_API(NodeWaveProfile, profile) - float scale, distortion, detail, detail_scale, detail_roughness, phase; - float3 vector; + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, distortion) + NODE_SOCKET_API(float, detail) + NODE_SOCKET_API(float, detail_scale) + NODE_SOCKET_API(float, detail_roughness) + NODE_SOCKET_API(float, phase) + NODE_SOCKET_API(float3, vector) }; class MagicTextureNode : public TextureNode { @@ -320,17 +350,20 @@ class MagicTextureNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - int depth; - float3 vector; - float scale, distortion; + NODE_SOCKET_API(int, depth) + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, distortion) }; class CheckerTextureNode : public TextureNode { public: SHADER_NODE_CLASS(CheckerTextureNode) - float3 vector, color1, color2; - float scale; + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float3, color1) + NODE_SOCKET_API(float3, color2) + NODE_SOCKET_API(float, scale) virtual int get_group() { @@ -342,12 +375,21 @@ class BrickTextureNode : public TextureNode { public: SHADER_NODE_CLASS(BrickTextureNode) - float offset, squash; - int offset_frequency, squash_frequency; - - float3 color1, color2, mortar; - float scale, mortar_size, mortar_smooth, bias, brick_width, row_height; - float3 vector; + NODE_SOCKET_API(float, offset) + NODE_SOCKET_API(float, squash) + NODE_SOCKET_API(int, offset_frequency) + NODE_SOCKET_API(int, squash_frequency) + + NODE_SOCKET_API(float3, color1) + NODE_SOCKET_API(float3, color2) + NODE_SOCKET_API(float3, mortar) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float, mortar_size) + NODE_SOCKET_API(float, mortar_smooth) + NODE_SOCKET_API(float, bias) + NODE_SOCKET_API(float, brick_width) + NODE_SOCKET_API(float, row_height) + NODE_SOCKET_API(float3, vector) virtual int get_group() { @@ -377,11 +419,11 @@ class PointDensityTextureNode : public ShaderNode { } /* Parameters. */ - ustring filename; - NodeTexVoxelSpace space; - InterpolationType interpolation; - Transform tfm; - float3 vector; + NODE_SOCKET_API(ustring, filename) + NODE_SOCKET_API(NodeTexVoxelSpace, space) + NODE_SOCKET_API(InterpolationType, interpolation) + NODE_SOCKET_API(Transform, tfm) + NODE_SOCKET_API(float3, vector) /* Runtime. */ ImageHandle handle; @@ -406,11 +448,11 @@ class IESLightNode : public TextureNode { return NODE_GROUP_LEVEL_2; } - ustring filename; - ustring ies; + NODE_SOCKET_API(ustring, filename) + NODE_SOCKET_API(ustring, ies) - float strength; - float3 vector; + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float3, vector) private: LightManager *light_manager; @@ -427,9 +469,9 @@ class WhiteNoiseTextureNode : public ShaderNode { return NODE_GROUP_LEVEL_2; } - int dimensions; - float3 vector; - float w; + NODE_SOCKET_API(int, dimensions) + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float, w) }; class MappingNode : public ShaderNode { @@ -441,8 +483,11 @@ class MappingNode : public ShaderNode { } void constant_fold(const ConstantFolder &folder); - float3 vector, location, rotation, scale; - NodeMappingType type; + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float3, location) + NODE_SOCKET_API(float3, rotation) + NODE_SOCKET_API(float3, scale) + NODE_SOCKET_API(NodeMappingType, mapping_type) }; class RGBToBWNode : public ShaderNode { @@ -450,7 +495,7 @@ class RGBToBWNode : public ShaderNode { SHADER_NODE_CLASS(RGBToBWNode) void constant_fold(const ConstantFolder &folder); - float3 color; + NODE_SOCKET_API(float3, color) }; class ConvertNode : public ShaderNode { @@ -460,6 +505,7 @@ class ConvertNode : public ShaderNode { void constant_fold(const ConstantFolder &folder); + private: SocketType::Type from, to; union { @@ -472,7 +518,6 @@ class ConvertNode : public ShaderNode { }; ustring value_string; - private: static const int MAX_TYPE = 12; static bool register_types(); static Node *create(const NodeType *type); @@ -500,6 +545,7 @@ class BsdfBaseNode : public ShaderNode { return false; } + protected: ClosureType closure; }; @@ -514,18 +560,20 @@ class BsdfNode : public BsdfBaseNode { ShaderInput *param3 = NULL, ShaderInput *param4 = NULL); - float3 color; - float3 normal; - float surface_mix_weight; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float, surface_mix_weight) }; class AnisotropicBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(AnisotropicBsdfNode) - float3 tangent; - float roughness, anisotropy, rotation; - ClosureType distribution; + NODE_SOCKET_API(float3, tangent) + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(float, anisotropy) + NODE_SOCKET_API(float, rotation) + NODE_SOCKET_API(ClosureType, distribution) ClosureType get_closure_type() { @@ -542,7 +590,7 @@ class DiffuseBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(DiffuseBsdfNode) - float roughness; + NODE_SOCKET_API(float, roughness) }; /* Disney principled BRDF */ @@ -570,19 +618,37 @@ class PrincipledBsdfNode : public BsdfBaseNode { ShaderInput *anisotropic_rotation, ShaderInput *transmission_roughness); - float3 base_color; - float3 subsurface_color, subsurface_radius; - float metallic, subsurface, specular, roughness, specular_tint, anisotropic, sheen, sheen_tint, - clearcoat, clearcoat_roughness, ior, transmission, anisotropic_rotation, - transmission_roughness; - float3 normal, clearcoat_normal, tangent; - float surface_mix_weight; - ClosureType distribution, distribution_orig; - ClosureType subsurface_method; - float3 emission; - float emission_strength; - float alpha; + NODE_SOCKET_API(float3, base_color) + NODE_SOCKET_API(float3, subsurface_color) + NODE_SOCKET_API(float3, subsurface_radius) + NODE_SOCKET_API(float, metallic) + NODE_SOCKET_API(float, subsurface) + NODE_SOCKET_API(float, specular) + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(float, specular_tint) + NODE_SOCKET_API(float, anisotropic) + NODE_SOCKET_API(float, sheen) + NODE_SOCKET_API(float, sheen_tint) + NODE_SOCKET_API(float, clearcoat) + NODE_SOCKET_API(float, clearcoat_roughness) + NODE_SOCKET_API(float, ior) + NODE_SOCKET_API(float, transmission) + NODE_SOCKET_API(float, anisotropic_rotation) + NODE_SOCKET_API(float, transmission_roughness) + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float3, clearcoat_normal) + NODE_SOCKET_API(float3, tangent) + NODE_SOCKET_API(float, surface_mix_weight) + NODE_SOCKET_API(ClosureType, distribution) + NODE_SOCKET_API(ClosureType, subsurface_method) + NODE_SOCKET_API(float3, emission) + NODE_SOCKET_API(float, emission_strength) + NODE_SOCKET_API(float, alpha) + private: + ClosureType distribution_orig; + + public: bool has_integrator_dependency(); void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() @@ -610,7 +676,7 @@ class VelvetBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(VelvetBsdfNode) - float sigma; + NODE_SOCKET_API(float, sigma) }; class GlossyBsdfNode : public BsdfNode { @@ -624,8 +690,12 @@ class GlossyBsdfNode : public BsdfNode { return distribution; } - float roughness, roughness_orig; - ClosureType distribution, distribution_orig; + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(ClosureType, distribution) + + private: + float roughness_orig; + ClosureType distribution_orig; }; class GlassBsdfNode : public BsdfNode { @@ -639,8 +709,13 @@ class GlassBsdfNode : public BsdfNode { return distribution; } - float roughness, roughness_orig, IOR; - ClosureType distribution, distribution_orig; + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(float, IOR) + NODE_SOCKET_API(ClosureType, distribution) + + private: + float roughness_orig; + ClosureType distribution_orig; }; class RefractionBsdfNode : public BsdfNode { @@ -654,16 +729,22 @@ class RefractionBsdfNode : public BsdfNode { return distribution; } - float roughness, roughness_orig, IOR; - ClosureType distribution, distribution_orig; + NODE_SOCKET_API(float, roughness) + NODE_SOCKET_API(float, IOR) + NODE_SOCKET_API(ClosureType, distribution) + + private: + float roughness_orig; + ClosureType distribution_orig; }; class ToonBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(ToonBsdfNode) - float smooth, size; - ClosureType component; + NODE_SOCKET_API(float, smooth) + NODE_SOCKET_API(float, size) + NODE_SOCKET_API(ClosureType, component) }; class SubsurfaceScatteringNode : public BsdfNode { @@ -679,11 +760,11 @@ class SubsurfaceScatteringNode : public BsdfNode { return falloff; } - float scale; - float3 radius; - float sharpness; - float texture_blur; - ClosureType falloff; + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float3, radius) + NODE_SOCKET_API(float, sharpness) + NODE_SOCKET_API(float, texture_blur) + NODE_SOCKET_API(ClosureType, falloff) }; class EmissionNode : public ShaderNode { @@ -700,9 +781,9 @@ class EmissionNode : public ShaderNode { return true; } - float3 color; - float strength; - float surface_mix_weight; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float, surface_mix_weight) }; class BackgroundNode : public ShaderNode { @@ -710,9 +791,9 @@ class BackgroundNode : public ShaderNode { SHADER_NODE_CLASS(BackgroundNode) void constant_fold(const ConstantFolder &folder); - float3 color; - float strength; - float surface_mix_weight; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float, surface_mix_weight) }; class HoldoutNode : public ShaderNode { @@ -727,8 +808,8 @@ class HoldoutNode : public ShaderNode { return CLOSURE_HOLDOUT_ID; } - float surface_mix_weight; - float volume_mix_weight; + NODE_SOCKET_API(float, surface_mix_weight) + NODE_SOCKET_API(float, volume_mix_weight) }; class AmbientOcclusionNode : public ShaderNode { @@ -748,13 +829,13 @@ class AmbientOcclusionNode : public ShaderNode { return true; } - float3 color; - float distance; - float3 normal; - int samples; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, distance) + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(int, samples) - bool only_local; - bool inside; + NODE_SOCKET_API(bool, only_local) + NODE_SOCKET_API(bool, inside) }; class VolumeNode : public ShaderNode { @@ -780,11 +861,14 @@ class VolumeNode : public ShaderNode { return true; } - float3 color; - float density; - float volume_mix_weight; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, density) + NODE_SOCKET_API(float, volume_mix_weight) + + protected: ClosureType closure; + public: virtual bool equals(const ShaderNode & /*other*/) { /* TODO(sergey): With some care Volume nodes can be de-duplicated. */ @@ -801,7 +885,7 @@ class ScatterVolumeNode : public VolumeNode { public: SHADER_NODE_CLASS(ScatterVolumeNode) - float anisotropy; + NODE_SOCKET_API(float, anisotropy) }; class PrincipledVolumeNode : public VolumeNode { @@ -813,17 +897,17 @@ class PrincipledVolumeNode : public VolumeNode { return true; } - ustring density_attribute; - ustring color_attribute; - ustring temperature_attribute; + NODE_SOCKET_API(ustring, density_attribute) + NODE_SOCKET_API(ustring, color_attribute) + NODE_SOCKET_API(ustring, temperature_attribute) - float anisotropy; - float3 absorption_color; - float emission_strength; - float3 emission_color; - float blackbody_intensity; - float3 blackbody_tint; - float temperature; + NODE_SOCKET_API(float, anisotropy) + NODE_SOCKET_API(float3, absorption_color) + NODE_SOCKET_API(float, emission_strength) + NODE_SOCKET_API(float3, emission_color) + NODE_SOCKET_API(float, blackbody_intensity) + NODE_SOCKET_API(float3, blackbody_tint) + NODE_SOCKET_API(float, temperature) }; /* Interface between the I/O sockets and the SVM/OSL backend. */ @@ -833,36 +917,36 @@ class PrincipledHairBsdfNode : public BsdfBaseNode { void attributes(Shader *shader, AttributeRequestSet *attributes); /* Longitudinal roughness. */ - float roughness; + NODE_SOCKET_API(float, roughness) /* Azimuthal roughness. */ - float radial_roughness; + NODE_SOCKET_API(float, radial_roughness) /* Randomization factor for roughnesses. */ - float random_roughness; + NODE_SOCKET_API(float, random_roughness) /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */ - float coat; + NODE_SOCKET_API(float, coat) /* Index of reflection. */ - float ior; + NODE_SOCKET_API(float, ior) /* Cuticle tilt angle. */ - float offset; + NODE_SOCKET_API(float, offset) /* Direct coloring's color. */ - float3 color; + NODE_SOCKET_API(float3, color) /* Melanin concentration. */ - float melanin; + NODE_SOCKET_API(float, melanin) /* Melanin redness ratio. */ - float melanin_redness; + NODE_SOCKET_API(float, melanin_redness) /* Dye color. */ - float3 tint; + NODE_SOCKET_API(float3, tint) /* Randomization factor for melanin quantities. */ - float random_color; + NODE_SOCKET_API(float, random_color) /* Absorption coefficient (unfiltered). */ - float3 absorption_coefficient; + NODE_SOCKET_API(float3, absorption_coefficient) - float3 normal; - float surface_mix_weight; + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float, surface_mix_weight) /* If linked, here will be the given random number. */ - float random; + NODE_SOCKET_API(float, random) /* Selected coloring parametrization. */ - NodePrincipledHairParametrization parametrization; + NODE_SOCKET_API(NodePrincipledHairParametrization, parametrization) }; class HairBsdfNode : public BsdfNode { @@ -873,11 +957,11 @@ class HairBsdfNode : public BsdfNode { return component; } - ClosureType component; - float offset; - float roughness_u; - float roughness_v; - float3 tangent; + NODE_SOCKET_API(ClosureType, component) + NODE_SOCKET_API(float, offset) + NODE_SOCKET_API(float, roughness_u) + NODE_SOCKET_API(float, roughness_v) + NODE_SOCKET_API(float3, tangent) }; class GeometryNode : public ShaderNode { @@ -894,7 +978,7 @@ class GeometryNode : public ShaderNode { } int get_group(); - float3 normal_osl; + NODE_SOCKET_API(float3, normal_osl) }; class TextureCoordinateNode : public ShaderNode { @@ -910,10 +994,10 @@ class TextureCoordinateNode : public ShaderNode { return true; } - float3 normal_osl; - bool from_dupli; - bool use_transform; - Transform ob_tfm; + NODE_SOCKET_API(float3, normal_osl) + NODE_SOCKET_API(bool, from_dupli) + NODE_SOCKET_API(bool, use_transform) + NODE_SOCKET_API(Transform, ob_tfm) }; class UVMapNode : public ShaderNode { @@ -933,8 +1017,8 @@ class UVMapNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - ustring attribute; - bool from_dupli; + NODE_SOCKET_API(ustring, attribute) + NODE_SOCKET_API(bool, from_dupli) }; class LightPathNode : public ShaderNode { @@ -958,8 +1042,8 @@ class LightFalloffNode : public ShaderNode { return NODE_GROUP_LEVEL_2; } - float strength; - float smooth; + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float, smooth) }; class ObjectInfoNode : public ShaderNode { @@ -1036,7 +1120,7 @@ class VertexColorNode : public ShaderNode { return true; } - ustring layer_name; + NODE_SOCKET_API(ustring, layer_name) }; class ValueNode : public ShaderNode { @@ -1045,7 +1129,7 @@ class ValueNode : public ShaderNode { void constant_fold(const ConstantFolder &folder); - float value; + NODE_SOCKET_API(float, value) }; class ColorNode : public ShaderNode { @@ -1054,7 +1138,7 @@ class ColorNode : public ShaderNode { void constant_fold(const ConstantFolder &folder); - float3 value; + NODE_SOCKET_API(float3, value) }; class AddClosureNode : public ShaderNode { @@ -1068,15 +1152,15 @@ class MixClosureNode : public ShaderNode { SHADER_NODE_CLASS(MixClosureNode) void constant_fold(const ConstantFolder &folder); - float fac; + NODE_SOCKET_API(float, fac) }; class MixClosureWeightNode : public ShaderNode { public: SHADER_NODE_CLASS(MixClosureWeightNode) - float weight; - float fac; + NODE_SOCKET_API(float, weight) + NODE_SOCKET_API(float, fac) }; class InvertNode : public ShaderNode { @@ -1088,8 +1172,8 @@ class InvertNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float fac; - float3 color; + NODE_SOCKET_API(float, fac) + NODE_SOCKET_API(float3, color) }; class MixNode : public ShaderNode { @@ -1102,11 +1186,11 @@ class MixNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - NodeMix type; - bool use_clamp; - float3 color1; - float3 color2; - float fac; + NODE_SOCKET_API(NodeMix, mix_type) + NODE_SOCKET_API(bool, use_clamp) + NODE_SOCKET_API(float3, color1) + NODE_SOCKET_API(float3, color2) + NODE_SOCKET_API(float, fac) }; class CombineRGBNode : public ShaderNode { @@ -1118,7 +1202,9 @@ class CombineRGBNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float r, g, b; + NODE_SOCKET_API(float, r) + NODE_SOCKET_API(float, g) + NODE_SOCKET_API(float, b) }; class CombineHSVNode : public ShaderNode { @@ -1130,7 +1216,9 @@ class CombineHSVNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float h, s, v; + NODE_SOCKET_API(float, h) + NODE_SOCKET_API(float, s) + NODE_SOCKET_API(float, v) }; class CombineXYZNode : public ShaderNode { @@ -1142,7 +1230,9 @@ class CombineXYZNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float x, y, z; + NODE_SOCKET_API(float, x) + NODE_SOCKET_API(float, y) + NODE_SOCKET_API(float, z) }; class GammaNode : public ShaderNode { @@ -1154,8 +1244,8 @@ class GammaNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - float3 color; - float gamma; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, gamma) }; class BrightContrastNode : public ShaderNode { @@ -1167,9 +1257,9 @@ class BrightContrastNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - float3 color; - float bright; - float contrast; + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, bright) + NODE_SOCKET_API(float, contrast) }; class SeparateRGBNode : public ShaderNode { @@ -1181,7 +1271,7 @@ class SeparateRGBNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float3 color; + NODE_SOCKET_API(float3, color) }; class SeparateHSVNode : public ShaderNode { @@ -1193,7 +1283,7 @@ class SeparateHSVNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float3 color; + NODE_SOCKET_API(float3, color) }; class SeparateXYZNode : public ShaderNode { @@ -1205,18 +1295,18 @@ class SeparateXYZNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float3 vector; + NODE_SOCKET_API(float3, vector) }; class HSVNode : public ShaderNode { public: SHADER_NODE_CLASS(HSVNode) - float hue; - float saturation; - float value; - float fac; - float3 color; + NODE_SOCKET_API(float, hue) + NODE_SOCKET_API(float, saturation) + NODE_SOCKET_API(float, value) + NODE_SOCKET_API(float, fac) + NODE_SOCKET_API(float3, color) }; class AttributeNode : public ShaderNode { @@ -1232,7 +1322,7 @@ class AttributeNode : public ShaderNode { return true; } - ustring attribute; + NODE_SOCKET_API(ustring, attribute) }; class CameraNode : public ShaderNode { @@ -1260,8 +1350,8 @@ class FresnelNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - float3 normal; - float IOR; + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float, IOR) }; class LayerWeightNode : public ShaderNode { @@ -1276,8 +1366,8 @@ class LayerWeightNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - float3 normal; - float blend; + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float, blend) }; class WireframeNode : public ShaderNode { @@ -1292,8 +1382,8 @@ class WireframeNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float size; - bool use_pixel_size; + NODE_SOCKET_API(float, size) + NODE_SOCKET_API(bool, use_pixel_size) }; class WavelengthNode : public ShaderNode { @@ -1304,7 +1394,7 @@ class WavelengthNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float wavelength; + NODE_SOCKET_API(float, wavelength) }; class BlackbodyNode : public ShaderNode { @@ -1316,7 +1406,7 @@ class BlackbodyNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - float temperature; + NODE_SOCKET_API(float, temperature) }; class MapRangeNode : public ShaderNode { @@ -1328,9 +1418,14 @@ class MapRangeNode : public ShaderNode { } void expand(ShaderGraph *graph); - float value, from_min, from_max, to_min, to_max, steps; - NodeMapRangeType type; - bool clamp; + NODE_SOCKET_API(float, value) + NODE_SOCKET_API(float, from_min) + NODE_SOCKET_API(float, from_max) + NODE_SOCKET_API(float, to_min) + NODE_SOCKET_API(float, to_max) + NODE_SOCKET_API(float, steps) + NODE_SOCKET_API(NodeMapRangeType, range_type) + NODE_SOCKET_API(bool, clamp) }; class ClampNode : public ShaderNode { @@ -1341,8 +1436,10 @@ class ClampNode : public ShaderNode { { return NODE_GROUP_LEVEL_3; } - float value, min, max; - NodeClampType type; + NODE_SOCKET_API(float, value) + NODE_SOCKET_API(float, min) + NODE_SOCKET_API(float, max) + NODE_SOCKET_API(NodeClampType, clamp_type) }; class MathNode : public ShaderNode { @@ -1355,11 +1452,11 @@ class MathNode : public ShaderNode { void expand(ShaderGraph *graph); void constant_fold(const ConstantFolder &folder); - float value1; - float value2; - float value3; - NodeMathType type; - bool use_clamp; + NODE_SOCKET_API(float, value1) + NODE_SOCKET_API(float, value2) + NODE_SOCKET_API(float, value3) + NODE_SOCKET_API(NodeMathType, math_type) + NODE_SOCKET_API(bool, use_clamp) }; class NormalNode : public ShaderNode { @@ -1370,8 +1467,8 @@ class NormalNode : public ShaderNode { return NODE_GROUP_LEVEL_2; } - float3 direction; - float3 normal; + NODE_SOCKET_API(float3, direction) + NODE_SOCKET_API(float3, normal) }; class VectorMathNode : public ShaderNode { @@ -1383,11 +1480,11 @@ class VectorMathNode : public ShaderNode { } void constant_fold(const ConstantFolder &folder); - float3 vector1; - float3 vector2; - float3 vector3; - float scale; - NodeVectorMathType type; + NODE_SOCKET_API(float3, vector1) + NODE_SOCKET_API(float3, vector2) + NODE_SOCKET_API(float3, vector3) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(NodeVectorMathType, math_type) }; class VectorRotateNode : public ShaderNode { @@ -1398,13 +1495,13 @@ class VectorRotateNode : public ShaderNode { { return NODE_GROUP_LEVEL_3; } - NodeVectorRotateType type; - bool invert; - float3 vector; - float3 center; - float3 axis; - float angle; - float3 rotation; + NODE_SOCKET_API(NodeVectorRotateType, rotate_type) + NODE_SOCKET_API(bool, invert) + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float3, center) + NODE_SOCKET_API(float3, axis) + NODE_SOCKET_API(float, angle) + NODE_SOCKET_API(float3, rotation) }; class VectorTransformNode : public ShaderNode { @@ -1416,10 +1513,10 @@ class VectorTransformNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - NodeVectorTransformType type; - NodeVectorTransformConvertSpace convert_from; - NodeVectorTransformConvertSpace convert_to; - float3 vector; + NODE_SOCKET_API(NodeVectorTransformType, transform_type) + NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_from) + NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_to) + NODE_SOCKET_API(float3, vector) }; class BumpNode : public ShaderNode { @@ -1435,15 +1532,15 @@ class BumpNode : public ShaderNode { return NODE_FEATURE_BUMP; } - bool invert; - bool use_object_space; - float height; - float sample_center; - float sample_x; - float sample_y; - float3 normal; - float strength; - float distance; + NODE_SOCKET_API(bool, invert) + NODE_SOCKET_API(bool, use_object_space) + NODE_SOCKET_API(float, height) + NODE_SOCKET_API(float, sample_center) + NODE_SOCKET_API(float, sample_x) + NODE_SOCKET_API(float, sample_y) + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float, distance) }; class CurvesNode : public ShaderNode { @@ -1456,9 +1553,11 @@ class CurvesNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - array<float3> curves; - float min_x, max_x, fac; - float3 value; + NODE_SOCKET_API(array<float3>, curves) + NODE_SOCKET_API(float, min_x) + NODE_SOCKET_API(float, max_x) + NODE_SOCKET_API(float, fac) + NODE_SOCKET_API(float3, value) protected: using ShaderNode::constant_fold; @@ -1488,16 +1587,16 @@ class RGBRampNode : public ShaderNode { return NODE_GROUP_LEVEL_1; } - array<float3> ramp; - array<float> ramp_alpha; - float fac; - bool interpolate; + NODE_SOCKET_API(array<float3>, ramp) + NODE_SOCKET_API(array<float>, ramp_alpha) + NODE_SOCKET_API(float, fac) + NODE_SOCKET_API(bool, interpolate) }; class SetNormalNode : public ShaderNode { public: SHADER_NODE_CLASS(SetNormalNode) - float3 direction; + NODE_SOCKET_API(float3, direction) }; class OSLNode : public ShaderNode { @@ -1549,11 +1648,11 @@ class NormalMapNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - NodeNormalMapSpace space; - ustring attribute; - float strength; - float3 color; - float3 normal_osl; + NODE_SOCKET_API(NodeNormalMapSpace, space) + NODE_SOCKET_API(ustring, attribute) + NODE_SOCKET_API(float, strength) + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float3, normal_osl) }; class TangentNode : public ShaderNode { @@ -1573,10 +1672,10 @@ class TangentNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } - NodeTangentDirectionType direction_type; - NodeTangentAxis axis; - ustring attribute; - float3 normal_osl; + NODE_SOCKET_API(NodeTangentDirectionType, direction_type) + NODE_SOCKET_API(NodeTangentAxis, axis) + NODE_SOCKET_API(ustring, attribute) + NODE_SOCKET_API(float3, normal_osl) }; class BevelNode : public ShaderNode { @@ -1595,9 +1694,9 @@ class BevelNode : public ShaderNode { return true; } - float radius; - float3 normal; - int samples; + NODE_SOCKET_API(float, radius) + NODE_SOCKET_API(float3, normal) + NODE_SOCKET_API(int, samples) }; class DisplacementNode : public ShaderNode { @@ -1609,11 +1708,11 @@ class DisplacementNode : public ShaderNode { return NODE_FEATURE_BUMP; } - NodeNormalMapSpace space; - float height; - float midlevel; - float scale; - float3 normal; + NODE_SOCKET_API(NodeNormalMapSpace, space) + NODE_SOCKET_API(float, height) + NODE_SOCKET_API(float, midlevel) + NODE_SOCKET_API(float, scale) + NODE_SOCKET_API(float3, normal) }; class VectorDisplacementNode : public ShaderNode { @@ -1630,11 +1729,11 @@ class VectorDisplacementNode : public ShaderNode { return NODE_FEATURE_BUMP; } - NodeNormalMapSpace space; - ustring attribute; - float3 vector; - float midlevel; - float scale; + NODE_SOCKET_API(NodeNormalMapSpace, space) + NODE_SOCKET_API(ustring, attribute) + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float, midlevel) + NODE_SOCKET_API(float, scale) }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index bce2e08b390..70ce60252f0 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -104,9 +104,13 @@ NODE_DEFINE(Object) SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f)); SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>()); SOCKET_FLOAT(shadow_terminator_offset, "Terminator Offset", 0.0f); + SOCKET_STRING(asset_name, "Asset Name", ustring()); SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false); + SOCKET_NODE(particle_system, "Particle System", &ParticleSystem::node_type); + SOCKET_INT(particle_index, "Particle Index", 0); + return type; } @@ -114,6 +118,7 @@ Object::Object() : Node(node_type) { particle_system = NULL; particle_index = 0; + attr_map_offset = 0; bounds = BoundBox::empty; } @@ -212,10 +217,11 @@ void Object::tag_update(Scene *scene) { if (geometry) { if (geometry->transform_applied) - geometry->need_update = true; + geometry->tag_modified(); - foreach (Shader *shader, geometry->used_shaders) { - if (shader->use_mis && shader->has_surface_emission) + foreach (Node *node, geometry->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + if (shader->get_use_mis() && shader->has_surface_emission) scene->light_manager->need_update = true; } } @@ -272,7 +278,7 @@ uint Object::visibility_for_tracing() const float Object::compute_volume_step_size() const { - if (geometry->type != Geometry::MESH && geometry->type != Geometry::VOLUME) { + if (geometry->geometry_type != Geometry::MESH && geometry->geometry_type != Geometry::VOLUME) { return FLT_MAX; } @@ -285,11 +291,12 @@ float Object::compute_volume_step_size() const /* Compute step rate from shaders. */ float step_rate = FLT_MAX; - foreach (Shader *shader, mesh->used_shaders) { + foreach (Node *node, mesh->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); if (shader->has_volume) { - if ((shader->heterogeneous_volume && shader->has_volume_spatial_varying) || + if ((shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) || (shader->has_volume_attribute_dependency)) { - step_rate = fminf(shader->volume_step_rate, step_rate); + step_rate = fminf(shader->get_volume_step_rate(), step_rate); } } } @@ -301,7 +308,7 @@ float Object::compute_volume_step_size() const /* Compute step size from voxel grids. */ float step_size = FLT_MAX; - if (geometry->type == Geometry::VOLUME) { + if (geometry->geometry_type == Geometry::VOLUME) { Volume *volume = static_cast<Volume *>(geometry); foreach (Attribute &attr, volume->attributes.attributes) { @@ -313,12 +320,17 @@ float Object::compute_volume_step_size() const } /* User specified step size. */ - float voxel_step_size = volume->step_size; + float voxel_step_size = volume->get_step_size(); if (voxel_step_size == 0.0f) { /* Auto detect step size. */ - float3 size = make_float3( - 1.0f / metadata.width, 1.0f / metadata.height, 1.0f / metadata.depth); + float3 size = make_float3(1.0f, 1.0f, 1.0f); +#ifdef WITH_NANOVDB + /* Dimensions were not applied to image transform with NanOVDB (see image_vdb.cpp) */ + if (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT && + metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) +#endif + size /= make_float3(metadata.width, metadata.height, metadata.depth); /* Step size is transformed from voxel to world space. */ Transform voxel_tfm = tfm; @@ -327,7 +339,7 @@ float Object::compute_volume_step_size() const } voxel_step_size = min3(fabs(transform_direction(&voxel_tfm, size))); } - else if (volume->object_space) { + else if (volume->get_object_space()) { /* User specified step size in object space. */ float3 size = make_float3(voxel_step_size, voxel_step_size, voxel_step_size); voxel_step_size = min3(fabs(transform_direction(&tfm, size))); @@ -371,14 +383,15 @@ static float object_surface_area(UpdateObjectTransformState *state, const Transform &tfm, Geometry *geom) { - if (geom->type != Geometry::MESH && geom->type != Geometry::VOLUME) { + if (geom->geometry_type != Geometry::MESH && geom->geometry_type != Geometry::VOLUME) { return 0.0f; } Mesh *mesh = static_cast<Mesh *>(geom); - if (mesh->has_volume || geom->type == Geometry::VOLUME) { + if (mesh->has_volume || geom->geometry_type == Geometry::VOLUME) { /* Volume density automatically adjust to object scale. */ - if (geom->type == Geometry::VOLUME && static_cast<Volume *>(geom)->object_space) { + if (geom->geometry_type == Geometry::VOLUME && + static_cast<Volume *>(geom)->get_object_space()) { const float3 unit = normalize(make_float3(1.0f, 1.0f, 1.0f)); return 1.0f / len(transform_direction(&tfm, unit)); } @@ -410,9 +423,9 @@ static float object_surface_area(UpdateObjectTransformState *state, size_t num_triangles = mesh->num_triangles(); for (size_t j = 0; j < num_triangles; j++) { Mesh::Triangle t = mesh->get_triangle(j); - float3 p1 = mesh->verts[t.v[0]]; - float3 p2 = mesh->verts[t.v[1]]; - float3 p3 = mesh->verts[t.v[2]]; + float3 p1 = mesh->get_verts()[t.v[0]]; + float3 p2 = mesh->get_verts()[t.v[1]]; + float3 p3 = mesh->get_verts()[t.v[2]]; surface_area += triangle_area(p1, p2, p3); } @@ -431,9 +444,9 @@ static float object_surface_area(UpdateObjectTransformState *state, size_t num_triangles = mesh->num_triangles(); for (size_t j = 0; j < num_triangles; j++) { Mesh::Triangle t = mesh->get_triangle(j); - float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]); - float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]); - float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]); + float3 p1 = transform_point(&tfm, mesh->get_verts()[t.v[0]]); + float3 p2 = transform_point(&tfm, mesh->get_verts()[t.v[1]]); + float3 p3 = transform_point(&tfm, mesh->get_verts()[t.v[2]]); surface_area += triangle_area(p1, p2, p3); } @@ -472,11 +485,11 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.particle_index = particle_index; kobject.motion_offset = 0; - if (geom->use_motion_blur) { + if (geom->get_use_motion_blur()) { state->have_motion = true; } - if (geom->type == Geometry::MESH) { + if (geom->geometry_type == Geometry::MESH) { /* TODO: why only mesh? */ Mesh *mesh = static_cast<Mesh *>(geom); if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { @@ -527,14 +540,16 @@ 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 = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom)->curve_keys.size() : - 0; + kobject.numkeys = (geom->geometry_type == Geometry::HAIR) ? + static_cast<Hair *>(geom)->get_curve_keys().size() : + 0; kobject.dupli_uv[0] = ob->dupli_uv[0]; kobject.dupli_uv[1] = ob->dupli_uv[1]; - int totalsteps = geom->motion_steps; + int totalsteps = geom->get_motion_steps(); kobject.numsteps = (totalsteps - 1) / 2; - kobject.numverts = (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) ? - static_cast<Mesh *>(geom)->verts.size() : + kobject.numverts = (geom->geometry_type == Geometry::MESH || + geom->geometry_type == Geometry::VOLUME) ? + static_cast<Mesh *>(geom)->get_verts().size() : 0; kobject.patch_map_offset = 0; kobject.attribute_map_offset = 0; @@ -552,7 +567,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s state->object_volume_step[ob->index] = FLT_MAX; /* Have curves. */ - if (geom->type == Geometry::HAIR) { + if (geom->geometry_type == Geometry::HAIR) { state->have_curves = true; } } @@ -687,6 +702,10 @@ void ObjectManager::device_update(Device *device, progress.set_status("Updating Objects", "Applying Static Transformations"); apply_static_transforms(dscene, scene, progress); } + + foreach (Object *object, scene->objects) { + object->clear_modified(); + } } void ObjectManager::device_update_flags( @@ -786,7 +805,7 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc foreach (Object *object, scene->objects) { Geometry *geom = object->geometry; - if (geom->type == Geometry::MESH) { + if (geom->geometry_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() - @@ -800,8 +819,15 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc } } - if (kobjects[object->index].attribute_map_offset != geom->attr_map_offset) { - kobjects[object->index].attribute_map_offset = geom->attr_map_offset; + size_t attr_map_offset = object->attr_map_offset; + + /* An object attribute map cannot have a zero offset because mesh maps come first. */ + if (attr_map_offset == 0) { + attr_map_offset = geom->attr_map_offset; + } + + if (kobjects[object->index].attribute_map_offset != attr_map_offset) { + kobjects[object->index].attribute_map_offset = attr_map_offset; update = true; } } @@ -857,11 +883,11 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P bool apply = (geometry_users[geom] == 1) && !geom->has_surface_bssrdf && !geom->has_true_displacement(); - if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) { + if (geom->geometry_type == Geometry::MESH) { Mesh *mesh = static_cast<Mesh *>(geom); - apply = apply && mesh->subdivision_type == Mesh::SUBDIVISION_NONE; + apply = apply && mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE; } - else if (geom->type == Geometry::HAIR) { + else if (geom->geometry_type == Geometry::HAIR) { /* Can't apply non-uniform scale to curves, this can't be represented by * control points and radius alone. */ float scale; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index ac9b4c331f5..76c9c30abb0 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -18,6 +18,11 @@ #define __OBJECT_H__ #include "graph/node.h" + +/* included as Object::set_particle_system defined through NODE_SOCKET_API does + * not select the right Node::set overload as it does not know that ParticleSystem + * is a Node */ +#include "render/particles.h" #include "render/scene.h" #include "util/util_array.h" @@ -46,26 +51,26 @@ class Object : public Node { public: NODE_DECLARE - Geometry *geometry; - Transform tfm; + NODE_SOCKET_API(Geometry *, geometry) + NODE_SOCKET_API(Transform, tfm) BoundBox bounds; - uint random_id; - int pass_id; - float3 color; - ustring asset_name; + NODE_SOCKET_API(uint, random_id) + NODE_SOCKET_API(int, pass_id) + NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(ustring, asset_name) vector<ParamValue> attributes; - uint visibility; - array<Transform> motion; - bool hide_on_missing_motion; - bool use_holdout; - bool is_shadow_catcher; - float shadow_terminator_offset; + NODE_SOCKET_API(uint, visibility) + NODE_SOCKET_API_ARRAY(array<Transform>, motion) + NODE_SOCKET_API(bool, hide_on_missing_motion) + NODE_SOCKET_API(bool, use_holdout) + NODE_SOCKET_API(bool, is_shadow_catcher) + NODE_SOCKET_API(float, shadow_terminator_offset) - float3 dupli_generated; - float2 dupli_uv; + NODE_SOCKET_API(float3, dupli_generated) + NODE_SOCKET_API(float2, dupli_uv) - ParticleSystem *particle_system; - int particle_index; + NODE_SOCKET_API(ParticleSystem *, particle_system); + NODE_SOCKET_API(int, particle_index); Object(); ~Object(); @@ -106,7 +111,12 @@ class Object : public Node { * in the device vectors. Gets set in device_update. */ int index; + /* Reference to the attribute map with object attributes, + * or 0 if none. Set in update_svm_attributes. */ + size_t attr_map_offset; + friend class ObjectManager; + friend class GeometryManager; }; /* Object Manager */ diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 0c2b2cf27e9..bea2c534bd1 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -131,7 +131,7 @@ void OSLShaderManager::device_update(Device *device, compiler.background = (shader == background_shader); compiler.compile(og, shader); - if (shader->use_mis && shader->has_surface_emission) + if (shader->get_use_mis() && shader->has_surface_emission) scene->light_manager->need_update = true; } @@ -145,7 +145,7 @@ void OSLShaderManager::device_update(Device *device, og->use = true; foreach (Shader *shader, scene->shaders) - shader->need_update = false; + shader->clear_modified(); need_update = false; @@ -1120,18 +1120,18 @@ OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph void OSLCompiler::compile(OSLGlobals *og, Shader *shader) { - if (shader->need_update) { + if (shader->is_modified()) { ShaderGraph *graph = shader->graph; ShaderNode *output = (graph) ? graph->output() : NULL; - bool has_bump = (shader->displacement_method != DISPLACE_TRUE) && + bool has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) && output->input("Surface")->link && output->input("Displacement")->link; /* finalize */ shader->graph->finalize(scene, has_bump, shader->has_integrator_dependency, - shader->displacement_method == DISPLACE_BOTH); + shader->get_displacement_method() == DISPLACE_BOTH); current_shader = shader; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 3fb6c9620e6..98c256a43b5 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -339,7 +339,7 @@ void Scene::device_update(Device *device_, Progress &progress) Scene::MotionType Scene::need_motion() { - if (integrator->motion_blur) + if (integrator->get_motion_blur()) return MOTION_BLUR; else if (Pass::contains(passes, PASS_MOTION)) return MOTION_PASS; @@ -352,7 +352,7 @@ float Scene::motion_shutter_time() if (need_motion() == Scene::MOTION_PASS) return 2.0f; else - return camera->shuttertime; + return camera->get_shuttertime(); } bool Scene::need_global_attribute(AttributeStandard std) @@ -376,20 +376,21 @@ void Scene::need_global_attributes(AttributeRequestSet &attributes) bool Scene::need_update() { - return (need_reset() || film->need_update); + return (need_reset() || film->is_modified()); } bool Scene::need_data_update() { - return (background->need_update || image_manager->need_update || object_manager->need_update || + return (background->is_modified() || image_manager->need_update || object_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 || bake_manager->need_update || film->need_update); + lookup_tables->need_update || integrator->is_modified() || shader_manager->need_update || + particle_system_manager->need_update || bake_manager->need_update || + film->is_modified()); } bool Scene::need_reset() { - return need_data_update() || camera->need_update; + return need_data_update() || camera->is_modified(); } void Scene::reset() @@ -398,9 +399,9 @@ void Scene::reset() shader_manager->add_default(this); /* ensure all objects are updated */ - camera->tag_update(); - dicing_camera->tag_update(); - film->tag_update(this); + camera->tag_modified(); + dicing_camera->tag_modified(); + film->tag_modified(); background->tag_update(this); integrator->tag_update(this); object_manager->tag_update(this); @@ -442,24 +443,24 @@ DeviceRequestedFeatures Scene::get_requested_device_features() requested_features.use_object_motion = false; requested_features.use_camera_motion = use_motion && camera->use_motion(); foreach (Object *object, objects) { - Geometry *geom = object->geometry; + Geometry *geom = object->get_geometry(); if (use_motion) { - requested_features.use_object_motion |= object->use_motion() | geom->use_motion_blur; - requested_features.use_camera_motion |= geom->use_motion_blur; + requested_features.use_object_motion |= object->use_motion() | geom->get_use_motion_blur(); + requested_features.use_camera_motion |= geom->get_use_motion_blur(); } - if (object->is_shadow_catcher) { + if (object->get_is_shadow_catcher()) { requested_features.use_shadow_tricks = true; } - if (geom->type == Geometry::MESH) { + if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); #ifdef WITH_OPENSUBDIV - if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + if (mesh->get_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) { + else if (geom->is_hair()) { requested_features.use_hair = true; } } @@ -467,8 +468,9 @@ DeviceRequestedFeatures Scene::get_requested_device_features() requested_features.use_background_light = light_manager->has_background_light(this); requested_features.use_baking = bake_manager->get_baking(); - requested_features.use_integrator_branched = (integrator->method == Integrator::BRANCHED_PATH); - if (film->denoising_data_pass) { + requested_features.use_integrator_branched = (integrator->get_method() == + Integrator::BRANCHED_PATH); + if (film->get_denoising_data_pass()) { requested_features.use_denoising = true; requested_features.use_shadow_tricks = true; } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 8f64495c76b..524a0e3b9d4 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -61,22 +61,6 @@ Session::Session(const SessionParams ¶ms_) TaskScheduler::init(params.threads); - /* Create CPU/GPU devices. */ - device = Device::create(params.device, stats, profiler, params.background); - - /* Create buffers for interactive rendering. */ - if (params.background && !params.write_render_cb) { - buffers = NULL; - display = NULL; - } - else { - buffers = new RenderBuffers(device); - display = new DisplayBuffer(device, params.display_buffer_linear); - } - - /* Validate denoising parameters. */ - set_denoising(params.denoising); - session_thread = NULL; scene = NULL; @@ -90,13 +74,33 @@ Session::Session(const SessionParams ¶ms_) gpu_draw_ready = false; gpu_need_display_buffer_update = false; pause = false; + + buffers = NULL; + display = NULL; + + /* Validate denoising parameters. */ + set_denoising(params.denoising); + + /* Create CPU/GPU devices. */ + device = Device::create(params.device, stats, profiler, params.background); + + if (!device->error_message().empty()) { + progress.set_error(device->error_message()); + return; + } + + /* Create buffers for interactive rendering. */ + if (!(params.background && !params.write_render_cb)) { + buffers = new RenderBuffers(device); + display = new DisplayBuffer(device, params.display_buffer_linear); + } } Session::~Session() { cancel(); - if (params.write_render_cb) { + if (buffers && params.write_render_cb) { /* Copy to display buffer and write out image if requested */ delete display; @@ -383,6 +387,62 @@ bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_param return false; } +bool Session::steal_tile(RenderTile &rtile, Device *tile_device, thread_scoped_lock &tile_lock) +{ + /* Devices that can get their tiles stolen don't steal tiles themselves. + * Additionally, if there are no stealable tiles in flight, give up here. */ + if (tile_device->info.type == DEVICE_CPU || stealable_tiles == 0) { + return false; + } + + /* Wait until no other thread is trying to steal a tile. */ + while (tile_stealing_state != NOT_STEALING && stealable_tiles > 0) { + /* Someone else is currently trying to get a tile. + * Wait on the condition variable and try later. */ + tile_steal_cond.wait(tile_lock); + } + /* If another thread stole the last stealable tile in the meantime, give up. */ + if (stealable_tiles == 0) { + return false; + } + + /* There are stealable tiles in flight, so signal that one should be released. */ + tile_stealing_state = WAITING_FOR_TILE; + + /* Wait until a device notices the signal and releases its tile. */ + while (tile_stealing_state != GOT_TILE && stealable_tiles > 0) { + tile_steal_cond.wait(tile_lock); + } + /* If the last stealable tile finished on its own, give up. */ + if (tile_stealing_state != GOT_TILE) { + tile_stealing_state = NOT_STEALING; + return false; + } + + /* Successfully stole a tile, now move it to the new device. */ + rtile = stolen_tile; + rtile.buffers->buffer.move_device(tile_device); + rtile.buffer = rtile.buffers->buffer.device_pointer; + rtile.stealing_state = RenderTile::NO_STEALING; + rtile.num_samples -= (rtile.sample - rtile.start_sample); + rtile.start_sample = rtile.sample; + + tile_stealing_state = NOT_STEALING; + + /* Poke any threads which might be waiting for NOT_STEALING above. */ + tile_steal_cond.notify_one(); + + return true; +} + +bool Session::get_tile_stolen() +{ + /* If tile_stealing_state is WAITING_FOR_TILE, atomically set it to RELEASING_TILE + * and return true. */ + TileStealingState expected = WAITING_FOR_TILE; + return tile_stealing_state.compare_exchange_weak(expected, RELEASING_TILE); +} + bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_types) { if (progress.get_cancel()) { @@ -404,7 +464,8 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ denoising_cond.wait(tile_lock); continue; } - return false; + + return steal_tile(rtile, tile_device, tile_lock); } /* fill render tile */ @@ -420,11 +481,18 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ if (tile->state == Tile::DENOISE) { rtile.task = RenderTile::DENOISE; } - else if (read_bake_tile_cb) { - rtile.task = RenderTile::BAKE; - } else { - rtile.task = RenderTile::PATH_TRACE; + if (tile_device->info.type == DEVICE_CPU) { + stealable_tiles++; + rtile.stealing_state = RenderTile::CAN_BE_STOLEN; + } + + if (read_bake_tile_cb) { + rtile.task = RenderTile::BAKE; + } + else { + rtile.task = RenderTile::PATH_TRACE; + } } tile_lock.unlock(); @@ -509,6 +577,26 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise) { thread_scoped_lock tile_lock(tile_mutex); + if (rtile.stealing_state != RenderTile::NO_STEALING) { + stealable_tiles--; + if (rtile.stealing_state == RenderTile::WAS_STOLEN) { + /* If the tile is being stolen, don't release it here - the new device will pick up where + * the old one left off. */ + + assert(tile_stealing_state == RELEASING_TILE); + assert(rtile.sample < rtile.start_sample + rtile.num_samples); + + tile_stealing_state = GOT_TILE; + stolen_tile = rtile; + tile_steal_cond.notify_all(); + return; + } + else if (stealable_tiles == 0) { + /* If this was the last stealable tile, wake up any threads still waiting for one. */ + tile_steal_cond.notify_all(); + } + } + progress.add_finished_tile(rtile.task == RenderTile::DENOISE); bool delete_tile; @@ -816,6 +904,8 @@ void Session::reset_(BufferParams &buffer_params, int samples) } tile_manager.reset(buffer_params, samples); + stealable_tiles = 0; + tile_stealing_state = NOT_STEALING; progress.reset_sample(); bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX; @@ -923,23 +1013,19 @@ bool Session::update_scene() int height = tile_manager.state.buffer.full_height; int resolution = tile_manager.state.resolution_divider; - if (width != cam->width || height != cam->height || resolution != cam->resolution) { - cam->width = width; - cam->height = height; - cam->resolution = resolution; - cam->tag_update(); - } + cam->set_screen_size_and_resolution(width, height, resolution); /* number of samples is needed by multi jittered * sampling pattern and by baking */ Integrator *integrator = scene->integrator; BakeManager *bake_manager = scene->bake_manager; - if (integrator->sampling_pattern != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) { + if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) { int aa_samples = tile_manager.num_samples; - if (aa_samples != integrator->aa_samples) { - integrator->aa_samples = aa_samples; + integrator->set_aa_samples(aa_samples); + + if (integrator->is_modified()) { integrator->tag_update(scene); } } @@ -1033,7 +1119,7 @@ bool Session::render_need_denoise(bool &delayed) /* Viewport render. */ /* It can happen that denoising was already enabled, but the scene still needs an update. */ - if (scene->film->need_update || !scene->film->denoising_data_offset) { + if (scene->film->is_modified() || !scene->film->get_denoising_data_offset()) { return false; } @@ -1076,10 +1162,12 @@ void Session::render(bool need_denoise) task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2); + task.get_tile_stolen = function_bind(&Session::get_tile_stolen, this); task.need_finish_queue = params.progressive_refine; - task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH; + task.integrator_branched = scene->integrator->get_method() == Integrator::BRANCHED_PATH; - task.adaptive_sampling.use = (scene->integrator->sampling_pattern == SAMPLING_PATTERN_PMJ) && + task.adaptive_sampling.use = (scene->integrator->get_sampling_pattern() == + SAMPLING_PATTERN_PMJ) && scene->dscene.data.film.pass_adaptive_aux_buffer; task.adaptive_sampling.min_samples = scene->dscene.data.integrator.adaptive_min_samples; task.adaptive_sampling.adaptive_step = scene->dscene.data.integrator.adaptive_step; @@ -1090,10 +1178,10 @@ void Session::render(bool need_denoise) if (need_denoise) { task.denoising = params.denoising; - task.pass_stride = scene->film->pass_stride; + task.pass_stride = scene->film->get_pass_stride(); task.target_pass_stride = task.pass_stride; - task.pass_denoising_data = scene->film->denoising_data_offset; - task.pass_denoising_clean = scene->film->denoising_clean_offset; + task.pass_denoising_data = scene->film->get_denoising_data_offset(); + task.pass_denoising_clean = scene->film->get_denoising_clean_offset(); task.denoising_from_render = true; diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index a52082bd8cb..ab6c0b5f124 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -194,6 +194,8 @@ class Session { bool render_need_denoise(bool &delayed); + bool steal_tile(RenderTile &tile, Device *tile_device, thread_scoped_lock &tile_lock); + bool get_tile_stolen(); bool acquire_tile(RenderTile &tile, Device *tile_device, uint tile_types); void update_tile_sample(RenderTile &tile); void release_tile(RenderTile &tile, const bool need_denoise); @@ -218,11 +220,22 @@ class Session { thread_mutex buffers_mutex; thread_mutex display_mutex; thread_condition_variable denoising_cond; + thread_condition_variable tile_steal_cond; double reset_time; double last_update_time; double last_display_time; + RenderTile stolen_tile; + typedef enum { + NOT_STEALING, /* There currently is no tile stealing in progress. */ + WAITING_FOR_TILE, /* A device is waiting for another device to release a tile. */ + RELEASING_TILE, /* A device has releasing a stealable tile. */ + GOT_TILE /* A device has released a stealable tile, which is now stored in stolen_tile. */ + } TileStealingState; + std::atomic<TileStealingState> tile_stealing_state; + int stealable_tiles; + /* progressive refine */ bool update_progressive_refine(bool cancel); }; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 135d0dc962b..cf49dedc426 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -187,6 +187,8 @@ NODE_DEFINE(Shader) displacement_method_enum.insert("both", DISPLACE_BOTH); SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP); + SOCKET_INT(pass_id, "Pass ID", 0); + return type; } @@ -216,7 +218,6 @@ Shader::Shader() : Node(node_type) id = -1; used = false; - need_update = true; need_update_geometry = true; } @@ -250,7 +251,7 @@ bool Shader::is_constant_emission(float3 *emission) return false; } - *emission = node->color * node->strength; + *emission = node->get_color() * node->get_strength(); } else if (surf->link->parent->type == BackgroundNode::node_type) { BackgroundNode *node = (BackgroundNode *)surf->link->parent; @@ -262,7 +263,7 @@ bool Shader::is_constant_emission(float3 *emission) return false; } - *emission = node->color * node->strength; + *emission = node->get_color() * node->get_strength(); } else { return false; @@ -306,7 +307,7 @@ void Shader::set_graph(ShaderGraph *graph_) void Shader::tag_update(Scene *scene) { /* update tag */ - need_update = true; + tag_modified(); scene->shader_manager->need_update = true; /* if the shader previously was emissive, update light distribution, @@ -369,7 +370,7 @@ void Shader::tag_used(Scene *scene) /* if an unused shader suddenly gets used somewhere, it needs to be * recompiled because it was skipped for compilation before */ if (!used) { - need_update = true; + tag_modified(); scene->shader_manager->need_update = true; } } @@ -493,16 +494,18 @@ void ShaderManager::update_shaders_used(Scene *scene) scene->default_background->used = true; scene->default_empty->used = true; - if (scene->background->shader) - scene->background->shader->used = true; + if (scene->background->get_shader()) + scene->background->get_shader()->used = true; foreach (Geometry *geom, scene->geometry) - foreach (Shader *shader, geom->used_shaders) + foreach (Node *node, geom->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); shader->used = true; + } foreach (Light *light, scene->lights) - if (light->shader) - light->shader->used = true; + if (light->get_shader()) + const_cast<Shader *>(light->get_shader())->used = true; } void ShaderManager::device_update_common(Device *device, @@ -522,9 +525,9 @@ void ShaderManager::device_update_common(Device *device, foreach (Shader *shader, scene->shaders) { uint flag = 0; - if (shader->use_mis) + if (shader->get_use_mis()) flag |= SD_USE_MIS; - if (shader->has_surface_transparent && shader->use_transparent_shadow) + if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) flag |= SD_HAS_TRANSPARENT_SHADOW; if (shader->has_volume) { flag |= SD_HAS_VOLUME; @@ -539,7 +542,7 @@ void ShaderManager::device_update_common(Device *device, if (shader->has_volume_connected && !shader->has_surface) flag |= SD_HAS_ONLY_VOLUME; if (shader->has_volume) { - if (shader->heterogeneous_volume && shader->has_volume_spatial_varying) + if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) flag |= SD_HETEROGENEOUS_VOLUME; } if (shader->has_volume_attribute_dependency) @@ -547,16 +550,16 @@ void ShaderManager::device_update_common(Device *device, if (shader->has_bssrdf_bump) flag |= SD_HAS_BSSRDF_BUMP; if (device->info.has_volume_decoupled) { - if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR) + if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) flag |= SD_VOLUME_EQUIANGULAR; - if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) + if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) flag |= SD_VOLUME_MIS; } - if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) + if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) flag |= SD_VOLUME_CUBIC; if (shader->has_bump) flag |= SD_HAS_BUMP; - if (shader->displacement_method != DISPLACE_BUMP) + if (shader->get_displacement_method() != DISPLACE_BUMP) flag |= SD_HAS_DISPLACEMENT; /* constant emission check */ @@ -568,7 +571,7 @@ void ShaderManager::device_update_common(Device *device, /* regular shader */ kshader->flags = flag; - kshader->pass_id = shader->pass_id; + kshader->pass_id = shader->get_pass_id(); kshader->constant_emission[0] = constant_emission.x; kshader->constant_emission[1] = constant_emission.y; kshader->constant_emission[2] = constant_emission.z; @@ -625,7 +628,7 @@ void ShaderManager::add_default(Scene *scene) ShaderGraph *graph = new ShaderGraph(); DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>(); - diffuse->color = make_float3(0.8f, 0.8f, 0.8f); + diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f)); graph->add(diffuse); graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface")); @@ -658,8 +661,8 @@ void ShaderManager::add_default(Scene *scene) ShaderGraph *graph = new ShaderGraph(); EmissionNode *emission = graph->create_node<EmissionNode>(); - emission->color = make_float3(0.8f, 0.8f, 0.8f); - emission->strength = 0.0f; + emission->set_color(make_float3(0.8f, 0.8f, 0.8f)); + emission->set_strength(0.0f); graph->add(emission); graph->connect(emission->output("Emission"), graph->output()->input("Surface")); @@ -703,10 +706,10 @@ void ShaderManager::get_requested_graph_features(ShaderGraph *graph, requested_features->nodes_features |= node->get_feature(); if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) { BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node); - if (CLOSURE_IS_VOLUME(bsdf_node->closure)) { + if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) { requested_features->nodes_features |= NODE_FEATURE_VOLUME; } - else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) { + else if (CLOSURE_IS_PRINCIPLED(bsdf_node->get_closure_type())) { requested_features->use_principled = true; } } @@ -738,7 +741,7 @@ void ShaderManager::get_requested_features(Scene *scene, ShaderNode *output_node = shader->graph->output(); if (output_node->input("Displacement")->link != NULL) { requested_features->nodes_features |= NODE_FEATURE_BUMP; - if (shader->displacement_method == DISPLACE_BOTH) { + if (shader->get_displacement_method() == DISPLACE_BOTH) { requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE; requested_features->max_nodes_group = max(requested_features->max_nodes_group, NODE_GROUP_LEVEL_1); diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 897b0984a7e..de19048d8e1 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -81,22 +81,25 @@ class Shader : public Node { public: NODE_DECLARE - int pass_id; - /* shader graph */ ShaderGraph *graph; + NODE_SOCKET_API(int, pass_id) + /* sampling */ - bool use_mis; - bool use_transparent_shadow; - bool heterogeneous_volume; - VolumeSampling volume_sampling_method; - int volume_interpolation_method; - float volume_step_rate; + NODE_SOCKET_API(bool, use_mis) + NODE_SOCKET_API(bool, use_transparent_shadow) + NODE_SOCKET_API(bool, heterogeneous_volume) + NODE_SOCKET_API(VolumeSampling, volume_sampling_method) + NODE_SOCKET_API(int, volume_interpolation_method) + NODE_SOCKET_API(float, volume_step_rate) + + /* displacement */ + NODE_SOCKET_API(DisplacementMethod, displacement_method) + float prev_volume_step_rate; /* synchronization */ - bool need_update; bool need_update_geometry; /* If the shader has only volume components, the surface is assumed to @@ -122,9 +125,6 @@ class Shader : public Node { bool has_volume_attribute_dependency; bool has_integrator_dependency; - /* displacement */ - DisplacementMethod displacement_method; - /* requested mesh attributes */ AttributeRequestSet attributes; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index d66744d06be..b2bc17aec19 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -123,8 +123,8 @@ void SVMShaderManager::device_update(Device *device, for (int i = 0; i < num_shaders; i++) { Shader *shader = scene->shaders[i]; - shader->need_update = false; - if (shader->use_mis && shader->has_surface_emission) { + shader->clear_modified(); + if (shader->get_use_mis() && shader->has_surface_emission) { scene->light_manager->need_update = true; } @@ -749,7 +749,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty /* for the bump shader we need add a node to store the shader state */ bool need_bump_state = (type == SHADER_TYPE_BUMP) && - (shader->displacement_method == DISPLACE_BOTH); + (shader->get_displacement_method() == DISPLACE_BOTH); int bump_state_offset = SVM_STACK_INVALID; if (need_bump_state) { bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE); @@ -840,7 +840,7 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum const double time_start = time_dt(); - bool has_bump = (shader->displacement_method != DISPLACE_TRUE) && + bool has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) && output->input("Surface")->link && output->input("Displacement")->link; /* finalize */ @@ -849,7 +849,7 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum shader->graph->finalize(scene, has_bump, shader->has_integrator_dependency, - shader->displacement_method == DISPLACE_BOTH); + shader->get_displacement_method() == DISPLACE_BOTH); } current_shader = shader; diff --git a/intern/cycles/render/volume.cpp b/intern/cycles/render/volume.cpp index ebb9752756e..85624d9af65 100644 --- a/intern/cycles/render/volume.cpp +++ b/intern/cycles/render/volume.cpp @@ -36,11 +36,7 @@ CCL_NAMESPACE_BEGIN NODE_DEFINE(Volume) { - NodeType *type = NodeType::add("volume", 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>()); + NodeType *type = NodeType::add("volume", create, NodeType::NONE, Mesh::node_type); SOCKET_FLOAT(clipping, "Clipping", 0.001f); SOCKET_FLOAT(step_size, "Step Size", 0.0f); @@ -56,9 +52,9 @@ Volume::Volume() : Mesh(node_type, Geometry::VOLUME) object_space = false; } -void Volume::clear() +void Volume::clear(bool preserve_shaders) { - Mesh::clear(true); + Mesh::clear(preserve_shaders, true); } struct QuadData { @@ -503,17 +499,19 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress) Shader *volume_shader = NULL; int pad_size = 0; - foreach (Shader *shader, volume->used_shaders) { + foreach (Node *node, volume->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + if (!shader->has_volume) { continue; } volume_shader = shader; - if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) { + if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_LINEAR) { pad_size = max(1, pad_size); } - else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) { + else if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) { pad_size = max(2, pad_size); } @@ -558,20 +556,20 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress) if (image_memory->data_elements == 1) { grid = openvdb_grid_from_device_texture<openvdb::FloatGrid>( - image_memory, volume->clipping, handle.metadata().transform_3d); + image_memory, volume->get_clipping(), handle.metadata().transform_3d); } else if (image_memory->data_elements == 3) { grid = openvdb_grid_from_device_texture<openvdb::Vec3fGrid>( - image_memory, volume->clipping, handle.metadata().transform_3d); + image_memory, volume->get_clipping(), handle.metadata().transform_3d); } else if (image_memory->data_elements == 4) { grid = openvdb_grid_from_device_texture<openvdb::Vec4fGrid>( - image_memory, volume->clipping, handle.metadata().transform_3d); + image_memory, volume->get_clipping(), handle.metadata().transform_3d); } } if (grid) { - builder.add_grid(grid, do_clipping, volume->clipping); + builder.add_grid(grid, do_clipping, volume->get_clipping()); } } #endif @@ -597,7 +595,8 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress) builder.create_mesh(vertices, indices, face_normals, face_overlap_avoidance); volume->reserve_mesh(vertices.size(), indices.size() / 3); - volume->used_shaders.push_back(volume_shader); + volume->used_shaders.clear(); + volume->used_shaders.push_back_slow(volume_shader); for (size_t i = 0; i < vertices.size(); ++i) { volume->add_vertex(vertices[i]); diff --git a/intern/cycles/render/volume.h b/intern/cycles/render/volume.h index 05157eb948f..2e9703bf7ed 100644 --- a/intern/cycles/render/volume.h +++ b/intern/cycles/render/volume.h @@ -28,11 +28,11 @@ class Volume : public Mesh { Volume(); - float clipping; - float step_size; - bool object_space; + NODE_SOCKET_API(float, clipping) + NODE_SOCKET_API(float, step_size) + NODE_SOCKET_API(bool, object_space) - virtual void clear() override; + virtual void clear(bool preserve_shaders = false) override; }; CCL_NAMESPACE_END diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 91c7f4bea05..4efdb98aa0f 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -42,11 +42,11 @@ void EdgeDice::reserve(int num_verts, int num_triangles) { Mesh *mesh = params.mesh; - vert_offset = mesh->verts.size(); + vert_offset = mesh->get_verts().size(); tri_offset = mesh->num_triangles(); - mesh->resize_mesh(mesh->verts.size() + num_verts, mesh->num_triangles()); - mesh->reserve_mesh(mesh->verts.size() + num_verts, mesh->num_triangles() + num_triangles); + mesh->resize_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles()); + mesh->reserve_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles() + num_triangles); Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index 1a8c182510c..928f5bf2ed7 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -341,8 +341,8 @@ void DiagSplit::split_patches(Patch *patches, size_t patches_byte_stride) { int patch_index = 0; - for (int f = 0; f < params.mesh->subd_faces.size(); f++) { - Mesh::SubdFace &face = params.mesh->subd_faces[f]; + for (int f = 0; f < params.mesh->get_num_subd_faces(); f++) { + Mesh::SubdFace face = params.mesh->get_subd_face(f); Patch *patch = (Patch *)(((char *)patches) + patch_index * patches_byte_stride); @@ -372,8 +372,8 @@ static Edge *create_edge_from_corner(DiagSplit *split, int v0, int v1) { - int a = mesh->subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]; - int b = mesh->subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]; + int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)]; + int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)]; reversed = !(b < a); @@ -443,8 +443,8 @@ static Edge *create_split_edge_from_corner(DiagSplit *split, { Edge *edge = split->alloc_edge(); - int a = mesh->subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]; - int b = mesh->subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]; + int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)]; + int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)]; if (b < a) { edge->stitch_edge_key = {b, a}; diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index 4639fc6d0dd..3eaec982d09 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -64,9 +64,11 @@ template<typename T> class ShaderNodeBuilder { return *this; } - template<typename T2, typename V> ShaderNodeBuilder &set(V T2::*pfield, V value) + template<typename V> ShaderNodeBuilder &set_param(const string &input_name, V value) { - static_cast<T *>(node_)->*pfield = value; + const SocketType *input_socket = node_->type->find_input(ustring(input_name.c_str())); + EXPECT_NE((void *)NULL, input_socket); + node_->set(*input_socket, value); return *this; } @@ -121,8 +123,8 @@ class ShaderGraphBuilder { /* Common input/output boilerplate. */ ShaderGraphBuilder &add_attribute(const string &name) { - return (*this).add_node(ShaderNodeBuilder<AttributeNode>(*graph_, name) - .set(&AttributeNode::attribute, ustring(name))); + return (*this).add_node( + ShaderNodeBuilder<AttributeNode>(*graph_, name).set_param("attribute", ustring(name))); } ShaderGraphBuilder &output_closure(const string &from) @@ -210,12 +212,12 @@ TEST_F(RenderGraph, deduplicate_deep) builder.add_node(ShaderNodeBuilder<GeometryNode>(graph, "Geometry1")) .add_node(ShaderNodeBuilder<GeometryNode>(graph, "Geometry2")) - .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value1").set(&ValueNode::value, 0.8f)) - .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value2").set(&ValueNode::value, 0.8f)) + .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value1").set_param("value", 0.8f)) + .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value2").set_param("value", 0.8f)) .add_node(ShaderNodeBuilder<NoiseTextureNode>(graph, "Noise1")) .add_node(ShaderNodeBuilder<NoiseTextureNode>(graph, "Noise2")) .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_BLEND) + .set_param("mix_type", NODE_MIX_BLEND) .set("Fac", 0.5f)) .add_connection("Geometry1::Parametric", "Noise1::Vector") .add_connection("Value1::Value", "Noise1::Scale") @@ -422,8 +424,8 @@ TEST_F(RenderGraph, constant_fold_mix_add) builder .add_node(ShaderNodeBuilder<MixNode>(graph, "MixAdd") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", false) .set("Fac", 0.8f) .set("Color1", make_float3(0.3f, 0.5f, 0.7f)) .set("Color2", make_float3(0.4f, 0.8f, 0.9f))) @@ -443,8 +445,8 @@ TEST_F(RenderGraph, constant_fold_mix_add_clamp) builder .add_node(ShaderNodeBuilder<MixNode>(graph, "MixAdd") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 0.8f) .set("Color1", make_float3(0.3f, 0.5f, 0.7f)) .set("Color2", make_float3(0.4f, 0.8f, 0.9f))) @@ -465,8 +467,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_dodge_no_fac_0) builder.add_attribute("Attribute1") .add_attribute("Attribute2") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_DODGE) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_DODGE) + .set_param("use_clamp", false) .set("Fac", 0.0f)) .add_connection("Attribute1::Color", "Mix::Color1") .add_connection("Attribute2::Color", "Mix::Color2") @@ -487,8 +489,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_light_no_fac_0) builder.add_attribute("Attribute1") .add_attribute("Attribute2") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_LIGHT) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_LIGHT) + .set_param("use_clamp", false) .set("Fac", 0.0f)) .add_connection("Attribute1::Color", "Mix::Color1") .add_connection("Attribute2::Color", "Mix::Color2") @@ -509,8 +511,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_burn_no_fac_0) builder.add_attribute("Attribute1") .add_attribute("Attribute2") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_BURN) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_BURN) + .set_param("use_clamp", false) .set("Fac", 0.0f)) .add_connection("Attribute1::Color", "Mix::Color1") .add_connection("Attribute2::Color", "Mix::Color2") @@ -531,8 +533,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend_clamped_no_fac_0) builder.add_attribute("Attribute1") .add_attribute("Attribute2") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_BLEND) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_BLEND) + .set_param("use_clamp", true) .set("Fac", 0.0f)) .add_connection("Attribute1::Color", "Mix::Color1") .add_connection("Attribute2::Color", "Mix::Color2") @@ -557,22 +559,22 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend) .add_attribute("Attribute2") /* choose left */ .add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend1") - .set(&MixNode::type, NODE_MIX_BLEND) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_BLEND) + .set_param("use_clamp", false) .set("Fac", 0.0f)) .add_connection("Attribute1::Color", "MixBlend1::Color1") .add_connection("Attribute2::Color", "MixBlend1::Color2") /* choose right */ .add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend2") - .set(&MixNode::type, NODE_MIX_BLEND) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", NODE_MIX_BLEND) + .set_param("use_clamp", false) .set("Fac", 1.0f)) .add_connection("Attribute1::Color", "MixBlend2::Color2") .add_connection("Attribute2::Color", "MixBlend2::Color1") /* both inputs folded to Attribute1 */ .add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend3") - .set(&MixNode::type, NODE_MIX_BLEND) - .set(&MixNode::use_clamp, false)) + .set_param("mix_type", NODE_MIX_BLEND) + .set_param("use_clamp", false)) .add_connection("Attribute1::Fac", "MixBlend3::Fac") .add_connection("MixBlend1::Color", "MixBlend3::Color1") .add_connection("MixBlend2::Color", "MixBlend3::Color2") @@ -592,8 +594,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_bad) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_SUB) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_SUB) + .set_param("use_clamp", true) .set("Fac", 0.5f)) .add_connection("Attribute::Color", "Mix::Color1") .add_connection("Attribute::Color", "Mix::Color2") @@ -613,8 +615,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_1) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix") - .set(&MixNode::type, NODE_MIX_SUB) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_SUB) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_connection("Attribute::Color", "Mix::Color1") .add_connection("Attribute::Color", "Mix::Color2") @@ -635,12 +637,12 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, .add_attribute("Attribute") /* constant on the left */ .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_Cx_Fx") - .set(&MixNode::type, type) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", type) + .set_param("use_clamp", false) .set("Color1", constval)) .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_Cx_F1") - .set(&MixNode::type, type) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", type) + .set_param("use_clamp", false) .set("Color1", constval) .set("Fac", 1.0f)) .add_connection("Attribute::Fac", "Mix_Cx_Fx::Fac") @@ -648,12 +650,12 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, .add_connection("Attribute::Color", "Mix_Cx_F1::Color2") /* constant on the right */ .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_xC_Fx") - .set(&MixNode::type, type) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", type) + .set_param("use_clamp", false) .set("Color2", constval)) .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_xC_F1") - .set(&MixNode::type, type) - .set(&MixNode::use_clamp, false) + .set_param("mix_type", type) + .set_param("use_clamp", false) .set("Color2", constval) .set("Fac", 1.0f)) .add_connection("Attribute::Fac", "Mix_xC_Fx::Fac") @@ -661,16 +663,16 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, .add_connection("Attribute::Color", "Mix_xC_F1::Color1") /* results of actual tests simply added up to connect to output */ .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out12") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out34") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out1234") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_connection("Mix_Cx_Fx::Color", "Out12::Color1") .add_connection("Mix_Cx_F1::Color", "Out12::Color2") @@ -898,8 +900,8 @@ TEST_F(RenderGraph, constant_fold_gamma_part_0) .add_connection("Attribute::Color", "Gamma_xC::Color") /* output sum */ .add_node(ShaderNodeBuilder<MixNode>(graph, "Out") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_connection("Gamma_Cx::Color", "Out::Color1") .add_connection("Gamma_xC::Color", "Out::Color2") @@ -928,8 +930,8 @@ TEST_F(RenderGraph, constant_fold_gamma_part_1) .add_connection("Attribute::Color", "Gamma_xC::Color") /* output sum */ .add_node(ShaderNodeBuilder<MixNode>(graph, "Out") - .set(&MixNode::type, NODE_MIX_ADD) - .set(&MixNode::use_clamp, true) + .set_param("mix_type", NODE_MIX_ADD) + .set_param("use_clamp", true) .set("Fac", 1.0f)) .add_connection("Gamma_Cx::Color", "Out::Color1") .add_connection("Gamma_xC::Color", "Out::Color2") @@ -988,8 +990,8 @@ TEST_F(RenderGraph, constant_fold_math) builder .add_node(ShaderNodeBuilder<MathNode>(graph, "Math") - .set(&MathNode::type, NODE_MATH_ADD) - .set(&MathNode::use_clamp, false) + .set_param("math_type", NODE_MATH_ADD) + .set_param("use_clamp", false) .set("Value1", 0.7f) .set("Value2", 0.9f)) .output_value("Math::Value"); @@ -1007,8 +1009,8 @@ TEST_F(RenderGraph, constant_fold_math_clamp) builder .add_node(ShaderNodeBuilder<MathNode>(graph, "Math") - .set(&MathNode::type, NODE_MATH_ADD) - .set(&MathNode::use_clamp, true) + .set_param("math_type", NODE_MATH_ADD) + .set_param("use_clamp", true) .set("Value1", 0.7f) .set("Value2", 0.9f)) .output_value("Math::Value"); @@ -1028,20 +1030,20 @@ static void build_math_partial_test_graph(ShaderGraphBuilder &builder, .add_attribute("Attribute") /* constant on the left */ .add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Math_Cx") - .set(&MathNode::type, type) - .set(&MathNode::use_clamp, false) + .set_param("math_type", type) + .set_param("use_clamp", false) .set("Value1", constval)) .add_connection("Attribute::Fac", "Math_Cx::Value2") /* constant on the right */ .add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Math_xC") - .set(&MathNode::type, type) - .set(&MathNode::use_clamp, false) + .set_param("math_type", type) + .set_param("use_clamp", false) .set("Value2", constval)) .add_connection("Attribute::Fac", "Math_xC::Value1") /* output sum */ .add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Out") - .set(&MathNode::type, NODE_MATH_ADD) - .set(&MathNode::use_clamp, true)) + .set_param("math_type", NODE_MATH_ADD) + .set_param("use_clamp", true)) .add_connection("Math_Cx::Value", "Out::Value1") .add_connection("Math_xC::Value", "Out::Value2") .output_value("Out::Value"); @@ -1178,7 +1180,7 @@ TEST_F(RenderGraph, constant_fold_vector_math) builder .add_node(ShaderNodeBuilder<VectorMathNode>(graph, "VectorMath") - .set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT) + .set_param("math_type", NODE_VECTOR_MATH_SUBTRACT) .set("Vector1", make_float3(1.3f, 0.5f, 0.7f)) .set("Vector2", make_float3(-1.7f, 0.5f, 0.7f))) .output_color("VectorMath::Vector"); @@ -1198,17 +1200,17 @@ static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder, .add_attribute("Attribute") /* constant on the left */ .add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Math_Cx") - .set(&VectorMathNode::type, type) + .set_param("math_type", type) .set("Vector1", constval)) .add_connection("Attribute::Vector", "Math_Cx::Vector2") /* constant on the right */ .add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Math_xC") - .set(&VectorMathNode::type, type) + .set_param("math_type", type) .set("Vector2", constval)) .add_connection("Attribute::Vector", "Math_xC::Vector1") /* output sum */ .add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Out") - .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD)) + .set_param("math_type", NODE_VECTOR_MATH_ADD)) .add_connection("Math_Cx::Vector", "Out::Vector1") .add_connection("Math_xC::Vector", "Out::Vector2") .output_color("Out::Vector"); @@ -1312,9 +1314,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves) builder .add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves") - .set(&CurvesNode::curves, curve) - .set(&CurvesNode::min_x, 0.1f) - .set(&CurvesNode::max_x, 0.9f) + .set_param("curves", curve) + .set_param("min_x", 0.1f) + .set_param("max_x", 0.9f) .set("Fac", 0.5f) .set("Color", make_float3(0.3f, 0.5f, 0.7f))) .output_color("Curves::Color"); @@ -1336,9 +1338,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves") - .set(&CurvesNode::curves, curve) - .set(&CurvesNode::min_x, 0.1f) - .set(&CurvesNode::max_x, 0.9f) + .set_param("curves", curve) + .set_param("min_x", 0.1f) + .set_param("max_x", 0.9f) .set("Fac", 0.0f)) .add_connection("Attribute::Color", "Curves::Color") .output_color("Curves::Color"); @@ -1360,9 +1362,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0_const) builder .add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves") - .set(&CurvesNode::curves, curve) - .set(&CurvesNode::min_x, 0.1f) - .set(&CurvesNode::max_x, 0.9f) + .set_param("curves", curve) + .set_param("min_x", 0.1f) + .set_param("max_x", 0.9f) .set("Fac", 0.0f) .set("Color", make_float3(0.3f, 0.5f, 0.7f))) .output_color("Curves::Color"); @@ -1384,9 +1386,9 @@ TEST_F(RenderGraph, constant_fold_vector_curves) builder .add_node(ShaderNodeBuilder<VectorCurvesNode>(graph, "Curves") - .set(&CurvesNode::curves, curve) - .set(&CurvesNode::min_x, 0.1f) - .set(&CurvesNode::max_x, 0.9f) + .set_param("curves", curve) + .set_param("min_x", 0.1f) + .set_param("max_x", 0.9f) .set("Fac", 0.5f) .set("Vector", make_float3(0.3f, 0.5f, 0.7f))) .output_color("Curves::Vector"); @@ -1408,9 +1410,9 @@ TEST_F(RenderGraph, constant_fold_vector_curves_fac_0) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<VectorCurvesNode>(graph, "Curves") - .set(&CurvesNode::curves, curve) - .set(&CurvesNode::min_x, 0.1f) - .set(&CurvesNode::max_x, 0.9f) + .set_param("curves", curve) + .set_param("min_x", 0.1f) + .set_param("max_x", 0.9f) .set("Fac", 0.0f)) .add_connection("Attribute::Vector", "Curves::Vector") .output_color("Curves::Vector"); @@ -1435,11 +1437,11 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp) builder .add_node(ShaderNodeBuilder<RGBRampNode>(graph, "Ramp") - .set(&RGBRampNode::ramp, curve) - .set(&RGBRampNode::ramp_alpha, alpha) - .set(&RGBRampNode::interpolate, true) + .set_param("ramp", curve) + .set_param("ramp_alpha", alpha) + .set_param("interpolate", true) .set("Fac", 0.56f)) - .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set(&MixNode::type, NODE_MIX_ADD)) + .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set_param("mix_type", NODE_MIX_ADD)) .add_connection("Ramp::Color", "Mix::Color1") .add_connection("Ramp::Alpha", "Mix::Color2") .output_color("Mix::Color"); @@ -1464,11 +1466,11 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp_flat) builder .add_node(ShaderNodeBuilder<RGBRampNode>(graph, "Ramp") - .set(&RGBRampNode::ramp, curve) - .set(&RGBRampNode::ramp_alpha, alpha) - .set(&RGBRampNode::interpolate, false) + .set_param("ramp", curve) + .set_param("ramp_alpha", alpha) + .set_param("interpolate", false) .set("Fac", 0.56f)) - .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set(&MixNode::type, NODE_MIX_ADD)) + .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set_param("mix_type", NODE_MIX_ADD)) .add_connection("Ramp::Color", "Mix::Color1") .add_connection("Ramp::Alpha", "Mix::Color2") .output_color("Mix::Color"); @@ -1510,7 +1512,7 @@ TEST_F(RenderGraph, constant_fold_convert_color_vector_color) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<VectorMathNode>(graph, "VecAdd") - .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD) + .set_param("math_type", NODE_VECTOR_MATH_ADD) .set("Vector2", make_float3(0, 0, 0))) .add_connection("Attribute::Color", "VecAdd::Vector1") .output_color("VecAdd::Vector"); @@ -1531,7 +1533,7 @@ TEST_F(RenderGraph, constant_fold_convert_color_float_color) builder.add_attribute("Attribute") .add_node(ShaderNodeBuilder<MathNode>(graph, "MathAdd") - .set(&MathNode::type, NODE_MATH_ADD) + .set_param("math_type", NODE_MATH_ADD) .set("Value2", 0.0f)) .add_connection("Attribute::Color", "MathAdd::Value1") .output_color("MathAdd::Value"); diff --git a/intern/cycles/util/util_array.h b/intern/cycles/util/util_array.h index db80ab474e0..ea481787018 100644 --- a/intern/cycles/util/util_array.h +++ b/intern/cycles/util/util_array.h @@ -213,6 +213,26 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra return data_[i]; } + T *begin() + { + return data_; + } + + const T *begin() const + { + return data_; + } + + T *end() + { + return data_ + datasize_; + } + + const T *end() const + { + return data_ + datasize_; + } + void reserve(size_t newcapacity) { if (newcapacity > capacity_) { diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index a721595667d..fc80fa9696c 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -53,7 +53,7 @@ typedef unsigned short ushort; /* Fixed Bits Types */ #ifdef __KERNEL_OPENCL__ -typedef ulong uint64_t; +typedef unsigned long uint64_t; #endif #ifndef __KERNEL_GPU__ diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 77e777db872..4a2a12932fe 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -332,7 +332,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) elseif(WIN32) # # Warnings as errors, this is too strict! # if(MSVC) - # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + # string(APPEND CMAKE_CXX_FLAGS " /WX") # endif() list(APPEND INC_SYS diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 2046b55c97f..64740b68c0c 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -31,8 +31,8 @@ extern "C" { /** * Definition of a callback routine that receives events. - * \param event The event received. - * \param userdata The callback's user data, supplied to GHOST_CreateSystem. + * \param event: The event received. + * \param userdata: The callback's user data, supplied to #GHOST_CreateSystem. */ typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata); @@ -49,21 +49,20 @@ extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, int is_debug_ /** * Disposes the one and only system. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. * \return An indication of success. */ extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle); /** * Show a system message box to the user - * \param systemhandle The handle to the system - * \param title Title of the message box - * \param message Message of the message box - * \param help_label Text to show on the help button that opens a link - * \param continue_label Text to show on the ok button that continues - * \param link Optional (hyper)link to a webpage to show when pressing help - * \param dialog_options Options to configure the message box. - * \return void. + * \param systemhandle: The handle to the system. + * \param title: Title of the message box. + * \param message: Message of the message box. + * \param help_label: Text to show on the help button that opens a link. + * \param continue_label: Text to show on the ok button that continues. + * \param link: Optional (hyper)link to a webpage to show when pressing help. + * \param dialog_options: Options to configure the message box. */ extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle, const char *title, @@ -75,15 +74,15 @@ extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle, /** * Creates an event consumer object - * \param eventCallback The event callback routine. - * \param userdata Pointer to user data returned to the callback routine. + * \param eventCallback: The event callback routine. + * \param userdata: Pointer to user data returned to the callback routine. */ extern GHOST_EventConsumerHandle GHOST_CreateEventConsumer( GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata); /** * Disposes an event consumer object - * \param consumerhandle Handle to the event consumer. + * \param consumerhandle: Handle to the event consumer. * \return An indication of success. */ extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle); @@ -92,7 +91,7 @@ extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consu * Returns the system time. * Returns the number of milliseconds since the start of the system process. * Based on ANSI clock() routine. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. * \return The number of milliseconds. */ extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); @@ -101,11 +100,11 @@ extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); * Installs a timer. * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * \param systemhandle The handle to the system - * \param delay The time to wait for the first call to the timerProc (in milliseconds) - * \param interval The interval between calls to the timerProc (in milliseconds) - * \param timerProc The callback invoked when the interval expires, - * \param userData Placeholder for user data. + * \param systemhandle: The handle to the system. + * \param delay: The time to wait for the first call to the timerProc (in milliseconds). + * \param interval: The interval between calls to the timerProc (in milliseconds). + * \param timerProc: The callback invoked when the interval expires. + * \param userData: Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, @@ -116,8 +115,8 @@ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, /** * Removes a timer. - * \param systemhandle The handle to the system - * \param timertaskhandle Timer task to be removed. + * \param systemhandle: The handle to the system. + * \param timertaskhandle: Timer task to be removed. * \return Indication of success. */ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, @@ -129,17 +128,16 @@ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, /** * Returns the number of displays on this system. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. * \return The number of displays. */ extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle); /** * Returns the dimensions of the main display on this system. - * \param systemhandle The handle to the system - * \param width A pointer the width gets put in - * \param height A pointer the height gets put in - * \return void. + * \param systemhandle: The handle to the system. + * \param width: A pointer the width gets put in. + * \param height: A pointer the height gets put in. */ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, GHOST_TUns32 *width, @@ -149,10 +147,9 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, * Returns the dimensions of all displays combine * (the current workspace). * No need to worry about overlapping monitors. - * \param systemhandle The handle to the system - * \param width A pointer the width gets put in - * \param height A pointer the height gets put in - * \return void. + * \param systemhandle: The handle to the system. + * \param width: A pointer the width gets put in. + * \param height: A pointer the height gets put in. */ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, GHOST_TUns32 *width, @@ -162,15 +159,15 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * \param systemhandle The handle to the system - * \param title The name of the window + * \param systemhandle: The handle to the system. + * \param title: The name of the window. * (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state of the window when opened. + * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL options. * \return A handle to the new window ( == NULL if creation failed). */ @@ -198,8 +195,8 @@ extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhand /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \param systemhandle The handle to the system - * \param platform_support_callback An optional callback to check platform support + * \param systemhandle: The handle to the system. + * \param platform_support_callback: An optional callback to check platform support. * \return A handle to the new context ( == NULL if creation failed). */ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle, @@ -207,8 +204,8 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha /** * Dispose of a context. - * \param systemhandle The handle to the system - * \param contexthandle Handle to the context to be disposed. + * \param systemhandle: The handle to the system. + * \param contexthandle: Handle to the context to be disposed. * \return Indication of success. */ extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle, @@ -216,15 +213,15 @@ extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle /** * Returns the window user data. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The window user data. */ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle); /** * Changes the window user data. - * \param windowhandle The handle to the window - * \param userdata The window user data. + * \param windowhandle: The handle to the window. + * \param userdata: The window user data. */ extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata); @@ -232,8 +229,8 @@ extern int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle); /** * Dispose a window. - * \param systemhandle The handle to the system - * \param windowhandle Handle to the window to be disposed. + * \param systemhandle: The handle to the system. + * \param windowhandle: Handle to the window to be disposed. * \return Indication of success. */ extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, @@ -241,17 +238,17 @@ extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, /** * Returns whether a window is valid. - * \param systemhandle The handle to the system - * \param windowhandle Handle to the window to be checked. + * \param systemhandle: The handle to the system. + * \param windowhandle: Handle to the window to be checked. * \return Indication of validity. */ extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle); /** * Begins full screen mode. - * \param systemhandle The handle to the system - * \param setting The new setting of the display. - * \param stereoVisual Option for stereo display. + * \param systemhandle: The handle to the system. + * \param setting: The new setting of the display. + * \param stereoVisual: Option for stereo display. * \return A handle to the window displayed in full screen. * This window is invalid after full screen has been ended. */ @@ -261,14 +258,14 @@ extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle, /** * Ends full screen mode. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. * \return Indication of success. */ extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle); /** * Returns current full screen mode status. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. * \return The current status. */ extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle); @@ -279,8 +276,8 @@ extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle); /** * Retrieves events from the system and stores them in the queue. - * \param systemhandle The handle to the system - * \param waitForEvent Boolean to indicate that ProcessEvents should + * \param systemhandle: The handle to the system. + * \param waitForEvent: Boolean to indicate that #ProcessEvents should. * wait (block) until the next event before returning. * \return Indication of the presence of events. */ @@ -288,14 +285,14 @@ extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent /** * Retrieves events from the queue and send them to the event consumers. - * \param systemhandle The handle to the system + * \param systemhandle: The handle to the system. */ extern void GHOST_DispatchEvents(GHOST_SystemHandle systemhandle); /** * Adds the given event consumer to our list. - * \param systemhandle The handle to the system - * \param consumerhandle The event consumer to add. + * \param systemhandle: The handle to the system. + * \param consumerhandle: The event consumer to add. * \return Indication of success. */ extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, @@ -303,8 +300,8 @@ extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, /** * Remove the given event consumer to our list. - * \param systemhandle The handle to the system - * \param consumerhandle The event consumer to remove. + * \param systemhandle: The handle to the system. + * \param consumerhandle: The event consumer to remove. * \return Indication of success. */ extern GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle, @@ -316,14 +313,14 @@ extern GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle, /** * Sets the progress bar value displayed in the window/application icon - * \param windowhandle The handle to the window - * \param progress The progress % (0.0 to 1.0) + * \param windowhandle: The handle to the window. + * \param progress: The progress percentage (0.0 to 1.0). */ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, float progress); /** * Hides the progress bar in the icon - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. */ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); @@ -333,7 +330,7 @@ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); /** * Returns the current cursor shape. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The current cursor shape. */ extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle); @@ -341,8 +338,8 @@ extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandl /** * Set the shape of the cursor. If the shape is not supported by the platform, * it will use the default cursor instead. - * \param windowhandle The handle to the window - * \param cursorshape The new cursor shape type id. + * \param windowhandle: The handle to the window. + * \param cursorshape: The new cursor shape type id. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle, @@ -357,14 +354,14 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle, /** * Set the shape of the cursor to a custom cursor of specified size. - * \param windowhandle The handle to the window - * \param bitmap The bitmap data for the cursor. - * \param mask The mask data for the cursor. - * \param sizex The width of the cursor - * \param sizey The height of the cursor - * \param hotX The X coordinate of the cursor hot-spot. - * \param hotY The Y coordinate of the cursor hot-spot. - * \param canInvertColor Let macOS invert cursor color to match platform convention. + * \param windowhandle: The handle to the window. + * \param bitmap: The bitmap data for the cursor. + * \param mask: The mask data for the cursor. + * \param sizex: The width of the cursor. + * \param sizey: The height of the cursor. + * \param hotX: The X coordinate of the cursor hot-spot. + * \param hotY: The Y coordinate of the cursor hot-spot. + * \param canInvertColor: Let macOS invert cursor color to match platform convention. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, @@ -378,24 +375,24 @@ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle /** * Returns the visibility state of the cursor. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The visibility state of the cursor. */ extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle); /** * Shows or hides the cursor. - * \param windowhandle The handle to the window - * \param visible The new visibility state of the cursor. + * \param windowhandle: The handle to the window. + * \param visible: The new visibility state of the cursor. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int visible); /** * Returns the current location of the cursor (location in screen coordinates) - * \param systemhandle The handle to the system - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. + * \param systemhandle: The handle to the system. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. * \return Indication of success. */ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, @@ -405,9 +402,9 @@ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, /** * Updates the location of the cursor (location in screen coordinates). * Not all operating systems allow the cursor to be moved (without the input device being moved). - * \param systemhandle The handle to the system - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. + * \param systemhandle: The handle to the system. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, @@ -418,10 +415,10 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, * Grabs the cursor for a modal operation, to keep receiving * events when the mouse is outside the window. X11 only, others * do this automatically. - * \param windowhandle The handle to the window - * \param mode The new grab state of the cursor. - * \param bounds The grab region (optional) - left,top,right,bottom - * \param mouse_ungrab_xy XY for new mouse location (optional) - x,y + * \param windowhandle: The handle to the window. + * \param mode: The new grab state of the cursor. + * \param bounds: The grab region (optional) - left,top,right,bottom. + * \param mouse_ungrab_xy: XY for new mouse location (optional). * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, @@ -436,9 +433,9 @@ extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, /** * Returns the state of a modifier key (outside the message queue). - * \param systemhandle The handle to the system - * \param mask The modifier key state to retrieve. - * \param isDown Pointer to return modifier state in. + * \param systemhandle: The handle to the system. + * \param mask: The modifier key state to retrieve. + * \param isDown: Pointer to return modifier state in. * \return Indication of success. */ extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, @@ -447,9 +444,9 @@ extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, /** * Returns the state of a mouse button (outside the message queue). - * \param systemhandle The handle to the system - * \param mask The button state to retrieve. - * \param isDown Pointer to return button state in. + * \param systemhandle: The handle to the system. + * \param mask: The button state to retrieve. + * \param isDown: Pointer to return button state in. * \return Indication of success. */ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, @@ -479,14 +476,14 @@ extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_ /** * Returns the event type. - * \param eventhandle The handle to the event + * \param eventhandle: The handle to the event. * \return The event type. */ extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle); /** * Returns the time this event was generated. - * \param eventhandle The handle to the event + * \param eventhandle: The handle to the event. * \return The event generation time. */ extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle); @@ -494,66 +491,66 @@ extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle); /** * Returns the window this event was generated on, * or NULL if it is a 'system' event. - * \param eventhandle The handle to the event + * \param eventhandle: The handle to the event. * \return The generating window. */ extern GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle); /** * Returns the event data. - * \param eventhandle The handle to the event + * \param eventhandle: The handle to the event. * \return The event data. */ extern GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle); /** * Returns the timer callback. - * \param timertaskhandle The handle to the timer-task. + * \param timertaskhandle: The handle to the timer-task. * \return The timer callback. */ extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle); /** * Changes the timer callback. - * \param timertaskhandle The handle to the timertask - * \param timerProc The timer callback. + * \param timertaskhandle: The handle to the timertask. + * \param timerProc: The timer callback. */ extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle, GHOST_TimerProcPtr timerProc); /** * Returns the timer user data. - * \param timertaskhandle The handle to the timertask + * \param timertaskhandle: The handle to the timertask. * \return The timer user data. */ extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle); /** * Changes the time user data. - * \param timertaskhandle The handle to the timertask - * \param userdata The timer user data. + * \param timertaskhandle: The handle to the timertask. + * \param userdata: The timer user data. */ extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, GHOST_TUserDataPtr userdata); /** * Returns indication as to whether the window is valid. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The validity of the window. */ extern int GHOST_GetValid(GHOST_WindowHandle windowhandle); /** * Returns the type of drawing context used in this window. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The current type of drawing context. */ extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle); /** * Tries to install a rendering context in this window. - * \param windowhandle The handle to the window - * \param type The type of rendering context installed. + * \param windowhandle: The handle to the window. + * \param type: The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle, @@ -561,8 +558,8 @@ extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandl /** * Sets the title displayed in the title bar. - * \param windowhandle The handle to the window - * \param title The title to display in the title bar. + * \param windowhandle: The handle to the window. + * \param title: The title to display in the title bar. */ extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title); @@ -570,7 +567,7 @@ extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title); * Returns the title displayed in the title bar. The title * should be free'd with free(). * - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The title, free with free(). */ extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle); @@ -578,7 +575,7 @@ extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle); /** * Returns the window rectangle dimensions. * These are screen coordinates. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return A handle to the bounding rectangle of the window. */ extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle); @@ -586,38 +583,38 @@ extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhand /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return A handle to the bounding rectangle of the window. */ extern GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle); /** - * Disposes a rectangle object - * \param rectanglehandle Handle to the rectangle. + * Disposes a rectangle object. + * \param rectanglehandle: Handle to the rectangle. */ void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle); /** * Resizes client rectangle width. - * \param windowhandle The handle to the window - * \param width The new width of the client area of the window. + * \param windowhandle: The handle to the window. + * \param width: The new width of the client area of the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width); /** * Resizes client rectangle height. - * \param windowhandle The handle to the window - * \param height The new height of the client area of the window. + * \param windowhandle: The handle to the window. + * \param height: The new height of the client area of the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height); /** * Resizes client rectangle. - * \param windowhandle The handle to the window - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param windowhandle: The handle to the window. + * \param width: The new width of the client area of the window. + * \param height: The new height of the client area of the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, @@ -626,11 +623,11 @@ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, /** * Converts a point in screen coordinates to client rectangle coordinates - * \param windowhandle The handle to the window - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param windowhandle: The handle to the window. + * \param inX: The x-coordinate on the screen. + * \param inY: The y-coordinate on the screen. + * \param outX: The x-coordinate in the client rectangle. + * \param outY: The y-coordinate in the client rectangle. */ extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, GHOST_TInt32 inX, @@ -640,11 +637,11 @@ extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, /** * Converts a point in screen coordinates to client rectangle coordinates - * \param windowhandle The handle to the window - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param windowhandle: The handle to the window. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, GHOST_TInt32 inX, @@ -654,24 +651,24 @@ extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, /** * Returns the state of the window (normal, minimized, maximized). - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return The state of the window. */ extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle); /** * Sets the state of the window (normal, minimized, maximized). - * \param windowhandle The handle to the window - * \param state The state of the window. + * \param windowhandle: The handle to the window. + * \param state: The state of the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, GHOST_TWindowState state); /** - * Sets the window "modified" status, indicating unsaved changes - * \param windowhandle The handle to the window - * \param isUnsavedChanges Unsaved changes or not + * Sets the window "modified" status, indicating unsaved changes. + * \param windowhandle: The handle to the window. + * \param isUnsavedChanges: Unsaved changes or not. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, @@ -679,8 +676,8 @@ extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhand /** * Sets the order of the window (bottom, top). - * \param windowhandle The handle to the window - * \param order The order of the window. + * \param windowhandle: The handle to the window. + * \param order: The order of the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, @@ -688,20 +685,20 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, /** * Swaps front and back buffers of a window. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return A success indicator. */ extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ extern GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interval); /** - * Gets the current swap interval for swapBuffers. + * Gets the current swap interval for #swapBuffers. * \param windowhandle: The handle to the window * \param intervalOut: pointer to location to return swap interval * (left untouched if there is an error) @@ -711,28 +708,28 @@ extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int /** * Activates the drawing context of this window. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return A success indicator. */ extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle); /** * Invalidates the contents of this window. - * \param windowhandle The handle to the window + * \param windowhandle: The handle to the window. * \return Indication of success. */ extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle); /** * Activates the drawing context of this context. - * \param contexthandle The handle to the context + * \param contexthandle: The handle to the context. * \return A success indicator. */ extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle); /** * Release the drawing context bound to this thread. - * \param contexthandle The handle to the context + * \param contexthandle: The handle to the context. * \return A success indicator. */ extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle); @@ -756,32 +753,32 @@ extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHa /** * Set which tablet API to use. Only affects Windows, other platforms have a single API. - * \param systemhandle The handle to the system - * \param api Enum indicating which API to use. + * \param systemhandle: The handle to the system. + * \param api: Enum indicating which API to use. */ extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api); /** * Access to rectangle width. - * \param rectanglehandle The handle to the rectangle + * \param rectanglehandle: The handle to the rectangle. * \return width of the rectangle */ extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle); /** * Access to rectangle height. - * \param rectanglehandle The handle to the rectangle + * \param rectanglehandle: The handle to the rectangle. * \return height of the rectangle */ extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle); /** * Gets all members of the rectangle. - * \param rectanglehandle The handle to the rectangle - * \param l Pointer to return left coordinate in. - * \param t Pointer to return top coordinate in. - * \param r Pointer to return right coordinate in. - * \param b Pointer to return bottom coordinate in. + * \param rectanglehandle: The handle to the rectangle. + * \param l: Pointer to return left coordinate in. + * \param t: Pointer to return top coordinate in. + * \param r: Pointer to return right coordinate in. + * \param b: Pointer to return bottom coordinate in. */ extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 *l, @@ -791,11 +788,11 @@ extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, /** * Sets all members of the rectangle. - * \param rectanglehandle The handle to the rectangle - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param rectanglehandle: The handle to the rectangle. + * \param l: requested left coordinate of the rectangle. + * \param t: requested top coordinate of the rectangle. + * \param r: requested right coordinate of the rectangle. + * \param b: requested bottom coordinate of the rectangle. */ extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 l, @@ -806,7 +803,7 @@ extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, /** * Returns whether this rectangle is empty. * Empty rectangles are rectangles that have width==0 and/or height==0. - * \param rectanglehandle The handle to the rectangle + * \param rectanglehandle: The handle to the rectangle. * \return Success value (true == empty rectangle) */ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle); @@ -815,7 +812,7 @@ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehand * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. * Thus, empty rectangles are valid. - * \param rectanglehandle The handle to the rectangle + * \param rectanglehandle: The handle to the rectangle. * \return Success value (true == valid rectangle) */ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle); @@ -823,25 +820,25 @@ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehand /** * Grows (or shrinks the rectangle). * The method avoids negative insets making the rectangle invalid - * \param rectanglehandle The handle to the rectangle - * \param i The amount of offset given to each extreme (negative values shrink the rectangle). + * \param rectanglehandle: The handle to the rectangle. + * \param i: The amount of offset given to each extreme (negative values shrink the rectangle). */ extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i); /** * Does a union of the rectangle given and this rectangle. * The result is stored in this rectangle. - * \param rectanglehandle The handle to the rectangle - * \param anotherrectanglehandle The rectangle that is input for the union operation. + * \param rectanglehandle: The handle to the rectangle. + * \param anotherrectanglehandle: The rectangle that is input for the union operation. */ extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_RectangleHandle anotherrectanglehandle); /** * Grows the rectangle to included a point. - * \param rectanglehandle The handle to the rectangle - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param rectanglehandle: The handle to the rectangle. + * \param x: The x-coordinate of the point. + * \param y: The y-coordinate of the point. */ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 x, @@ -850,9 +847,9 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, /** * Returns whether the point is inside this rectangle. * Point on the boundary is considered inside. - * \param rectanglehandle The handle to the rectangle - * \param x x-coordinate of point to test. - * \param y y-coordinate of point to test. + * \param rectanglehandle: The handle to the rectangle. + * \param x: x-coordinate of point to test. + * \param y: y-coordinate of point to test. * \return Success value (true if point is inside). */ extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, @@ -861,8 +858,8 @@ extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehan /** * Returns whether the rectangle is inside this rectangle. - * \param rectanglehandle The handle to the rectangle - * \param anotherrectanglehandle The rectangle to test. + * \param rectanglehandle: The handle to the rectangle. + * \param anotherrectanglehandle: The rectangle to test. * \return visibility (not, partially or fully visible). */ extern GHOST_TVisibility GHOST_GetRectangleVisibility( @@ -871,9 +868,9 @@ extern GHOST_TVisibility GHOST_GetRectangleVisibility( /** * Sets rectangle members. * Sets rectangle members such that it is centered at the given location. - * \param rectanglehandle The handle to the rectangle - * \param cx Requested center x-coordinate of the rectangle - * \param cy Requested center y-coordinate of the rectangle + * \param rectanglehandle: The handle to the rectangle. + * \param cx: Requested center x-coordinate of the rectangle. + * \param cy: Requested center y-coordinate of the rectangle. */ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 cx, @@ -883,11 +880,11 @@ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, * Sets rectangle members. * Sets rectangle members such that it is centered at the given location, * with the width requested. - * \param rectanglehandle The handle to the rectangle - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle - * \param w requested width of the rectangle - * \param h requested height of the rectangle + * \param rectanglehandle: The handle to the rectangle. + * \param cx: requested center x-coordinate of the rectangle. + * \param cy: requested center y-coordinate of the rectangle. + * \param w: requested width of the rectangle. + * \param h: requested height of the rectangle. */ extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 cx, @@ -899,8 +896,8 @@ extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, * Clips a rectangle. * Updates the rectangle given such that it will fit within this one. * This can result in an empty rectangle. - * \param rectanglehandle The handle to the rectangle - * \param anotherrectanglehandle The rectangle to clip + * \param rectanglehandle: The handle to the rectangle. + * \param anotherrectanglehandle: The rectangle to clip. * \return Whether clipping has occurred */ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, @@ -908,21 +905,21 @@ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, /** * Return the data from the clipboard - * \param selection Boolean to return the selection instead, X11 only feature. + * \param selection: Boolean to return the selection instead, X11 only feature. * \return clipboard data */ extern GHOST_TUns8 *GHOST_getClipboard(int selection); /** * Put data to the Clipboard - * \param buffer the string buffer to set. - * \param selection Set the selection instead, X11 only feature. + * \param buffer: the string buffer to set. + * \param selection: Set the selection instead, X11 only feature. */ extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection); /** * Toggles console - * \param action + * \param action: * - 0: Hides * - 1: Shows * - 2: Toggles @@ -955,14 +952,14 @@ extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle); /** * Enable IME attached to the given window, i.e. allows user-input * events to be dispatched to the IME. - * \param windowhandle Window handle of the caller - * \param x Requested x-coordinate of the rectangle - * \param y Requested y-coordinate of the rectangle - * \param w Requested width of the rectangle - * \param h Requested height of the rectangle - * \param complete Whether or not to complete the ongoing composition - * true: Start a new composition - * false: Move the IME windows to the given position without finishing it. + * \param windowhandle: Window handle of the caller. + * \param x: Requested x-coordinate of the rectangle. + * \param y: Requested y-coordinate of the rectangle. + * \param w: Requested width of the rectangle. + * \param h: Requested height of the rectangle. + * \param complete: Whether or not to complete the ongoing composition. + * - true: Start a new composition. + * - false: Move the IME windows to the given position without finishing it. */ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle, GHOST_TInt32 x, @@ -973,7 +970,7 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle, /** * Disable the IME attached to the given window, i.e. prohibits any user-input * events from being dispatched to the IME. - * \param windowhandle The window handle of the caller + * \param windowhandle: The window handle of the caller. */ extern void GHOST_EndIME(GHOST_WindowHandle windowhandle); @@ -1071,4 +1068,5 @@ GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context); #ifdef __cplusplus } + #endif diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h index c6316e90ce4..278a9a40bd1 100644 --- a/intern/ghost/GHOST_IContext.h +++ b/intern/ghost/GHOST_IContext.h @@ -44,13 +44,13 @@ class GHOST_IContext { /** * Activates the drawing context. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess releaseDrawingContext() = 0; diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h index b5975068da0..9096c70904b 100644 --- a/intern/ghost/GHOST_IEventConsumer.h +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -46,8 +46,8 @@ class GHOST_IEventConsumer { /** * This method is called by the system when it has events to dispatch. * \see GHOST_ISystem#dispatchEvents - * \param event The event that can be handled or ignored. - * \return Indication as to whether the event was handled. + * \param event: The event that can be handled or ignored. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event) = 0; diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 61ddae47292..81b54cf5a0d 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -183,10 +183,10 @@ class GHOST_ISystem { * Installs a timer. * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * \param delay The time to wait for the first call to the timerProc (in milliseconds) - * \param interval The interval between calls to the timerProc (in milliseconds) - * \param timerProc The callback invoked when the interval expires, - * \param userData Placeholder for user data. + * \param delay: The time to wait for the first call to the timerProc (in milliseconds). + * \param interval: The interval between calls to the timerProc (in milliseconds). + * \param timerProc: The callback invoked when the interval expires. + * \param userData: Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, @@ -196,7 +196,7 @@ class GHOST_ISystem { /** * Removes a timer. - * \param timerTask Timer task to be removed. + * \param timerTask: Timer task to be removed. * \return Indication of success. */ virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask) = 0; @@ -255,38 +255,38 @@ class GHOST_ISystem { /** * Dispose a window. - * \param window Pointer to the window to be disposed. - * \return Indication of success. + * \param window: Pointer to the window to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0; /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0; /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeContext(GHOST_IContext *context) = 0; /** * Returns whether a window is valid. - * \param window Pointer to the window to be checked. - * \return Indication of validity. + * \param window: Pointer to the window to be checked. + * \return Indication of validity. */ virtual bool validWindow(GHOST_IWindow *window) = 0; /** * Begins full screen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. + * \param setting: The new setting of the display. + * \param window: Window displayed in full screen. * This window is invalid after full screen has been ended. - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window, @@ -295,17 +295,17 @@ class GHOST_ISystem { /** * Updates the resolution while in fullscreen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. + * \param setting: The new setting of the display. + * \param window: Window displayed in full screen. * - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window) = 0; /** * Ends full screen mode. - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void) = 0; @@ -331,7 +331,7 @@ class GHOST_ISystem { /** * Retrieves events from the system and stores them in the queue. - * \param waitForEvent Flag to wait for an event (or return immediately). + * \param waitForEvent: Flag to wait for an event (or return immediately). * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent) = 0; @@ -343,14 +343,14 @@ class GHOST_ISystem { /** * Adds the given event consumer to our list. - * \param consumer The event consumer to add. + * \param consumer: The event consumer to add. * \return Indication of success. */ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer) = 0; /** * Removes the given event consumer to our list. - * \param consumer The event consumer to remove. + * \param consumer: The event consumer to remove. * \return Indication of success. */ virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer) = 0; @@ -361,18 +361,18 @@ class GHOST_ISystem { /** * Returns the current location of the cursor (location in screen coordinates) - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const = 0; /** * Updates the location of the cursor (location in screen coordinates). * Not all operating systems allow the cursor to be moved (without the input device being moved). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0; @@ -382,23 +382,23 @@ class GHOST_ISystem { /** * Returns the state of a modifier key (outside the message queue). - * \param mask The modifier key state to retrieve. - * \param isDown The state of a modifier key (true == pressed). - * \return Indication of success. + * \param mask: The modifier key state to retrieve. + * \param isDown: The state of a modifier key (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool &isDown) const = 0; /** * Returns the state of a mouse button (outside the message queue). - * \param mask The button state to retrieve. - * \param isDown Button state. - * \return Indication of success. + * \param mask: The button state to retrieve. + * \param isDown: Button state. + * \return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool &isDown) const = 0; /** * Set which tablet API to use. Only affects Windows, other platforms have a single API. - * \param api Enum indicating which API to use. + * \param api: Enum indicating which API to use. */ virtual void setTabletAPI(GHOST_TTabletAPI api) = 0; @@ -412,8 +412,8 @@ class GHOST_ISystem { /** * Toggles console - * \param action - * - 0: Hides + * \param action: + * - 0: Hides. * - 1: Shows * - 2: Toggles * - 3: Hides if it runs not from command line @@ -445,12 +445,12 @@ class GHOST_ISystem { /** * Show a system message box * - * \param title The title of the message box - * \param message The message to display - * \param help_label Help button label - * \param continue_label Continue button label - * \param link An optional hyperlink - * \param dialog_options Options how to display the message + * \param title: The title of the message box. + * \param message: The message to display. + * \param help_label: Help button label. + * \param continue_label: Continue button label. + * \param link: An optional hyperlink. + * \param dialog_options: Options how to display the message. */ virtual GHOST_TSuccess showMessageBox(const char * /*title*/, const char * /*message*/, diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h index 0f4ac74c466..5d3013ac348 100644 --- a/intern/ghost/GHOST_ITimerTask.h +++ b/intern/ghost/GHOST_ITimerTask.h @@ -55,7 +55,7 @@ class GHOST_ITimerTask { /** * Changes the timer callback. - * \param timerProc The timer callback. + * \param timerProc: The timer callback. */ virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0; diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 6e8b61ae5a1..1650b230812 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -73,62 +73,62 @@ class GHOST_IWindow { /** * Tries to install a rendering context in this window. - * \param type The type of rendering context installed. + * \param type: The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0; /** * Sets the title displayed in the title bar. - * \param title The title to display in the title bar. + * \param title: The title to display in the title bar. */ virtual void setTitle(const char *title) = 0; /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \param title: The title displayed in the title bar. */ virtual std::string getTitle() const = 0; /** * Returns the window rectangle dimensions. * These are screen coordinates. - * \param bounds The bounding rectangle of the window. + * \param bounds: The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect &bounds) const = 0; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * \param bounds The bounding rectangle of the client area of the window. + * \param bounds: The bounding rectangle of the client area of the window. */ virtual void getClientBounds(GHOST_Rect &bounds) const = 0; /** * Resizes client rectangle width. - * \param width The new width of the client area of the window. + * \param width: The new width of the client area of the window. */ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; /** * Resizes client rectangle height. - * \param height The new height of the client area of the window. + * \param height: The new height of the client area of the window. */ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; /** * Resizes client rectangle. - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param width: The new width of the client area of the window. + * \param height: The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param inX: The x-coordinate on the screen. + * \param inY: The y-coordinate on the screen. + * \param outX: The x-coordinate in the client rectangle. + * \param outY: The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -137,10 +137,10 @@ class GHOST_IWindow { /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -166,14 +166,14 @@ class GHOST_IWindow { /** * Sets the state of the window (normal, minimized, maximized). - * \param state The state of the window. + * \param state: The state of the window. * \return Indication of success. */ virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; /** * Sets the window "modified" status, indicating unsaved changes - * \param isUnsavedChanges Unsaved changes or not + * \param isUnsavedChanges: Unsaved changes or not. * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; @@ -186,27 +186,27 @@ class GHOST_IWindow { /** * Sets the order of the window (bottom, top). - * \param order The order of the window. + * \param order: The order of the window. * \return Indication of success. */ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0; /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers() = 0; /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ virtual GHOST_TSuccess setSwapInterval(int interval) = 0; /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut pointer to location to return swap interval + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: pointer to location to return swap interval. * (left untouched if there is an error) * \return A boolean success indicator of if swap interval was successfully read. */ @@ -214,13 +214,13 @@ class GHOST_IWindow { /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; /** - * Gets the OpenGL framebuffer associated with the window's contents. - * \return The name of an OpenGL framebuffer object. + * Gets the OpenGL frame-buffer associated with the window's contents. + * \return The name of an OpenGL frame-buffer object. */ virtual unsigned int getDefaultFramebuffer() = 0; @@ -238,7 +238,7 @@ class GHOST_IWindow { /** * Changes the window user data. - * \param userData The window user data. + * \param userData: The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; @@ -250,7 +250,7 @@ class GHOST_IWindow { /** * Sets the progress bar value displayed in the window/application icon - * \param progress The progress % + * \param progress: The progress percentage (0.0 to 1.0). */ virtual GHOST_TSuccess setProgressBar(float progress) = 0; @@ -265,13 +265,13 @@ class GHOST_IWindow { /** * Returns the current cursor shape. - * \return The current cursor shape. + * \return The current cursor shape. */ virtual GHOST_TStandardCursor getCursorShape() const = 0; /** * Set the shape of the cursor. - * \param cursorShape: The new cursor shape type id. + * \param cursorShape: The new cursor shape type id. * \return Indication of success. */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; @@ -284,11 +284,11 @@ class GHOST_IWindow { /** * Set the shape of the cursor to a custom cursor. - * \param bitmap The bitmap data for the cursor. - * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hot-spot. - * \param hotY The Y coordinate of the cursor hot-spot. - * \return Indication of success. + * \param bitmap: The bitmap data for the cursor. + * \param mask: The mask data for the cursor. + * \param hotX: The X coordinate of the cursor hot-spot. + * \param hotY: The Y coordinate of the cursor hot-spot. + * \return Indication of success. */ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, @@ -300,21 +300,21 @@ class GHOST_IWindow { /** * Returns the visibility state of the cursor. - * \return The visibility state of the cursor. + * \return The visibility state of the cursor. */ virtual bool getCursorVisibility() const = 0; /** * Shows or hides the cursor. - * \param visible The new visibility state of the cursor. - * \return Indication of success. + * \param visible: The new visibility state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; /** * Grabs the cursor for a modal operation. - * \param grab The new grab state of the cursor. - * \return Indication of success. + * \param grab: The new grab state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/, GHOST_TAxisFlag /*wrap_axis*/, @@ -340,13 +340,13 @@ class GHOST_IWindow { /** * Enable IME attached to the given window, i.e. allows user-input * events to be dispatched to the IME. - * \param x Requested x-coordinate of the rectangle - * \param y Requested y-coordinate of the rectangle - * \param w Requested width of the rectangle - * \param h Requested height of the rectangle - * \param complete Whether or not to complete the ongoing composition - * true: Start a new composition - * false: Move the IME windows to the given position without finishing it. + * \param x: Requested x-coordinate of the rectangle. + * \param y: Requested y-coordinate of the rectangle. + * \param w: Requested width of the rectangle. + * \param h: Requested height of the rectangle. + * \param complete: Whether or not to complete the ongoing composition. + * - true: Start a new composition + * - false: Move the IME windows to the given position without finishing it. */ virtual void beginIME( GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) = 0; diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index fcc9da20197..dae2a2a8cbb 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -37,10 +37,10 @@ class GHOST_Rect { public: /** * Constructs a rectangle with the given values. - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param l: requested left coordinate of the rectangle. + * \param t: requested top coordinate of the rectangle. + * \param r: requested right coordinate of the rectangle. + * \param b: requested bottom coordinate of the rectangle. */ GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0) : m_l(l), m_t(t), m_r(r), m_b(b) @@ -56,13 +56,13 @@ class GHOST_Rect { /** * Access to rectangle width. - * \return width of the rectangle + * \return width of the rectangle. */ virtual inline GHOST_TInt32 getWidth() const; /** * Access to rectangle height. - * \return height of the rectangle + * \return height of the rectangle. */ virtual inline GHOST_TInt32 getHeight() const; @@ -86,7 +86,7 @@ class GHOST_Rect { * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. * Thus, empty rectangles are valid. - * \return boolean value (true==valid rectangle) + * \return boolean value (true==valid rectangle) */ virtual inline bool isValid() const; @@ -113,8 +113,8 @@ class GHOST_Rect { /** * Grows the rectangle to included a point. - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param x: The x-coordinate of the point. + * \param y: The y-coordinate of the point. */ virtual inline void wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, @@ -124,24 +124,24 @@ class GHOST_Rect { /** * Returns whether the point is inside this rectangle. * Point on the boundary is considered inside. - * \param x x-coordinate of point to test. - * \param y y-coordinate of point to test. + * \param x: x-coordinate of point to test. + * \param y: y-coordinate of point to test. * \return boolean value (true if point is inside). */ virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const; /** * Returns whether the rectangle is inside this rectangle. - * \param r rectangle to test. - * \return visibility (not, partially or fully visible). + * \param r: rectangle to test. + * \return visibility (not, partially or fully visible). */ virtual GHOST_TVisibility getVisibility(GHOST_Rect &r) const; /** * Sets rectangle members. * Sets rectangle members such that it is centered at the given location. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle + * \param cx: requested center x-coordinate of the rectangle. + * \param cy: requested center y-coordinate of the rectangle. */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); @@ -149,10 +149,10 @@ class GHOST_Rect { * Sets rectangle members. * Sets rectangle members such that it is centered at the given location, * with the width requested. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle - * \param w requested width of the rectangle - * \param h requested height of the rectangle + * \param cx: requested center x-coordinate of the rectangle. + * \param cy: requested center y-coordinate of the rectangle. + * \param w: requested width of the rectangle. + * \param h: requested height of the rectangle. */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); @@ -160,8 +160,8 @@ class GHOST_Rect { * Clips a rectangle. * Updates the rectangle given such that it will fit within this one. * This can result in an empty rectangle. - * \param r the rectangle to clip - * \return whether clipping has occurred + * \param r: the rectangle to clip. + * \return whether clipping has occurred */ virtual bool clip(GHOST_Rect &r) const; diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 5f0516ae121..a03b59d14b0 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -162,7 +162,8 @@ typedef enum { } GHOST_TDrawingContextType; typedef enum { - GHOST_kButtonMaskLeft = 0, + GHOST_kButtonMaskNone, + GHOST_kButtonMaskLeft, GHOST_kButtonMaskMiddle, GHOST_kButtonMaskRight, GHOST_kButtonMaskButton4, @@ -469,6 +470,8 @@ typedef struct { GHOST_TInt32 deltaX; /** The y-delta (currently only for scroll subtype) of the trackpad event */ GHOST_TInt32 deltaY; + /** The delta is inverted from the device due to system preferences. */ + char isDirectionInverted; } GHOST_TEventTrackpadData; typedef enum { @@ -584,8 +587,8 @@ typedef int GHOST_TEmbedderWindowID; /** * A timer task callback routine. - * \param task The timer task object. - * \param time The current time. + * \param task: The timer task object. + * \param time: The current time. */ #ifdef __cplusplus class GHOST_ITimerTask; diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index e28fae8870c..e77bab4f2ec 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -40,15 +40,15 @@ struct GHOST_Buttons { /** * Returns the state of a single button. - * \param mask Key button to return. + * \param mask: Key button to return. * \return The state of the button (pressed == true). */ bool get(GHOST_TButtonMask mask) const; /** * Updates the state of a single button. - * \param mask Button state to update. - * \param down The new state of the button. + * \param mask: Button state to update. + * \param down: The new state of the button. */ void set(GHOST_TButtonMask mask, bool down); diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h index 9a76f4b031f..0d4941907c7 100644 --- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h @@ -35,8 +35,8 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer { public: /** * Constructor. - * \param eventCallback The call-back routine invoked. - * \param userData The data passed back through the call-back routine. + * \param eventCallback: The call-back routine invoked. + * \param userData: The data passed back through the call-back routine. */ GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userData); @@ -50,7 +50,7 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer { /** * This method is called by an event producer when an event is available. - * \param event The event that can be handled or ignored. + * \param event: The event that can be handled or ignored. * \return Indication as to whether the event was handled. */ bool processEvent(GHOST_IEvent *event); diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h index 33eeacbb203..d07913b28c4 100644 --- a/intern/ghost/intern/GHOST_Context.h +++ b/intern/ghost/intern/GHOST_Context.h @@ -35,7 +35,7 @@ class GHOST_Context : public GHOST_IContext { public: /** * Constructor. - * \param stereoVisual Stereo visual for quad buffered stereo. + * \param stereoVisual: Stereo visual for quad buffered stereo. */ GHOST_Context(bool stereoVisual) : m_stereoVisual(stereoVisual) { @@ -50,19 +50,19 @@ class GHOST_Context : public GHOST_IContext { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers() = 0; /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess releaseDrawingContext() = 0; @@ -89,8 +89,8 @@ class GHOST_Context : public GHOST_IContext { virtual GHOST_TSuccess releaseNativeHandles() = 0; /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ virtual GHOST_TSuccess setSwapInterval(int /*interval*/) @@ -99,8 +99,8 @@ class GHOST_Context : public GHOST_IContext { } /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ virtual GHOST_TSuccess getSwapInterval(int &) diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h index 7b1e186dede..d499ec987b0 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.h +++ b/intern/ghost/intern/GHOST_ContextCGL.h @@ -50,19 +50,19 @@ class GHOST_ContextCGL : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -82,15 +82,15 @@ class GHOST_ContextCGL : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &); diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h index e85516838fc..18b4a5d1286 100644 --- a/intern/ghost/intern/GHOST_ContextD3D.h +++ b/intern/ghost/intern/GHOST_ContextD3D.h @@ -38,19 +38,19 @@ class GHOST_ContextD3D : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -77,8 +77,8 @@ class GHOST_ContextD3D : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int /*interval*/) @@ -87,8 +87,8 @@ class GHOST_ContextD3D : public GHOST_Context { } /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &) diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h index e5dae0d22a8..f828271d88d 100644 --- a/intern/ghost/intern/GHOST_ContextEGL.h +++ b/intern/ghost/intern/GHOST_ContextEGL.h @@ -57,19 +57,19 @@ class GHOST_ContextEGL : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -87,15 +87,15 @@ class GHOST_ContextEGL : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &intervalOut); diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h index e5654b1aed7..178c750ea99 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.h +++ b/intern/ghost/intern/GHOST_ContextGLX.h @@ -61,19 +61,19 @@ class GHOST_ContextGLX : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -91,15 +91,15 @@ class GHOST_ContextGLX : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &intervalOut); diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h index b1ac349e4a7..46dde89794a 100644 --- a/intern/ghost/intern/GHOST_ContextNone.h +++ b/intern/ghost/intern/GHOST_ContextNone.h @@ -35,50 +35,50 @@ class GHOST_ContextNone : public GHOST_Context { /** * Dummy function - * \return Always succeeds + * \return Always succeeds */ GHOST_TSuccess swapBuffers(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess activateDrawingContext(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess releaseDrawingContext(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess updateDrawingContext(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess initializeDrawingContext(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess releaseNativeHandles(); /** * Dummy function - * \return Always succeeds + * \return Always succeeds. */ GHOST_TSuccess setSwapInterval(int interval); /** * Dummy function - * \param intervalOut Gets whatever was set by setSwapInterval - * \return Always succeeds + * \param intervalOut: Gets whatever was set by #setSwapInterval. + * \return Always succeeds. */ GHOST_TSuccess getSwapInterval(int &intervalOut); diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h index ead2e91181c..8e8c91b86a3 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.h +++ b/intern/ghost/intern/GHOST_ContextSDL.h @@ -61,19 +61,19 @@ class GHOST_ContextSDL : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -91,15 +91,15 @@ class GHOST_ContextSDL : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &intervalOut); diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h index 087fca100e4..7367bc3baed 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.h +++ b/intern/ghost/intern/GHOST_ContextWGL.h @@ -58,19 +58,19 @@ class GHOST_ContextWGL : public GHOST_Context { /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess activateDrawingContext(); /** * Release the drawing context of the calling thread. - * \return A boolean success indicator. + * \return A boolean success indicator. */ GHOST_TSuccess releaseDrawingContext(); @@ -88,15 +88,15 @@ class GHOST_ContextWGL : public GHOST_Context { GHOST_TSuccess releaseNativeHandles(); /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. - * \param intervalOut Variable to store the swap interval if it can be read. + * Gets the current swap interval for #swapBuffers. + * \param intervalOut: Variable to store the swap interval if it can be read. * \return Whether the swap interval can be read. */ GHOST_TSuccess getSwapInterval(int &intervalOut); diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h index 67b9aada55f..26bc687a179 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.h +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -52,15 +52,15 @@ class GHOST_DisplayManager { /** * Returns the number of display devices on this system. - * \param numDisplays The number of displays on this system. + * \param numDisplays: The number of displays on this system. * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; /** * Returns the number of display settings for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param numSettings The number of settings of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param numSettings: The number of settings of the display device with this index. * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, @@ -68,9 +68,9 @@ class GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param index The setting index to be returned. - * \param setting The setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param index: The setting index to be returned. + * \param setting: The setting of the display device with this index. * \return Indication of success. */ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, @@ -79,8 +79,8 @@ class GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, @@ -90,8 +90,8 @@ class GHOST_DisplayManager { * Changes the current setting for this display device. * The setting given to this method is matched against the available display settings. * The best match is activated (@see findMatch()). - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The setting of the display device to be matched and activated. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The setting of the display device to be matched and activated. * \return Indication of success. */ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, @@ -102,9 +102,9 @@ class GHOST_DisplayManager { /** * Finds the best display settings match. - * \param display The index of the display device. - * \param setting The setting to match. - * \param match The optimal display setting. + * \param display: The index of the display device. + * \param setting: The setting to match. + * \param match: The optimal display setting. * \return Indication of success. */ GHOST_TSuccess findMatch(GHOST_TUns8 display, diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h index 5edd555a78b..745ad457796 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h @@ -43,14 +43,14 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { /** * Returns the number of display devices on this system. - * \param numDisplays The number of displays on this system. + * \param numDisplays: The number of displays on this system. * \return Indication of success. */ GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; /** * Returns the number of display settings for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ @@ -58,9 +58,9 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param index The setting index to be returned. - * \param setting The setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param index: The setting index to be returned. + * \param setting: The setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, @@ -69,8 +69,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, @@ -78,8 +78,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { /** * Changes the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h index 3392d515c16..2de866b04ec 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -42,14 +42,14 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { /** * Returns the number of display devices on this system. - * \param numDisplays The number of displays on this system. + * \param numDisplays: The number of displays on this system. * \return Indication of success. */ GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; /** * Returns the number of display settings for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ @@ -57,9 +57,9 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param index The setting index to be returned. - * \param setting The setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param index: The setting index to be returned. + * \param setting: The setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, @@ -68,8 +68,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, @@ -77,8 +77,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { /** * Changes the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h index a36ff8d49f1..e0fc1cc1210 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.h +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -40,14 +40,14 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { /** * Returns the number of display devices on this system. - * \param numDisplays The number of displays on this system. + * \param numDisplays: The number of displays on this system. * \return Indication of success. */ GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; /** * Returns the number of display settings for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ @@ -55,9 +55,9 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param index The setting index to be returned. - * \param setting The setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param index: The setting index to be returned. + * \param setting: The setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, @@ -66,8 +66,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { /** * Returns the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, @@ -75,8 +75,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { /** * Changes the current setting for this display device. - * \param display The index of the display to query with 0 <= display < getNumDisplays(). - * \param setting The current setting of the display device with this index. + * \param display: The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting: The current setting of the display device with this index. * \return Indication of success. */ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index ecce3a68835..08e8ba11b23 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -73,8 +73,8 @@ class GHOST_DropTargetWin32 : public IDropTarget { * With the modifier keys, we want to distinguish left and right keys. * Sometimes this is not possible (Windows ME for instance). Then, we want * events generated for both keys. - * \param window The window to register as drop target. - * \param system The associated system. + * \param window: The window to register as drop target. + * \param system: The associated system. */ GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system); @@ -89,14 +89,14 @@ class GHOST_DropTargetWin32 : public IDropTarget { /** * Base the effect on those allowed by the drop-source. - * \param dwAllowed Drop sources allowed drop effect. + * \param dwAllowed: Drop sources allowed drop effect. * \return The allowed drop effect. */ DWORD allowedDropEffect(DWORD dwAllowed); /** * Query DataObject for the data types it supports. - * \param pDataObject Pointer to the DataObject. + * \param pDataObject: Pointer to the DataObject. * \return GHOST data type. */ GHOST_TDragnDropTypes getGhostType(IDataObject *pDataObject); @@ -104,21 +104,21 @@ class GHOST_DropTargetWin32 : public IDropTarget { /** * Get data to pass in event. * It checks the type and calls specific functions for each type. - * \param pDataObject Pointer to the DataObject. + * \param pDataObject: Pointer to the DataObject. * \return Pointer to data. */ void *getGhostData(IDataObject *pDataObject); /** * Allocate data as file array to pass in event. - * \param pDataObject Pointer to the DataObject. + * \param pDataObject: Pointer to the DataObject. * \return Pointer to data. */ void *getDropDataAsFilenames(IDataObject *pDataObject); /** * Allocate data as string to pass in event. - * \param pDataObject Pointer to the DataObject. + * \param pDataObject: Pointer to the DataObject. * \return Pointer to data. */ void *getDropDataAsString(IDataObject *pDataObject); @@ -127,8 +127,8 @@ class GHOST_DropTargetWin32 : public IDropTarget { * Convert Unicode to ANSI, replacing uncomfortable chars with '?'. * The ANSI codepage is the system default codepage, * and can change from system to system. - * \param in LPCWSTR. - * \param out char *. Is set to NULL on failure. + * \param in: LPCWSTR. + * \param out: char *. Is set to NULL on failure. * \return 0 on failure. Else the size of the string including '\0'. */ int WideCharToANSI(LPCWSTR in, char *&out); diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h index a96852da7bb..69f6fec7ac1 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.h +++ b/intern/ghost/intern/GHOST_DropTargetX11.h @@ -34,8 +34,8 @@ class GHOST_DropTargetX11 { /** * Constructor * - * \param window The window to register as drop target. - * \param system The associated system. + * \param window: The window to register as drop target. + * \param system: The associated system. */ GHOST_DropTargetX11(GHOST_WindowX11 *window, GHOST_SystemX11 *system); @@ -52,9 +52,9 @@ class GHOST_DropTargetX11 { /** * Get data to pass in event. * It checks the type and calls specific functions for each type. - * \param dropType - type of dropped entity. - * \param dropBuffer - buffer returned from source application - * \param dropBufferSize - size of returned buffer + * \param dropType: Type of dropped entity. + * \param dropBuffer: Buffer returned from source application. + * \param dropBufferSize: Size of returned buffer. * \return Pointer to data. */ void *getGhostData(Atom dropType, unsigned char *dropBuffer, int dropBufferSize); @@ -73,25 +73,25 @@ class GHOST_DropTargetX11 { void Uninitialize(void); /** - * Get data to be passed to event from text/uri-list mime type - * \param dropBuffer - buffer returned from source application - * \param dropBufferSize - size of dropped buffer - * \return pointer to newly created GHOST data + * Get data to be passed to event from text/URI-list mime type + * \param dropBuffer: Buffer returned from source application. + * \param dropBufferSize: Size of dropped buffer. + * \return pointer to newly created GHOST data. */ void *getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize); /** - * Decode URL (i.e. converts "file:///a%20b/test" to "file:///a b/test") - * \param decodedOut - buffer for decoded URL - * \param bufferSize - size of output buffer - * \param encodedIn - input encoded buffer to be decoded + * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`) + * \param decodedOut: - buffer for decoded URL. + * \param bufferSize: - size of output buffer. + * \param encodedIn: - input encoded buffer to be decoded. */ void UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn); /** - * Fully decode file URL (i.e. converts "file:///a%20b/test" to "/a b/test") - * \param fileUrl - file path URL to be fully decoded - * \return decoded file path (result should be free-d) + * Fully decode file URL (i.e. converts `file:///a%20b/test` to `/a b/test`) + * \param fileUrl: - file path URL to be fully decoded. + * \return decoded file path (result should be free-d). */ char *FileUrlDecode(char *fileUrl); diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h index 845d62fa810..5016ca0e117 100644 --- a/intern/ghost/intern/GHOST_Event.h +++ b/intern/ghost/intern/GHOST_Event.h @@ -33,9 +33,9 @@ class GHOST_Event : public GHOST_IEvent { public: /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of this event. - * \param window The generating window (or NULL if system event). + * \param msec: The time this event was generated. + * \param type: The type of this event. + * \param window: The generating window (or NULL if system event). */ GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window) : m_type(type), m_time(msec), m_window(window), m_data(NULL) diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index 7072e0c5409..02804efdcba 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -34,21 +34,19 @@ class GHOST_EventButton : public GHOST_Event { public: /** * Constructor. - * \param time The time this event was generated. - * \param type The type of this event. - * \param window The window of this event. - * \param button The state of the buttons were at the time of the event. - * \param tablet The tablet data associated with this event. + * \param time: The time this event was generated. + * \param type: The type of this event. + * \param window: The window of this event. + * \param button: The state of the buttons were at the time of the event. + * \param tablet: The tablet data associated with this event. */ GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask button, const GHOST_TabletData &tablet) - : GHOST_Event(time, type, window) + : GHOST_Event(time, type, window), m_buttonEventData({button, tablet}) { - m_buttonEventData.button = button; - m_buttonEventData.tablet = tablet; m_data = &m_buttonEventData; } diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index ba85cd74723..d83ff6af6ce 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -33,11 +33,11 @@ class GHOST_EventCursor : public GHOST_Event { public: /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of this event. - * \param x The x-coordinate of the location the cursor was at the time of the event. - * \param y The y-coordinate of the location the cursor was at the time of the event. - * \param tablet The tablet data associated with this event. + * \param msec: The time this event was generated. + * \param type: The type of this event. + * \param x: The x-coordinate of the location the cursor was at the time of the event. + * \param y: The y-coordinate of the location the cursor was at the time of the event. + * \param tablet: The tablet data associated with this event. */ GHOST_EventCursor(GHOST_TUns64 msec, GHOST_TEventType type, @@ -45,11 +45,8 @@ class GHOST_EventCursor : public GHOST_Event { GHOST_TInt32 x, GHOST_TInt32 y, const GHOST_TabletData &tablet) - : GHOST_Event(msec, type, window) + : GHOST_Event(msec, type, window), m_cursorEventData({x, y, tablet}) { - m_cursorEventData.x = x; - m_cursorEventData.y = y; - m_cursorEventData.tablet = tablet; m_data = &m_cursorEventData; } diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index 10975792993..a86b8302bf5 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -64,13 +64,13 @@ class GHOST_EventDragnDrop : public GHOST_Event { public: /** * Constructor. - * \param time The time this event was generated. - * \param type The type of this event. - * \param dataType The type of the drop candidate object - * \param window The window where the event occurred - * \param x The x-coordinate of the location the cursor was at the time of the event. - * \param y The y-coordinate of the location the cursor was at the time of the event. - * \param data The "content" dropped in the window + * \param time: The time this event was generated. + * \param type: The type of this event. + * \param dataType: The type of the drop candidate object. + * \param window: The window where the event occurred. + * \param x: The x-coordinate of the location the cursor was at the time of the event. + * \param y: The y-coordinate of the location the cursor was at the time of the event. + * \param data: The "content" dropped in the window. */ GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index cb71b452d80..1e6a3284a51 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -35,9 +35,9 @@ class GHOST_EventKey : public GHOST_Event { public: /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of key event. - * \param key The key code of the key. + * \param msec: The time this event was generated. + * \param type: The type of key event. + * \param key: The key code of the key. */ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, @@ -55,10 +55,10 @@ class GHOST_EventKey : public GHOST_Event { /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of key event. - * \param key The key code of the key. - * \param ascii The ascii code for the key event. + * \param msec: The time this event was generated. + * \param type: The type of key event. + * \param key: The key code of the key. + * \param ascii: The ascii code for the key event. */ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index befbdc72a5c..a372eb96a99 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -57,7 +57,7 @@ class GHOST_EventManager { /** * Returns the number of events of a certain type currently on the stack. - * \param type The type of events to be counted. + * \param type: The type of events to be counted. * \return The number of events on the stack of this type. */ GHOST_TUns32 getNumEvents(GHOST_TEventType type); @@ -66,7 +66,7 @@ class GHOST_EventManager { * Pushes an event on the stack. * To dispatch it, call dispatchEvent() or dispatchEvents(). * Do not delete the event! - * \param event The event to push on the stack. + * \param event: The event to push on the stack. */ GHOST_TSuccess pushEvent(GHOST_IEvent *event); @@ -89,30 +89,30 @@ class GHOST_EventManager { /** * Adds a consumer to the list of event consumers. - * \param consumer The consumer added to the list. + * \param consumer: The consumer added to the list. * \return Indication as to whether addition has succeeded. */ GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer); /** * Removes a consumer from the list of event consumers. - * \param consumer The consumer removed from the list. + * \param consumer: The consumer removed from the list. * \return Indication as to whether removal has succeeded. */ GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer); /** * Removes all events for a window from the stack. - * \param window The window to remove events for. + * \param window: The window to remove events for. */ void removeWindowEvents(GHOST_IWindow *window); /** * Removes all events of a certain type from the stack. - * The window parameter is optional. If non-null, the routine will remove - * events only associated with that window. - * \param type The type of events to be removed. - * \param window The window to remove the events for. + * The window parameter is optional. + * If non-null, the routine will remove events only associated with that window. + * \param type: The type of events to be removed. + * \param window: The window to remove the events for. */ void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *window = NULL); diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index 42de4da5ee5..96d0b9acf2d 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -34,7 +34,7 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer { public: /** * Prints all the events received to std out. - * \param event The event that can be handled or not. + * \param event: The event that can be handled or not. * \return Indication as to whether the event was handled. */ bool processEvent(GHOST_IEvent *event); @@ -42,8 +42,8 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer { protected: /** * Converts GHOST key code to a readable string. - * \param key The GHOST key code to convert. - * \param str The GHOST key code converted to a readable string. + * \param key: The GHOST key code to convert. + * \param str: The GHOST key code converted to a readable string. */ void getKeyString(GHOST_TKey key, char str[32]) const; }; diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h index 8cd24a8a78b..6dd2ffb2e86 100644 --- a/intern/ghost/intern/GHOST_EventString.h +++ b/intern/ghost/intern/GHOST_EventString.h @@ -33,10 +33,10 @@ class GHOST_EventString : public GHOST_Event { public: /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of this event. - * \param window The generating window (or NULL if system event). - * \param data_ptr Pointer to the (unformatted) data associated with the event + * \param msec: The time this event was generated. + * \param type: The type of this event. + * \param window: The generating window (or NULL if system event). + * \param data_ptr: Pointer to the (un-formatted) data associated with the event. */ GHOST_EventString(GHOST_TUns64 msec, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h index a22f8a34fad..d4f9d0f2b55 100644 --- a/intern/ghost/intern/GHOST_EventTrackpad.h +++ b/intern/ghost/intern/GHOST_EventTrackpad.h @@ -33,11 +33,11 @@ class GHOST_EventTrackpad : public GHOST_Event { public: /** * Constructor. - * \param msec The time this event was generated. + * \param msec: The time this event was generated. * \param window: The window of this event. - * \param subtype The subtype of the event. - * \param x The x-delta of the pan event. - * \param y The y-delta of the pan event. + * \param subtype: The subtype of the event. + * \param x: The x-delta of the pan event. + * \param y: The y-delta of the pan event. */ GHOST_EventTrackpad(GHOST_TUns64 msec, GHOST_IWindow *window, @@ -45,7 +45,8 @@ class GHOST_EventTrackpad : public GHOST_Event { GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 deltaX, - GHOST_TInt32 deltaY) + GHOST_TInt32 deltaY, + bool isDirectionInverted) : GHOST_Event(msec, GHOST_kEventTrackpad, window) { m_trackpadEventData.subtype = subtype; @@ -53,6 +54,7 @@ class GHOST_EventTrackpad : public GHOST_Event { m_trackpadEventData.y = y; m_trackpadEventData.deltaX = deltaX; m_trackpadEventData.deltaY = deltaY; + m_trackpadEventData.isDirectionInverted = isDirectionInverted; m_data = &m_trackpadEventData; } diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h index 24b42c08e8a..e9e688b76ab 100644 --- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h +++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h @@ -44,8 +44,8 @@ class GHOST_IXrGraphicsBinding { * Does __not__ require this object is initialized (can be called prior to * #initFromGhostContext). It's actually meant to be called first. * - * \param r_requirement_info Return argument to retrieve an informal string on the requirements - * to be met. Useful for error/debug messages. + * \param r_requirement_info: Return argument to retrieve an informal string on the requirements. + * to be met. Useful for error/debug messages. */ virtual bool checkVersionRequirements(class GHOST_Context &ghost_ctx, XrInstance instance, diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 74698d50659..63ecfd96cb8 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -40,9 +40,9 @@ class GHOST_EventIME : public GHOST_Event { public: /** * Constructor. - * \param msec The time this event was generated. - * \param type The type of key event. - * \param key The key code of the key. + * \param msec: The time this event was generated. + * \param type: The type of key event. + * \param key: The key code of the key. */ GHOST_EventIME(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata) : GHOST_Event(msec, type, window) diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h index c41ce8b7f39..e94ccef08c0 100644 --- a/intern/ghost/intern/GHOST_ModifierKeys.h +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -40,7 +40,7 @@ struct GHOST_ModifierKeys { /** * Returns the modifier key's key code from a modifier key mask. - * \param mask The mask of the modifier key. + * \param mask: The mask of the modifier key. * \return The modifier key's key code. */ static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index d5b23d76016..279f90b9641 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -79,12 +79,14 @@ class GHOST_System : public GHOST_ISystem { /** * Installs a timer. - * Note that, on most operating systems, messages need to be processed in order + * + * \note On most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * \param delay The time to wait for the first call to the timerProc (in milliseconds) - * \param interval The interval between calls to the timerProc - * \param timerProc The callback invoked when the interval expires, - * \param userData Placeholder for user data. + * + * \param delay: The time to wait for the first call to the #timerProc (in milliseconds). + * \param interval: The interval between calls to the #timerProc. + * \param timerProc: The callback invoked when the interval expires. + * \param userData: Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, @@ -94,7 +96,7 @@ class GHOST_System : public GHOST_ISystem { /** * Removes a timer. - * \param timerTask Timer task to be removed. + * \param timerTask: Timer task to be removed. * \return Indication of success. */ GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask); @@ -105,32 +107,32 @@ class GHOST_System : public GHOST_ISystem { /** * Dispose a window. - * \param window Pointer to the window to be disposed. - * \return Indication of success. + * \param window: Pointer to the window to be disposed. + * \return Indication of success. */ GHOST_TSuccess disposeWindow(GHOST_IWindow *window); /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0; /** * Returns whether a window is valid. - * \param window Pointer to the window to be checked. - * \return Indication of validity. + * \param window: Pointer to the window to be checked. + * \return Indication of validity. */ bool validWindow(GHOST_IWindow *window); /** * Begins full screen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. - * \param stereoVisual Stereo visual for quad buffered stereo. + * \param setting: The new setting of the display. + * \param window: Window displayed in full screen. + * \param stereoVisual: Stereo visual for quad buffered stereo. * This window is invalid after full screen has been ended. - * \return Indication of success. + * \return Indication of success. */ GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window, @@ -139,16 +141,16 @@ class GHOST_System : public GHOST_ISystem { /** * Updates the resolution while in fullscreen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. + * \param setting: The new setting of the display. + * \param window: Window displayed in full screen. * - * \return Indication of success. + * \return Indication of success. */ GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window); /** * Ends full screen mode. - * \return Indication of success. + * \return Indication of success. */ GHOST_TSuccess endFullScreen(void); @@ -189,14 +191,14 @@ class GHOST_System : public GHOST_ISystem { /** * Adds the given event consumer to our list. - * \param consumer The event consumer to add. + * \param consumer: The event consumer to add. * \return Indication of success. */ GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer); /** * Remove the given event consumer to our list. - * \param consumer The event consumer to remove. + * \param consumer: The event consumer to remove. * \return Indication of success. */ GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer); @@ -219,25 +221,25 @@ class GHOST_System : public GHOST_ISystem { /** * Returns the state of a modifier key (outside the message queue). - * \param mask The modifier key state to retrieve. - * \param isDown The state of a modifier key (true == pressed). - * \return Indication of success. + * \param mask: The modifier key state to retrieve. + * \param isDown: The state of a modifier key (true == pressed). + * \return Indication of success. */ GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool &isDown) const; /** * Returns the state of a mouse button (outside the message queue). - * \param mask The button state to retrieve. - * \param isDown Button state. - * \return Indication of success. + * \param mask: The button state to retrieve. + * \param isDown: Button state. + * \return Indication of success. */ GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool &isDown) const; /** * Set which tablet API to use. Only affects Windows, other platforms have a single API. - * \param api Enum indicating which API to use. + * \param api: Enum indicating which API to use. */ - void setTabletAPI(GHOST_TTabletAPI api); + virtual void setTabletAPI(GHOST_TTabletAPI api); GHOST_TTabletAPI getTabletAPI(void); #ifdef WITH_INPUT_NDOF @@ -260,7 +262,7 @@ class GHOST_System : public GHOST_ISystem { * Pushes an event on the stack. * To dispatch it, call dispatchEvent() or dispatchEvents(). * Do not delete the event! - * \param event The event to push on the stack. + * \param event: The event to push on the stack. */ GHOST_TSuccess pushEvent(GHOST_IEvent *event); @@ -288,41 +290,41 @@ class GHOST_System : public GHOST_ISystem { /** * Returns the state of all modifier keys. - * \param keys The state of all modifier keys (true == pressed). - * \return Indication of success. + * \param keys: The state of all modifier keys (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const = 0; /** * Returns the state of the mouse buttons (outside the message queue). - * \param buttons The state of the buttons. - * \return Indication of success. + * \param buttons: The state of the buttons. + * \return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const = 0; /** * Returns the selection buffer - * \param selection Only used on X11 - * \return Returns the clipboard data + * \param selection: Only used on X11. + * \return Returns the clipboard data * */ virtual GHOST_TUns8 *getClipboard(bool selection) const = 0; /** * Put data to the Clipboard - * \param buffer The buffer to copy to the clipboard - * \param selection The clipboard to copy too only used on X11 + * \param buffer: The buffer to copy to the clipboard. + * \param selection: The clipboard to copy too only used on X11. */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; /** * Show a system message box - * \param title The title of the message box - * \param message The message to display - * \param help_label Help button label - * \param continue_label Continue button label - * \param link An optional hyperlink - * \param dialog_options Options how to display the message + * \param title: The title of the message box. + * \param message: The message to display. + * \param help_label: Help button label. + * \param continue_label: Continue button label. + * \param link: An optional hyperlink. + * \param dialog_options: Options how to display the message. */ virtual GHOST_TSuccess showMessageBox(const char * /*title*/, const char * /*message*/, @@ -363,7 +365,7 @@ class GHOST_System : public GHOST_ISystem { /** * Creates a fullscreen window. - * \param window The window created. + * \param window: The window created. * \return Indication of success. */ GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 22f3c58d297..5637dfb0565 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -85,19 +85,19 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Create a new window. * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window + * Never explicitly delete the window, use #disposeWindow() instead. + * \param title: The name of the window. * (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state of the window when opened. + * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window ontop and ignore others (used fullscreen). - * \param parentWindow Parent (embedder) window - * \return The new window (or 0 if creation failed). + * \param parentWindow: Parent (embedder) window. + * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, @@ -114,14 +114,14 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings); /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess disposeContext(GHOST_IContext *context); @@ -131,7 +131,7 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Gets events from the system and stores them in the queue. - * \param waitForEvent Flag to wait for an event (or return immediately). + * \param waitForEvent: Flag to wait for an event (or return immediately). * \return Indication of the presence of events. */ bool processEvents(bool waitForEvent); @@ -150,12 +150,12 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass - * \param eventType The type of drag'n'drop event - * \param draggedObjectType The type object concerned - * (currently array of file names, string, TIFF image) - * \param mouseX x mouse coordinate (in cocoa base window coordinates) - * \param mouseY y mouse coordinate - * \param window The window on which the event occurred + * \param eventType: The type of drag'n'drop event. + * \param draggedObjectType: The type object concerned. + * (currently array of file names, string, TIFF image). + * \param mouseX: x mouse coordinate (in cocoa base window coordinates). + * \param mouseY: y mouse coordinate. + * \param window: The window on which the event occurred. * \return Indication whether the event was handled. */ GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, @@ -171,17 +171,17 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Returns the current location of the cursor (location in screen coordinates) - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; /** * Updates the location of the cursor (location in screen coordinates). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); @@ -191,36 +191,36 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Returns the state of all modifier keys. - * \param keys The state of all modifier keys (true == pressed). - * \return Indication of success. + * \param keys: The state of all modifier keys (true == pressed). + * \return Indication of success. */ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const; /** * Returns the state of the mouse buttons (outside the message queue). - * \param buttons The state of the buttons. - * \return Indication of success. + * \param buttons: The state of the buttons. + * \return Indication of success. */ GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const; /** * Returns Clipboard data - * \param selection Indicate which buffer to return - * \return Returns the selected buffer + * \param selection: Indicate which buffer to return. + * \return Returns the selected buffer */ GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * \param buffer The buffer to be copied - * \param selection Indicates which buffer to copy too, only used on X11 + * \param buffer: The buffer to be copied. + * \param selection: Indicates which buffer to copy too, only used on X11. */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Handles a window event. Called by GHOST_WindowCocoa window delegate - * \param eventType The type of window event - * \param window The window on which the event occurred + * \param eventType: The type of window event. + * \param window: The window on which the event occurred. * \return Indication whether the event was handled. */ GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa *window); @@ -284,9 +284,9 @@ class GHOST_SystemCocoa : public GHOST_System { /** * Performs the actual cursor position update (location in screen coordinates). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 152dae48905..c12c09f1053 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -763,7 +763,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, /** * Create a new offscreen context. * Never explicitly delete the context, use #disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings) { @@ -778,8 +778,8 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context) { @@ -1716,8 +1716,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventTrackpad( - [event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, + window, + GHOST_kTrackpadEventScroll, + x, + y, + dx, + dy, + [event isDirectionInvertedFromDevice])); } } break; @@ -1731,7 +1737,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) x, y, [event magnification] * 125.0 + 0.1, - 0)); + 0, + false)); } break; case NSEventTypeSmartMagnify: { @@ -1739,7 +1746,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); pushEvent(new GHOST_EventTrackpad( - [event timestamp] * 1000, window, GHOST_kTrackpadEventSmartMagnify, x, y, 0, 0)); + [event timestamp] * 1000, window, GHOST_kTrackpadEventSmartMagnify, x, y, 0, 0, false)); } break; case NSEventTypeRotate: { @@ -1752,7 +1759,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) x, y, [event rotation] * -5.0, - 0)); + 0, + false)); } default: return GHOST_kFailure; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index b1e2502fa78..8178b9bdf1e 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -234,6 +234,11 @@ GHOST_SystemWin32::~GHOST_SystemWin32() toggleConsole(1); } +GHOST_TUns64 GHOST_SystemWin32::millisSinceStart(__int64 ms) const +{ + return (GHOST_TUns64)(ms - m_start * 1000 / m_freq); +} + GHOST_TUns64 GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const { // Calculate the time passed since system initialization. @@ -417,8 +422,8 @@ finished: /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context) { @@ -941,23 +946,137 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, window->updateMouseCapture(MouseReleased); } - if (window->m_tabletInRange) { - if (window->useTabletAPI(GHOST_kTabletNative)) { - // Win32 Pointer processing handles input while in-range and in-contact events. - return NULL; - } + /* Check for active Wintab mouse emulation in addition to a tablet in range because a proximity + * leave event might have fired before the Windows mouse up event, thus there are still tablet + * events to grab. The described behavior was observed in a Wacom Bamboo CTE-450. */ + if (window->useTabletAPI(GHOST_kTabletWintab) && + (window->m_tabletInRange || window->wintabSysButPressed()) && + processWintabEvent(type, window, mask, window->getMousePressed())) { + /* Wintab processing only handles in-contact events. */ + return NULL; } return new GHOST_EventButton( - system->getMilliSeconds(), type, window, mask, window->getTabletData()); + system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE); +} + +GHOST_TSuccess GHOST_SystemWin32::processWintabEvent(GHOST_TEventType type, + GHOST_WindowWin32 *window, + GHOST_TButtonMask mask, + bool mousePressed) +{ + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); + + /* Only process Wintab packets if we can correlate them to a Window's mouse button event. When a + * button event associated to a mouse button by Wintab occurs outside of WM_*BUTTON events, + * there's no way to tell if other simultaneously pressed non-mouse mapped buttons are associated + * to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and thus it is not + * possible to determine if a mouse click event should occur. */ + if (!mousePressed && !window->wintabSysButPressed()) { + return GHOST_kFailure; + } + + std::vector<GHOST_WintabInfoWin32> wintabInfo; + if (!window->getWintabInfo(wintabInfo)) { + return GHOST_kFailure; + } + + auto wtiIter = wintabInfo.begin(); + + /* We only process events that correlate to a mouse button events, so there may exist Wintab + * button down events that were instead mapped to e.g. scroll still in the queue. We need to + * skip those and find the last button down mapped to mouse buttons. */ + if (!window->wintabSysButPressed()) { + /* Assume there may be no button down event currently in the queue. */ + wtiIter = wintabInfo.end(); + + for (auto it = wintabInfo.begin(); it != wintabInfo.end(); it++) { + if (it->type == GHOST_kEventButtonDown) { + wtiIter = it; + } + } + } + + bool unhandledButton = type != GHOST_kEventCursorMove; + + for (; wtiIter != wintabInfo.end(); wtiIter++) { + auto info = *wtiIter; + + switch (info.type) { + case GHOST_kEventButtonDown: { + /* While changing windows with a tablet, Window's mouse button events normally occur before + * tablet proximity events, so a button up event can't be differentiated as occurring from + * a Wintab tablet or a normal mouse and a Ghost button event will always be generated. + * + * If we were called during a button down event create a ghost button down event, otherwise + * don't duplicate the prior button down as it interrupts drawing immediately after + * changing a window. */ + system->pushEvent(new GHOST_EventCursor( + info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); + if (type == GHOST_kEventButtonDown && mask == info.button) { + system->pushEvent( + new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData)); + unhandledButton = false; + } + window->updateWintabSysBut(MousePressed); + break; + } + case GHOST_kEventCursorMove: + system->pushEvent(new GHOST_EventCursor( + info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); + break; + case GHOST_kEventButtonUp: + system->pushEvent( + new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData)); + if (type == GHOST_kEventButtonUp && mask == info.button) { + unhandledButton = false; + } + window->updateWintabSysBut(MouseReleased); + break; + default: + break; + } + } + + /* No Wintab button found correlating to the system button event, handle it too. + * + * Wintab button up events may be handled during WM_MOUSEMOVE, before their corresponding + * WM_*BUTTONUP event has fired, which results in two GHOST Button up events for a single Wintab + * associated button event. Alternatively this Windows button up event may have been generated + * from a non-stylus device such as a button on the tablet pad and needs to be handled for some + * workflows. + * + * The ambiguity introduced by Windows and Wintab buttons being asynchronous and having no + * definitive way to associate each, and that the Wintab API does not provide enough information + * to differentiate whether the stylus down is or is not modified by another button to a + * non-mouse mapping, means that we must pessimistically generate mouse up events when we are + * unsure of an association to prevent the mouse locking into a down state. */ + if (unhandledButton) { + if (!window->wintabSysButPressed()) { + GHOST_TInt32 x, y; + system->getCursorPosition(x, y); + system->pushEvent(new GHOST_EventCursor(system->getMilliSeconds(), + GHOST_kEventCursorMove, + window, + x, + y, + GHOST_TABLET_DATA_NONE)); + } + system->pushEvent(new GHOST_EventButton( + system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE)); + } + + return GHOST_kSuccess; } -void GHOST_SystemWin32::processPointerEvents( +void GHOST_SystemWin32::processPointerEvent( UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled) { std::vector<GHOST_PointerInfoWin32> pointerInfo; GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); + /* Pointer events might fire when changing windows for a device which is set to use Wintab, even + * when when Wintab is left enabled but set to the bottom of Wintab overlap order. */ if (!window->useTabletAPI(GHOST_kTabletNative)) { return; } @@ -982,7 +1101,7 @@ void GHOST_SystemWin32::processPointerEvents( pointerInfo[0].tabletData)); break; case WM_POINTERDOWN: - // Move cursor to point of contact because GHOST_EventButton does not include position. + /* Move cursor to point of contact because GHOST_EventButton does not include position. */ system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time, GHOST_kEventCursorMove, window, @@ -997,8 +1116,8 @@ void GHOST_SystemWin32::processPointerEvents( window->updateMouseCapture(MousePressed); break; case WM_POINTERUPDATE: - // Coalesced pointer events are reverse chronological order, reorder chronologically. - // Only contiguous move events are coalesced. + /* Coalesced pointer events are reverse chronological order, reorder chronologically. + * Only contiguous move events are coalesced. */ for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) { system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time, GHOST_kEventCursorMove, @@ -1018,11 +1137,6 @@ void GHOST_SystemWin32::processPointerEvents( break; case WM_POINTERLEAVE: window->m_tabletInRange = false; - system->pushEvent(new GHOST_EventButton(pointerInfo[0].time, - GHOST_kEventCursorMove, - window, - pointerInfo[0].buttonMask, - pointerInfo[0].tabletData)); break; default: break; @@ -1037,13 +1151,21 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - if (window->m_tabletInRange) { - if (window->useTabletAPI(GHOST_kTabletNative)) { - // Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet - // input aren't normally generated when using WM_POINTER events, but manually moving the - // system cursor as we do in WM_POINTER handling does. + if (window->m_tabletInRange || window->wintabSysButPressed()) { + if (window->useTabletAPI(GHOST_kTabletWintab) && + processWintabEvent( + GHOST_kEventCursorMove, window, GHOST_kButtonMaskNone, window->getMousePressed())) { + return NULL; + } + else if (window->useTabletAPI(GHOST_kTabletNative)) { + /* Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet + * input aren't normally generated when using WM_POINTER events, but manually moving the + * system cursor as we do in WM_POINTER handling does. */ return NULL; } + + /* If using Wintab but no button event is currently active, + * fall through to default handling. */ } system->getCursorPosition(x_screen, y_screen); @@ -1076,7 +1198,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind window, x_screen + x_accum, y_screen + y_accum, - window->getTabletData()); + GHOST_TABLET_DATA_NONE); } } else { @@ -1085,7 +1207,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind window, x_screen, y_screen, - window->getTabletData()); + GHOST_TABLET_DATA_NONE); } return NULL; } @@ -1202,7 +1324,6 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, if (type == GHOST_kEventWindowActivate) { system->getWindowManager()->setActiveWindow(window); - window->bringTabletContextToFront(); } return new GHOST_Event(system->getMilliSeconds(), type, window); @@ -1230,6 +1351,20 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data)); } +void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api) +{ + GHOST_System::setTabletAPI(api); + + GHOST_WindowManager *wm = getWindowManager(); + GHOST_WindowWin32 *activeWindow = (GHOST_WindowWin32 *)wm->getActiveWindow(); + + for (GHOST_IWindow *win : wm->getWindows()) { + GHOST_WindowWin32 *windowsWindow = (GHOST_WindowWin32 *)win; + windowsWindow->updateWintab(windowsWindow == activeWindow, + !::IsIconic(windowsWindow->getHWND())); + } +} + void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax) { minmax->ptMinTrackSize.x = 320; @@ -1467,14 +1602,19 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; //////////////////////////////////////////////////////////////////////// - // Tablet events, processed + // Wintab events, processed //////////////////////////////////////////////////////////////////////// - case WT_PACKET: - window->processWin32TabletEvent(wParam, lParam); + case WT_INFOCHANGE: { + window->processWintabInfoChangeEvent(lParam); + break; + } + case WT_PROXIMITY: { + bool inRange = LOWORD(lParam); + window->processWintabProximityEvent(inRange); break; - case WT_CSRCHANGE: - case WT_PROXIMITY: - window->processWin32TabletInitEvent(); + } + case WT_PACKET: + window->updatePendingWintabEvents(); break; //////////////////////////////////////////////////////////////////////// // Pointer events, processed @@ -1484,7 +1624,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_POINTERUPDATE: case WM_POINTERUP: case WM_POINTERLEAVE: - processPointerEvents(msg, window, wParam, lParam, eventHandled); + processPointerEvent(msg, window, wParam, lParam, eventHandled); break; //////////////////////////////////////////////////////////////////////// // Mouse events, processed @@ -1614,7 +1754,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * will not be dispatched to OUR active window if we minimize one of OUR windows. */ if (LOWORD(wParam) == WA_INACTIVE) window->lostMouseCapture(); - window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam)); + + window->updateWintab(LOWORD(wParam) != WA_INACTIVE, !::IsIconic(window->getHWND())); + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; } @@ -1672,6 +1814,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, else { event = processWindowEvent(GHOST_kEventWindowSize, window); } + + /* Window might be minimized while inactive. When a window is inactive but not minimized, + * Wintab is left enabled (to catch the case where a pen is used to activate a window). + * When an inactive window is minimized, we need to disable Wintab. */ + if (msg == WM_SIZE && wParam == SIZE_MINIMIZED) { + window->updateWintab(false, false); + } + break; case WM_CAPTURECHANGED: window->lostMouseCapture(); @@ -1722,6 +1872,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, SWP_NOZORDER | SWP_NOACTIVATE); } break; + case WM_DISPLAYCHANGE: + for (GHOST_IWindow *iter_win : system->getWindowManager()->getWindows()) { + GHOST_WindowWin32 *iter_win32win = (GHOST_WindowWin32 *)iter_win; + iter_win32win->processWintabDisplayChangeEvent(); + } + break; //////////////////////////////////////////////////////////////////////// // Window events, ignored //////////////////////////////////////////////////////////////////////// @@ -1915,6 +2071,7 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const } } +/* -------------------------------------------------------------------- */ /** \name Message Box * \{ */ GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title, diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index b91a9d7a154..00b626511ab 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -64,6 +64,8 @@ class GHOST_SystemWin32 : public GHOST_System { ** Time(r) functionality ***************************************************************************************/ + GHOST_TUns64 millisSinceStart(__int64 ms) const; + /** * This method converts performance counter measurements into milliseconds since the start of the * system process. @@ -111,19 +113,19 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Create a new window. * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window + * Never explicitly delete the window, use #disposeWindow() instead. + * \param title: The name of the window. * (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state of the window when opened. + * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window ontop and ignore others (used fullscreen). - * \param parentWindow Parent window - * \return The new window (or 0 if creation failed). + * \param parentWindow: Parent window. + * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, @@ -140,14 +142,14 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Create a new offscreen context. * Never explicitly delete the window, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings); /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess disposeContext(GHOST_IContext *context); @@ -156,15 +158,15 @@ class GHOST_SystemWin32 : public GHOST_System { * Never explicitly delete the context, use disposeContext() instead. * This is for GHOST internal, Win32 specific use, so it can be called statically. * - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ static GHOST_ContextD3D *createOffscreenContextD3D(); /** * Dispose of a DirectX context. * This is for GHOST internal, Win32 specific use, so it can be called statically. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ static GHOST_TSuccess disposeContextD3D(GHOST_ContextD3D *context); @@ -174,7 +176,7 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Gets events from the system and stores them in the queue. - * \param waitForEvent Flag to wait for an event (or return immediately). + * \param waitForEvent: Flag to wait for an event (or return immediately). * \return Indication of the presence of events. */ bool processEvents(bool waitForEvent); @@ -185,17 +187,17 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Returns the current location of the cursor (location in screen coordinates) - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; /** * Updates the location of the cursor (location in screen coordinates). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x: The x-coordinate of the cursor. + * \param y: The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); @@ -205,40 +207,40 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Returns the state of all modifier keys. - * \param keys The state of all modifier keys (true == pressed). - * \return Indication of success. + * \param keys: The state of all modifier keys (true == pressed). + * \return Indication of success. */ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const; /** * Returns the state of the mouse buttons (outside the message queue). - * \param buttons The state of the buttons. - * \return Indication of success. + * \param buttons: The state of the buttons. + * \return Indication of success. */ GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const; /** * Returns unsigned char from CUT_BUFFER0 - * \param selection Used by X11 only - * \return Returns the Clipboard + * \param selection: Used by X11 only. + * \return Returns the Clipboard. */ GHOST_TUns8 *getClipboard(bool selection) const; /** - * Puts buffer to system clipboard - * \param selection Used by X11 only - * \return No return + * Puts buffer to system clipboard. + * \param selection: Used by X11 only. + * \return No return. */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Show a system message box - * \param title The title of the message box - * \param message The message to display - * \param help_label Help button label - * \param continue_label Continue button label - * \param link An optional hyperlink - * \param dialog_options Options how to display the message + * \param title: The title of the message box. + * \param message: The message to display. + * \param help_label: Help button label. + * \param continue_label: Continue button label. + * \param link: An optional hyperlink. + * \param dialog_options: Options how to display the message. */ GHOST_TSuccess showMessageBox(const char *title, const char *message, @@ -265,6 +267,16 @@ class GHOST_SystemWin32 : public GHOST_System { int mouseY, void *data); + /*************************************************************************************** + ** Modify tablet API + ***************************************************************************************/ + + /** + * Set which tablet API to use. + * \param api: Enum indicating which API to use. + */ + void setTabletAPI(GHOST_TTabletAPI api) override; + protected: /** * Initializes the system. @@ -281,27 +293,27 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Converts raw WIN32 key codes from the wndproc to GHOST keys. - * \param vKey The virtual key from hardKey - * \param ScanCode The ScanCode of pressed key (similar to PS/2 Set 1) - * \param extend Flag if key is not primly (left or right) + * \param vKey: The virtual key from #hardKey. + * \param ScanCode: The ScanCode of pressed key (similar to PS/2 Set 1). + * \param extend: Flag if key is not primly (left or right). * \return The GHOST key (GHOST_kKeyUnknown if no match). */ GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const; /** * Catches raw WIN32 key codes from WM_INPUT in the wndproc. - * \param raw RawInput structure with detailed info about the key event - * \param keyDown Pointer flag that specify if a key is down - * \param vk Pointer to virtual key + * \param raw: RawInput structure with detailed info about the key event. + * \param keyDown: Pointer flag that specify if a key is down. + * \param vk: Pointer to virtual key. * \return The GHOST key (GHOST_kKeyUnknown if no match). */ GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_keyDown, bool *r_is_repeated_modifier); /** * Creates mouse button event. - * \param type The type of event to create. - * \param window The window receiving the event (the active window). - * \param mask The button mask of this event. + * \param type: The type of event to create. + * \param window: The window receiving the event (the active window). + * \param mask: The button mask of this event. * \return The event created. */ static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, @@ -310,34 +322,40 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Creates tablet events from Wintab events. - * \param type The type of pointer event - * \param window The window receiving the event (the active window). + * \param type: The type of pointer event. + * \param window: The window receiving the event (the active window). + * \param mask: The button mask of the calling event. + * \param mousePressed: Whether the mouse is currently pressed. + * \return True if the method handled the event. */ - static GHOST_TSuccess processWintabEvents(GHOST_TEventType type, GHOST_WindowWin32 *window); + static GHOST_TSuccess processWintabEvent(GHOST_TEventType type, + GHOST_WindowWin32 *window, + GHOST_TButtonMask mask, + bool mousePressed); /** * Creates tablet events from pointer events. - * \param type The type of pointer event - * \param window The window receiving the event (the active window). - * \param wParam The wParam from the wndproc - * \param lParam The lParam from the wndproc - * \param eventhandled true if the method handled the event + * \param type: The type of pointer event. + * \param window: The window receiving the event (the active window). + * \param wParam: The wParam from the wndproc. + * \param lParam: The lParam from the wndproc. + * \param eventhandled: True if the method handled the event. */ - static void processPointerEvents( + static void processPointerEvent( UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventhandled); /** * Creates cursor event. - * \param window The window receiving the event (the active window). + * \param window: The window receiving the event (the active window). * \return The event created. */ static GHOST_EventCursor *processCursorEvent(GHOST_WindowWin32 *window); /** * Handles a mouse wheel event. - * \param window The window receiving the event (the active window). - * \param wParam The wParam from the wndproc - * \param lParam The lParam from the wndproc + * \param window: The window receiving the event (the active window). + * \param wParam: The wParam from the wndproc. + * \param lParam: The lParam from the wndproc. */ static void processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam); @@ -345,23 +363,23 @@ class GHOST_SystemWin32 : public GHOST_System { * Creates a key event and updates the key data stored locally (m_modifierKeys). * In most cases this is a straightforward conversion of key codes. * For the modifier keys however, we want to distinguish left and right keys. - * \param window The window receiving the event (the active window). - * \param raw RawInput structure with detailed info about the key event + * \param window: The window receiving the event (the active window). + * \param raw: RawInput structure with detailed info about the key event. */ static GHOST_EventKey *processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw); /** * Process special keys (VK_OEM_*), to see if current key layout * gives us anything special, like ! on french AZERTY. - * \param vKey The virtual key from hardKey - * \param scanCode The ScanCode of pressed key (similar to PS/2 Set 1) + * \param vKey: The virtual key from #hardKey. + * \param scanCode: The ScanCode of pressed key (similar to PS/2 Set 1). */ GHOST_TKey processSpecialKey(short vKey, short scanCode) const; /** * Creates a window event. - * \param type The type of event to create. - * \param window The window receiving the event (the active window). + * \param type: The type of event to create. + * \param window: The window receiving the event (the active window). * \return The event created. */ static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window); @@ -369,9 +387,9 @@ class GHOST_SystemWin32 : public GHOST_System { #ifdef WITH_INPUT_IME /** * Creates a IME event. - * \param type The type of event to create. - * \param window The window receiving the event (the active window). - * \param data IME data. + * \param type: The type of event to create. + * \param window: The window receiving the event (the active window). + * \param data: IME data. * \return The event created. */ static GHOST_Event *processImeEvent(GHOST_TEventType type, @@ -381,7 +399,7 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Handles minimum window size. - * \param minmax The MINMAXINFO structure. + * \param minmax: The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO *minmax); @@ -390,7 +408,7 @@ class GHOST_SystemWin32 : public GHOST_System { * Handles Motion and Button events from a SpaceNavigator or related device. * Instead of returning an event object, this function communicates directly * with the GHOST_NDOFManager. - * \param raw RawInput structure with detailed info about the NDOF event + * \param raw: RawInput structure with detailed info about the NDOF event. * \return Whether an event was generated and sent. */ bool processNDOF(RAWINPUT const &raw); @@ -398,7 +416,7 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Returns the local state of the modifier keys (from the message queue). - * \param keys The state of the keys. + * \param keys: The state of the keys. */ inline void retrieveModifierKeys(GHOST_ModifierKeys &keys) const; @@ -421,7 +439,7 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Toggles console - * \param action + * \param action: * - 0 - Hides * - 1 - Shows * - 2 - Toggles diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 1906ec67c33..8e7b966aadf 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -23,7 +23,7 @@ * \ingroup GHOST */ -#include <X11/XKBlib.h> /* allow detectable autorepeate */ +#include <X11/XKBlib.h> /* Allow detectable auto-repeate. */ #include <X11/Xatom.h> #include <X11/Xutil.h> #include <X11/keysym.h> @@ -130,10 +130,9 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_ #endif #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) - /* note -- don't open connection to XIM server here, because the locale - * has to be set before opening the connection but setlocale() has not - * been called yet. the connection will be opened after entering - * the event loop. */ + /* NOTE: Don't open connection to XIM server here, because the locale has to be + * set before opening the connection but `setlocale()` has not been called yet. + * the connection will be opened after entering the event loop. */ m_xim = NULL; #endif @@ -189,7 +188,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_ /* Taking care not to overflow the tv.tv_sec * 1000 */ m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000; - /* use detectable autorepeate, mac and windows also do this */ + /* Use detectable auto-repeate, mac and windows also do this. */ int use_xkb; int xkb_opcode, xkb_event, xkb_error; int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion; @@ -325,19 +324,19 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 /** * Create a new window. * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window + * Never explicitly delete the window, use #disposeWindow() instead. + * \param title: The name of the window * (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state of the window when opened. + * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. - * \param exclusive: Use to show the window ontop and ignore others (used fullscreen). - * \param parentWindow Parent window - * \return The new window (or 0 if creation failed). + * \param exclusive: Use to show the window on top and ignore others (used full-screen). + * \param parentWindow: Parent window. + * \return The new window (or 0 if creation failed). */ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, GHOST_TInt32 left, @@ -393,7 +392,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings) { @@ -505,8 +504,8 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess GHOST_SystemX11::disposeContext(GHOST_IContext *context) { @@ -2284,6 +2283,7 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const } } +/* -------------------------------------------------------------------- */ /** \name Message Box * \{ */ class DialogData { diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index ee29f463fb6..bcebda66ae3 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -24,7 +24,7 @@ #pragma once -#include <X11/XKBlib.h> /* allow detectable autorepeate */ +#include <X11/XKBlib.h> /* Allow detectable auto-repeate. */ #include <X11/Xlib.h> #include "../GHOST_Types.h" @@ -121,20 +121,19 @@ class GHOST_SystemX11 : public GHOST_System { /** * Create a new window. * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window + * Never explicitly delete the window, use #disposeWindow() instead. + * \param title: The name of the window. * (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. - * \param stereoVisual Create a stereo visual for quad buffered stereo. - * \param exclusive Use to show the window ontop and ignore others - * (used fullscreen). - * \param parentWindow Parent (embedder) window - * \return The new window (or 0 if creation failed). + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state of the window when opened. + * \param type: The type of drawing context installed in this window. + * \param stereoVisual: Create a stereo visual for quad buffered stereo. + * \param exclusive: Use to show the window ontop and ignore others (used full*screen). + * \param parentWindow: Parent (embedder) window. + * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, @@ -151,20 +150,20 @@ class GHOST_SystemX11 : public GHOST_System { /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. - * \return The new context (or 0 if creation failed). + * \return The new context (or 0 if creation failed). */ GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings); /** * Dispose of a context. - * \param context Pointer to the context to be disposed. - * \return Indication of success. + * \param context: Pointer to the context to be disposed. + * \return Indication of success. */ GHOST_TSuccess disposeContext(GHOST_IContext *context); /** * Retrieves events from the system and stores them in the queue. - * \param waitForEvent Flag to wait for an event (or return immediately). + * \param waitForEvent: Flag to wait for an event (or return immediately). * \return Indication of the presence of events. */ bool processEvents(bool waitForEvent); @@ -175,15 +174,15 @@ class GHOST_SystemX11 : public GHOST_System { /** * Returns the state of all modifier keys. - * \param keys The state of all modifier keys (true == pressed). - * \return Indication of success. + * \param keys: The state of all modifier keys (true == pressed). + * \return Indication of success. */ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const; /** * Returns the state of the mouse buttons (outside the message queue). - * \param buttons The state of the buttons. - * \return Indication of success. + * \param buttons: The state of the buttons. + * \return Indication of success. */ GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const; @@ -220,26 +219,26 @@ class GHOST_SystemX11 : public GHOST_System { /** * Returns unsigned char from CUT_BUFFER0 - * \param selection Get selection, X11 only feature - * \return Returns the Clipboard indicated by Flag + * \param selection: Get selection, X11 only feature. + * \return Returns the Clipboard indicated by Flag. */ GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * \param buffer The buffer to copy to the clipboard - * \param selection Set the selection into the clipboard, X11 only feature + * \param buffer: The buffer to copy to the clipboard. + * \param selection: Set the selection into the clipboard, X11 only feature. */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Show a system message box - * \param title The title of the message box - * \param message The message to display - * \param help_label Help button label - * \param continue_label Continue button label - * \param link An optional hyperlink - * \param dialog_options Options how to display the message + * \param title: The title of the message box. + * \param message: The message to display. + * \param help_label: Help button label. + * \param continue_label: Continue button label. + * \param link: An optional hyperlink. + * \param dialog_options: Options how to display the message. */ GHOST_TSuccess showMessageBox(const char *title, const char *message, @@ -251,12 +250,12 @@ class GHOST_SystemX11 : public GHOST_System { /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. * Called by GHOST_DropTargetX11 class. - * \param eventType The type of drag'n'drop event - * \param draggedObjectType The type object concerned + * \param eventType: The type of drag'n'drop event. + * \param draggedObjectType: The type object concerned. * (currently array of file names, string, ?bitmap) - * \param mouseX x mouse coordinate (in window coordinates) - * \param mouseY y mouse coordinate - * \param window The window on which the event occurred + * \param mouseX: x mouse coordinate (in window coordinates). + * \param mouseY: y mouse coordinate. + * \param window: The window on which the event occurred. * \return Indication whether the event was handled. */ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h index 2e0f5d42230..3ca62202e5e 100644 --- a/intern/ghost/intern/GHOST_TimerManager.h +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -62,7 +62,7 @@ class GHOST_TimerManager { /** * Adds a timer task to the list. * It is only added when it not already present in the list. - * \param timer The timer task added to the list. + * \param timer: The timer task added to the list. * \return Indication as to whether addition has succeeded. */ GHOST_TSuccess addTimer(GHOST_TimerTask *timer); @@ -70,7 +70,7 @@ class GHOST_TimerManager { /** * Removes a timer task from the list. * It is only removed when it is found in the list. - * \param timer The timer task to be removed from the list. + * \param timer: The timer task to be removed from the list. * \return Indication as to whether removal has succeeded. */ GHOST_TSuccess removeTimer(GHOST_TimerTask *timer); @@ -84,15 +84,15 @@ class GHOST_TimerManager { /** * Checks all timer tasks to see if they are expired and fires them if needed. - * \param time The current time. + * \param time: The current time. * \return True if any timers were fired. */ bool fireTimers(GHOST_TUns64 time); /** * Checks this timer task to see if they are expired and fires them if needed. - * \param time The current time. - * \param task The timer task to check and optionally fire. + * \param time: The current time. + * \param task: The timer task to check and optionally fire. * \return True if the timer fired. */ bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task); diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h index 6dc0728e19b..9c81d3d2637 100644 --- a/intern/ghost/intern/GHOST_TimerTask.h +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -33,9 +33,9 @@ class GHOST_TimerTask : public GHOST_ITimerTask { public: /** * Constructor. - * \param start The timer start time. - * \param interval The interval between calls to the timerProc - * \param timerProc The callback invoked when the interval expires. + * \param start: The timer start time. + * \param interval: The interval between calls to the #timerProc. + * \param timerProc: The callback invoked when the interval expires. * \param userData: The timer user data. */ GHOST_TimerTask(GHOST_TUns64 start, @@ -62,7 +62,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { /** * Changes the timer start time. - * \param start The timer start time. + * \param start: The timer start time. */ void setStart(GHOST_TUns64 start) { @@ -80,7 +80,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { /** * Changes the timer interval. - * \param interval The timer interval. + * \param interval: The timer interval. */ void setInterval(GHOST_TUns64 interval) { @@ -98,7 +98,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { /** * Changes the time the timerProc will be called. - * \param next The time the timerProc will be called. + * \param next: The time the timerProc will be called. */ void setNext(GHOST_TUns64 next) { @@ -152,7 +152,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { /** * Changes the auxiliary storage room. - * \param auxData The auxiliary storage room. + * \param auxData: The auxiliary storage room. */ void setAuxData(GHOST_TUns32 auxData) { diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index c8c21b2b08f..d897fafc003 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -41,13 +41,12 @@ class GHOST_Window : public GHOST_IWindow { * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * \param width The width the window. - * \param heigh The height the window. - * \param state The state the window is initially opened with. - * \param type The type of drawing context installed in this window. - * \param stereoVisual Stereo visual for quad buffered stereo. - * \param exclusive Use to show the window ontop and ignore others - * (used fullscreen). + * \param width: The width the window. + * \param heigh: The height the window. + * \param state: The state the window is initially opened with. + * \param type: The type of drawing context installed in this window. + * \param stereoVisual: Stereo visual for quad buffered stereo. + * \param exclusive: Use to show the window ontop and ignore others (used full-screen). */ GHOST_Window(GHOST_TUns32 width, GHOST_TUns32 height, @@ -103,7 +102,7 @@ class GHOST_Window : public GHOST_IWindow { /** * Returns the current cursor shape. - * \return The current cursor shape. + * \return The current cursor shape. */ inline GHOST_TStandardCursor getCursorShape() const; @@ -114,18 +113,18 @@ class GHOST_Window : public GHOST_IWindow { /** * Set the shape of the cursor. - * \param cursorShape: The new cursor shape type id. - * \return Indication of success. + * \param cursorShape: The new cursor shape type id. + * \return Indication of success. */ GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape); /** * Set the shape of the cursor to a custom cursor. - * \param bitmap The bitmap data for the cursor. - * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hot-spot. - * \param hotY The Y coordinate of the cursor hot-spot. - * \return Indication of success. + * \param bitmap: The bitmap data for the cursor. + * \param mask: The mask data for the cursor. + * \param hotX: The X coordinate of the cursor hot-spot. + * \param hotY: The Y coordinate of the cursor hot-spot. + * \return Indication of success. */ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, @@ -137,7 +136,7 @@ class GHOST_Window : public GHOST_IWindow { /** * Returns the visibility state of the cursor. - * \return The visibility state of the cursor. + * \return The visibility state of the cursor. */ inline bool getCursorVisibility() const; inline GHOST_TGrabCursorMode getCursorGrabMode() const; @@ -149,15 +148,15 @@ class GHOST_Window : public GHOST_IWindow { /** * Shows or hides the cursor. - * \param visible The new visibility state of the cursor. - * \return Indication of success. + * \param visible: The new visibility state of the cursor. + * \return Indication of success. */ GHOST_TSuccess setCursorVisibility(bool visible); /** * Sets the cursor grab. - * \param mode The new grab state of the cursor. - * \return Indication of success. + * \param mode: The new grab state of the cursor. + * \return Indication of success. */ GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_TAxisFlag wrap_axis, @@ -172,7 +171,7 @@ class GHOST_Window : public GHOST_IWindow { /** * Sets the progress bar value displayed in the window/application icon - * \param progress The progress % (0.0 to 1.0) + * \param progress: The progress percentage (0.0 to 1.0). */ virtual GHOST_TSuccess setProgressBar(float /*progress*/) { @@ -188,14 +187,14 @@ class GHOST_Window : public GHOST_IWindow { } /** - * Sets the swap interval for swapBuffers. - * \param interval The swap interval to use. + * Sets the swap interval for #swapBuffers. + * \param interval: The swap interval to use. * \return A boolean success indicator. */ GHOST_TSuccess setSwapInterval(int interval); /** - * Gets the current swap interval for swapBuffers. + * Gets the current swap interval for #swapBuffers. * \return An integer. */ GHOST_TSuccess getSwapInterval(int &intervalOut); @@ -213,7 +212,7 @@ class GHOST_Window : public GHOST_IWindow { /** * Sets the window "modified" status, indicating unsaved changes - * \param isUnsavedChanges Unsaved changes or not + * \param isUnsavedChanges: Unsaved changes or not. * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); @@ -233,21 +232,21 @@ class GHOST_Window : public GHOST_IWindow { /** * Tries to install a rendering context in this window. * Child classes do not need to overload this method, - * They should overload newDrawingContext instead. - * \param type The type of rendering context installed. + * They should overload #newDrawingContext instead. + * \param type: The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type); /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext(); @@ -259,8 +258,8 @@ class GHOST_Window : public GHOST_IWindow { GHOST_TSuccess updateDrawingContext(); /** - * Gets the OpenGL framebuffer associated with the window's contents. - * \return The ID of an OpenGL framebuffer object. + * Gets the OpenGL frame-buffer associated with the window's contents. + * \return The ID of an OpenGL frame-buffer object. */ virtual unsigned int getDefaultFramebuffer(); @@ -314,7 +313,7 @@ class GHOST_Window : public GHOST_IWindow { protected: /** * Tries to install a rendering context in this window. - * \param type The type of rendering context installed. + * \param type: The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ virtual GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) = 0; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 97486c9e77a..3cfe46a080b 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -44,16 +44,16 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Constructor. * Creates a new window and opens it. - * To check if the window was created properly, use the getValid() method. - * \param systemCocoa The associated system class to forward events to - * \param title The text shown in the title bar of the window. - * \param left The coordinate of the left edge of the window. - * \param bottom The coordinate of the bottom edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state the window is initially opened with. - * \param type The type of drawing context installed in this window. - * \param stereoVisual Stereo visual for quad buffered stereo. + * To check if the window was created properly, use the #getValid() method. + * \param systemCocoa: The associated system class to forward events to. + * \param title: The text shown in the title bar of the window. + * \param left: The coordinate of the left edge of the window. + * \param bottom: The coordinate of the bottom edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state the window is initially opened with. + * \param type: The type of drawing context installed in this window. + * \param stereoVisual: Stereo visual for quad buffered stereo. */ GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, const char *title, @@ -88,12 +88,12 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Sets the title displayed in the title bar. - * \param title The title to display in the title bar. + * \param title: The title to display in the title bar. */ void setTitle(const char *title); /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \param title: The title displayed in the title bar. */ std::string getTitle() const; @@ -101,33 +101,33 @@ class GHOST_WindowCocoa : public GHOST_Window { * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are * relative to the upper-left corner of the screen. - * \param bounds The bounding rectangle of the window. + * \param bounds: The bounding rectangle of the window. */ void getWindowBounds(GHOST_Rect &bounds) const; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * \param bounds The bounding rectangle of the client area of the window. + * \param bounds: The bounding rectangle of the client area of the window. */ void getClientBounds(GHOST_Rect &bounds) const; /** * Resizes client rectangle width. - * \param width The new width of the client area of the window. + * \param width: The new width of the client area of the window. */ GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. - * \param height The new height of the client area of the window. + * \param height: The new height of the client area of the window. */ GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param width: The new width of the client area of the window. + * \param height: The new height of the client area of the window. */ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); @@ -139,17 +139,17 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Sets the window "modified" status, indicating unsaved changes - * \param isUnsavedChanges Unsaved changes or not + * \param isUnsavedChanges: Unsaved changes or not. * \return Indication of success. */ GHOST_TSuccess setModifiedState(bool isUnsavedChanges); /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param inX: The x-coordinate on the screen. + * \param inY: The y-coordinate on the screen. + * \param outX: The x-coordinate in the client rectangle. + * \param outY: The y-coordinate in the client rectangle. */ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -158,10 +158,10 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -171,10 +171,10 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Converts a point in screen coordinates to client rectangle coordinates * but without the y coordinate conversion needed for ghost compatibility. - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ void clientToScreenIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -184,10 +184,10 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Converts a point in screen coordinates to client rectangle coordinates, * but without the y coordinate conversion needed for ghost compatibility. - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ void screenToClientIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -202,14 +202,14 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Sets the state of the window (normal, minimized, maximized). - * \param state The state of the window. + * \param state: The state of the window. * \return Indication of success. */ GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * \param order The order of the window. + * \param order: The order of the window. * \return Indication of success. */ GHOST_TSuccess setOrder(GHOST_TWindowOrder order); @@ -226,7 +226,7 @@ class GHOST_WindowCocoa : public GHOST_Window { /** * Sets the progress bar value displayed in the window/application icon - * \param progress The progress % (0.0 to 1.0) + * \param progress: The progress percentage (0.0 to 1.0). */ GHOST_TSuccess setProgressBar(float progress); @@ -265,7 +265,7 @@ class GHOST_WindowCocoa : public GHOST_Window { protected: /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type); diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index f8e2f96d111..3f0ed2a4def 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -404,7 +404,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, [m_window setAcceptsMouseMovedEvents:YES]; NSView *contentview = [m_window contentView]; - [contentview setAcceptsTouchEvents:YES]; + [contentview setAllowedTouchTypes:(NSTouchTypeMaskDirect | NSTouchTypeMaskIndirect)]; [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, @@ -869,28 +869,26 @@ GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress) NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)]; [dockIcon lockFocus]; - NSRect progressBox = {{4, 4}, {120, 16}}; [[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; - // Track & Outline - [[NSColor blackColor] setFill]; - NSRectFill(progressBox); + NSRect progressRect = {{8, 8}, {112, 14}}; + NSBezierPath *progressPath; - [[NSColor whiteColor] set]; - NSFrameRect(progressBox); + /* Draw white track. */ + [[[NSColor whiteColor] colorWithAlphaComponent:0.6] setFill]; + progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:7 yRadius:7]; + [progressPath fill]; - // Progress fill - progressBox = NSInsetRect(progressBox, 1, 1); - - progressBox.size.width = progressBox.size.width * progress; - NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor darkGrayColor] - endingColor:[NSColor lightGrayColor]]; - [gradient drawInRect:progressBox angle:90]; - [gradient release]; + /* Black progress fill. */ + [[[NSColor blackColor] colorWithAlphaComponent:0.7] setFill]; + progressRect = NSInsetRect(progressRect, 2, 2); + progressRect.size.width *= progress; + progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:5 yRadius:5]; + [progressPath fill]; [dockIcon unlockFocus]; diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h index 34fdfd30f27..cb0337773c6 100644 --- a/intern/ghost/intern/GHOST_WindowManager.h +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -47,54 +47,54 @@ class GHOST_WindowManager { /** * Add a window to our list. * It is only added if it is not already in the list. - * \param window Pointer to the window to be added. - * \return Indication of success. + * \param window: Pointer to the window to be added. + * \return Indication of success. */ GHOST_TSuccess addWindow(GHOST_IWindow *window); /** * Remove a window from our list. - * \param window Pointer to the window to be removed. - * \return Indication of success. + * \param window: Pointer to the window to be removed. + * \return Indication of success. */ GHOST_TSuccess removeWindow(const GHOST_IWindow *window); /** * Returns whether the window is in our list. - * \param window Pointer to the window to query. - * \return A boolean indicator. + * \param window: Pointer to the window to query. + * \return A boolean indicator. */ bool getWindowFound(const GHOST_IWindow *window) const; /** - * Returns whether one of the windows is fullscreen. - * \return A boolean indicator. + * Returns whether one of the windows is full-screen. + * \return A boolean indicator. */ bool getFullScreen(void) const; /** * Returns pointer to the full-screen window. - * \return The full-screen window (NULL if not in full-screen). + * \return The full-screen window (NULL if not in full-screen). */ GHOST_IWindow *getFullScreenWindow(void) const; /** - * Activates fullscreen mode for a window. - * \param window The window displayed fullscreen. - * \return Indication of success. + * Activates full-screen mode for a window. + * \param window: The window displayed full-screen. + * \return Indication of success. */ GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual); /** - * Closes fullscreen mode down. - * \return Indication of success. + * Closes full-screen mode down. + * \return Indication of success. */ GHOST_TSuccess endFullScreen(void); /** * Sets new window as active window (the window receiving events). * There can be only one window active which should be in the current window list. - * \param window The new active window. + * \param window: The new active window. */ GHOST_TSuccess setActiveWindow(GHOST_IWindow *window); @@ -107,7 +107,7 @@ class GHOST_WindowManager { /** * Set this window to be inactive (not receiving events). - * \param window The window to deactivate. + * \param window: The window to deactivate. */ void setWindowInactive(const GHOST_IWindow *window); @@ -119,9 +119,9 @@ class GHOST_WindowManager { const std::vector<GHOST_IWindow *> &getWindows() const; /** - * Finds the window associated with an OS window object/handle - * \param osWindow The OS window object/handle - * \return The associated window, null if none corresponds + * Finds the window associated with an OS window object/handle. + * \param osWindow: The OS window object/handle. + * \return The associated window, null if none corresponds. */ GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow); diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index 0b5a7ee3450..aca06ba75b5 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -168,7 +168,7 @@ class GHOST_WindowNULL : public GHOST_Window { GHOST_SystemNULL *m_system; /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index 643c54c282e..bfe07af1c70 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -85,7 +85,7 @@ class GHOST_WindowSDL : public GHOST_Window { protected: /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type); diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index 1ee41f4d0f6..b62b5c24d60 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -118,7 +118,7 @@ class GHOST_WindowWayland : public GHOST_Window { std::string title; /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 18a48c9169e..5904a72b186 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -81,6 +81,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_nPressedButtons(0), m_customCursor(0), m_wantAlphaBackground(alphaBackground), + m_wintab(), m_normal_state(GHOST_kWindowStateNormal), m_user32(NULL), m_fpGetPointerInfoHistory(NULL), @@ -89,10 +90,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL), m_debug_context(is_debug) { - // Initialize tablet variables - memset(&m_wintab, 0, sizeof(m_wintab)); - m_tabletData = GHOST_TABLET_DATA_NONE; - // Create window if (state != GHOST_kWindowStateFullScreen) { RECT rect; @@ -297,66 +294,25 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_user32, "GetPointerTouchInfoHistory"); } - // Initialize Wintab - m_wintab.handle = ::LoadLibrary("Wintab32.dll"); - if (m_wintab.handle && m_system->getTabletAPI() != GHOST_kTabletNative) { - // Get API functions - m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA"); - m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA"); - m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose"); - m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket"); - m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable"); - m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap"); - - // Let's see if we can initialize tablet here. - // Check if WinTab available by getting system context info. - LOGCONTEXT lc = {0}; - lc.lcOptions |= CXO_SYSTEM; - if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) { - // Now init the tablet - /* The maximum tablet size, pressure and orientation (tilt) */ - AXIS TabletX, TabletY, Pressure, Orientation[3]; - - // Open a Wintab context - - // Open the context - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PACKETMODE; - lc.lcOptions |= CXO_MESSAGES; - lc.lcMoveMask = PACKETDATA; - - /* Set the entire tablet as active */ - m_wintab.info(WTI_DEVICES, DVC_X, &TabletX); - m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY); - - /* get the max pressure, to divide into a float */ - BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_wintab.maxPressure = Pressure.axMax; - else - m_wintab.maxPressure = 0; - - /* get the max tilt axes, to divide into floats */ - BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - /* all this assumes the minimum is 0 */ - m_wintab.maxAzimuth = Orientation[0].axMax; - m_wintab.maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_wintab.maxAzimuth = m_wintab.maxAltitude = 0; - } - } - - // The Wintab spec says we must open the context disabled if we are using cursor masks. - m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE); - if (m_wintab.enable && m_wintab.tablet) { - m_wintab.enable(m_wintab.tablet, TRUE); - } - } + if ((m_wintab.handle = ::LoadLibrary("Wintab32.dll")) && + (m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA")) && + (m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA")) && + (m_wintab.get = (GHOST_WIN32_WTGet)::GetProcAddress(m_wintab.handle, "WTGetA")) && + (m_wintab.set = (GHOST_WIN32_WTSet)::GetProcAddress(m_wintab.handle, "WTSetA")) && + (m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose")) && + (m_wintab.packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(m_wintab.handle, + "WTPacketsGet")) && + (m_wintab.queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(m_wintab.handle, + "WTQueueSizeGet")) && + (m_wintab.queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(m_wintab.handle, + "WTQueueSizeSet")) && + (m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable")) && + (m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap"))) { + initializeWintab(); + // Determine which tablet API to use and enable it. + updateWintab(m_system->m_windowFocus, m_system->m_windowFocus); } + CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar); } @@ -370,8 +326,9 @@ GHOST_WindowWin32::~GHOST_WindowWin32() } if (m_wintab.handle) { - if (m_wintab.close && m_wintab.tablet) { - m_wintab.close(m_wintab.tablet); + updateWintab(false, false); + if (m_wintab.close && m_wintab.context) { + m_wintab.close(m_wintab.context); } FreeLibrary(m_wintab.handle); @@ -819,6 +776,27 @@ bool GHOST_WindowWin32::getMousePressed() const return m_nPressedButtons; } +bool GHOST_WindowWin32::wintabSysButPressed() const +{ + return m_wintab.numSysButtons; +} + +void GHOST_WindowWin32::updateWintabSysBut(GHOST_MouseCaptureEventWin32 event) +{ + switch (event) { + case MousePressed: + m_wintab.numSysButtons++; + break; + case MouseReleased: + if (m_wintab.numSysButtons) + m_wintab.numSysButtons--; + break; + case OperatorGrab: + case OperatorUngrab: + break; + } +} + HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const { // Convert GHOST cursor to Windows OEM cursor @@ -1022,6 +1000,98 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha return (getStandardCursor(cursorShape)) ? GHOST_kSuccess : GHOST_kFailure; } +void GHOST_WindowWin32::updateWintab(bool active, bool visible) +{ + if (m_wintab.enable && m_wintab.overlap && m_wintab.context) { + bool enable = useTabletAPI(GHOST_kTabletWintab) && visible; + bool overlap = enable && active; + + /* Disabling context while the Window is not minimized can cause issues on receiving Wintab + * input while changing a window for some drivers, so only disable if either Wintab had been + * disabled or the window is minimized. */ + m_wintab.enable(m_wintab.context, enable); + m_wintab.overlap(m_wintab.context, overlap); + + if (!overlap) { + /* WT_PROXIMITY event doesn't occur unless tablet's cursor leaves the proximity while the + * window is active. */ + m_tabletInRange = false; + m_wintab.numSysButtons = 0; + m_wintab.sysButtonsPressed = 0; + } + } +} + +void GHOST_WindowWin32::initializeWintab() +{ + /* Return if wintab library handle doesn't exist or wintab is already initialized. */ + if (!m_wintab.handle || m_wintab.context) { + return; + } + + /* Check if WinTab available by getting system context info. */ + LOGCONTEXT lc = {0}; + if (m_wintab.open && m_wintab.info && m_wintab.queueSizeGet && m_wintab.queueSizeSet && + m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) { + + /* The pressure and orientation (tilt) */ + AXIS Pressure, Orientation[3]; + lc.lcPktData = PACKETDATA; + lc.lcPktMode = PACKETMODE; + lc.lcMoveMask = PACKETDATA; + lc.lcOptions |= CXO_CSRMESSAGES | CXO_MESSAGES; + /* Wacom maps y origin to the tablet's bottom. Invert to match Windows y origin mapping to the + * screen top. */ + lc.lcOutExtY = -lc.lcOutExtY; + + m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices); + + BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure); + m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0; + + BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation); + /* Does the tablet support azimuth ([0]) and altitude ([1])? */ + if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) { + /* All this assumes the minimum is 0. */ + m_wintab.maxAzimuth = Orientation[0].axMax; + m_wintab.maxAltitude = Orientation[1].axMax; + } + else { /* No so dont do tilt stuff. */ + m_wintab.maxAzimuth = m_wintab.maxAltitude = 0; + } + + /* The Wintab spec says we must open the context disabled if we are using cursor masks. */ + m_wintab.context = m_wintab.open(m_hWnd, &lc, FALSE); + + /* Wintab provides no way to determine the maximum queue size aside from checking if attempts + * to change the queue size are successful. */ + const int maxQueue = 500; + int queueSize = m_wintab.queueSizeGet(m_wintab.context); + + while (queueSize < maxQueue) { + int testSize = min(queueSize + 16, maxQueue); + if (m_wintab.queueSizeSet(m_wintab.context, testSize)) { + queueSize = testSize; + } + else { + /* From Windows Wintab Documentation for WTQueueSizeSet: + * "If the return value is zero, the context has no queue because the function deletes the + * original queue before attempting to create a new one. The application must continue + * calling the function with a smaller queue size until the function returns a non - zero + * value." + * + * In our case we start with a known valid queue size and in the event of failure roll + * back to the last valid queue size. The Wintab spec dates back to 16 bit Windows, thus + * assumes memory recently deallocated may not be available, which is no longer a practical + * concern. */ + m_wintab.queueSizeSet(m_wintab.context, queueSize); + break; + } + } + m_wintab.pkts.resize(queueSize); + } +} + GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam) { @@ -1104,28 +1174,20 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( return GHOST_kSuccess; } -void GHOST_WindowWin32::setTabletData(GHOST_TabletData *pTabletData) +void GHOST_WindowWin32::processWintabDisplayChangeEvent() { - if (pTabletData) { - m_tabletData = *pTabletData; - } - else { - m_tabletData = GHOST_TABLET_DATA_NONE; - } -} + LOGCONTEXT lc_sys = {0}, lc_curr = {0}; -void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state) -{ - if (!useTabletAPI(GHOST_kTabletWintab)) { - return; - } + if (m_wintab.info && m_wintab.get && m_wintab.set && m_wintab.info(WTI_DEFSYSCTX, 0, &lc_sys)) { - if (m_wintab.enable && m_wintab.tablet) { - m_wintab.enable(m_wintab.tablet, state); + m_wintab.get(m_wintab.context, &lc_curr); - if (m_wintab.overlap && state) { - m_wintab.overlap(m_wintab.tablet, TRUE); - } + lc_curr.lcOutOrgX = lc_sys.lcOutOrgX; + lc_curr.lcOutOrgY = lc_sys.lcOutOrgY; + lc_curr.lcOutExtX = lc_sys.lcOutExtX; + lc_curr.lcOutExtY = -lc_sys.lcOutExtY; + + m_wintab.set(m_wintab.context, &lc_curr); } } @@ -1135,7 +1197,7 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const return true; } else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) { - if (m_wintab.tablet) + if (m_wintab.numDevices) return api == GHOST_kTabletWintab; else return api == GHOST_kTabletNative; @@ -1145,114 +1207,232 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const } } -void GHOST_WindowWin32::processWin32TabletInitEvent() +void GHOST_WindowWin32::processWintabProximityEvent(bool inRange) { if (!useTabletAPI(GHOST_kTabletWintab)) { return; } // Let's see if we can initialize tablet here - if (m_wintab.info && m_wintab.tablet) { + if (m_wintab.info && m_wintab.context) { AXIS Pressure, Orientation[3]; /* The maximum tablet size */ BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_wintab.maxPressure = Pressure.axMax; - else - m_wintab.maxPressure = 0; + m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0; BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - m_wintab.maxAzimuth = Orientation[0].axMax; - m_wintab.maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_wintab.maxAzimuth = m_wintab.maxAltitude = 0; - } + /* does the tablet support azimuth ([0]) and altitude ([1]) */ + if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) { + m_wintab.maxAzimuth = Orientation[0].axMax; + m_wintab.maxAltitude = Orientation[1].axMax; } + else { /* no so dont do tilt stuff */ + m_wintab.maxAzimuth = m_wintab.maxAltitude = 0; + } + } + + m_tabletInRange = inRange; +} + +void GHOST_WindowWin32::processWintabInfoChangeEvent(LPARAM lParam) +{ + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); + + // Update number of connected Wintab digitizers + if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) { + m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices); + updateWintab((GHOST_WindowWin32 *)system->getWindowManager()->getActiveWindow() == this, + !::IsIconic(m_hWnd)); } +} + +GHOST_TSuccess GHOST_WindowWin32::wintabMouseToGhost(UINT cursor, + WORD physicalButton, + GHOST_TButtonMask &ghostButton) +{ + const WORD numButtons = 32; + BYTE logicalButtons[numButtons] = {0}; + BYTE systemButtons[numButtons] = {0}; - m_tabletData.Active = GHOST_kTabletModeNone; + m_wintab.info(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons); + m_wintab.info(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons); + + if (physicalButton >= numButtons) { + return GHOST_kFailure; + } + BYTE lb = logicalButtons[physicalButton]; + + if (lb >= numButtons) { + return GHOST_kFailure; + } + switch (systemButtons[lb]) { + case SBN_LCLICK: + ghostButton = GHOST_kButtonMaskLeft; + return GHOST_kSuccess; + case SBN_RCLICK: + ghostButton = GHOST_kButtonMaskRight; + return GHOST_kSuccess; + case SBN_MCLICK: + ghostButton = GHOST_kButtonMaskMiddle; + return GHOST_kSuccess; + default: + return GHOST_kFailure; + } } -void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) +GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo) { if (!useTabletAPI(GHOST_kTabletWintab)) { - return; + return GHOST_kFailure; } - if (m_wintab.packet && m_wintab.tablet) { - PACKET pkt; - if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) { - switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */ - case 0: - m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */ - break; - case 1: - m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */ - break; - case 2: - m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */ - break; - } + if (!(m_wintab.packetsGet && m_wintab.context)) { + return GHOST_kFailure; + } - if (m_wintab.maxPressure > 0) { - m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure; - } - else { - m_tabletData.Pressure = 1.0f; - } + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); - if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) { - ORIENTATION ort = pkt.pkOrientation; - float vecLen; - float altRad, azmRad; /* in radians */ + updatePendingWintabEvents(); - /* - * from the wintab spec: - * orAzimuth Specifies the clockwise rotation of the - * cursor about the z axis through a full circular range. - * - * orAltitude Specifies the angle with the x-y plane - * through a signed, semicircular range. Positive values - * specify an angle upward toward the positive z axis; - * negative values specify an angle downward toward the negative z axis. - * - * wintab.h defines .orAltitude as a UINT but documents .orAltitude - * as positive for upward angles and negative for downward angles. - * WACOM uses negative altitude values to show that the pen is inverted; - * therefore we cast .orAltitude as an (int) and then use the absolute value. - */ - - /* convert raw fixed point data to radians */ - altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0); - azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0); - - /* find length of the stylus' projected vector on the XY plane */ - vecLen = cos(altRad); - - /* from there calculate X and Y components based on azimuth */ - m_tabletData.Xtilt = sin(azmRad) * vecLen; - m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen); + auto &pendingEvents = m_wintab.pendingEvents; + size_t pendingEventSize = pendingEvents.size(); + outWintabInfo.resize(pendingEventSize); + + for (int i = 0; i < pendingEventSize; i++) { + PACKET pkt = pendingEvents.front(); + pendingEvents.pop(); + + GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE; + switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */ + case 0: + tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */ + break; + case 1: + tabletData.Active = GHOST_kTabletModeStylus; /* stylus */ + break; + case 2: + tabletData.Active = GHOST_kTabletModeEraser; /* eraser */ + break; + } + + if (m_wintab.maxPressure > 0) { + tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure; + } + + if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) { + ORIENTATION ort = pkt.pkOrientation; + float vecLen; + float altRad, azmRad; /* in radians */ + + /* + * from the wintab spec: + * orAzimuth Specifies the clockwise rotation of the + * cursor about the z axis through a full circular range. + * + * orAltitude Specifies the angle with the x-y plane + * through a signed, semicircular range. Positive values + * specify an angle upward toward the positive z axis; + * negative values specify an angle downward toward the negative z axis. + * + * wintab.h defines .orAltitude as a UINT but documents .orAltitude + * as positive for upward angles and negative for downward angles. + * WACOM uses negative altitude values to show that the pen is inverted; + * therefore we cast .orAltitude as an (int) and then use the absolute value. + */ + + /* convert raw fixed point data to radians */ + altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0); + azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0); + + /* find length of the stylus' projected vector on the XY plane */ + vecLen = cos(altRad); + + /* from there calculate X and Y components based on azimuth */ + tabletData.Xtilt = sin(azmRad) * vecLen; + tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen); + } + + outWintabInfo[i].x = pkt.pkX; + outWintabInfo[i].y = pkt.pkY; + + /* Some Wintab libraries don't handle relative button input correctly, so we track button + * presses manually. Examples include Wacom's Bamboo modifying button events in the queue when + * peeked, or missing events when entering the window when the context is not on top. */ + DWORD buttonsChanged = m_wintab.sysButtonsPressed ^ pkt.pkButtons; + + /* Find the index for the changed button from the button map. */ + WORD physicalButton = 0; + for (DWORD diff = (unsigned)buttonsChanged >> 1; diff > 0; diff = (unsigned)diff >> 1) { + physicalButton++; + } + + if (buttonsChanged && + wintabMouseToGhost(pkt.pkCursor, physicalButton, outWintabInfo[i].button)) { + if (buttonsChanged & pkt.pkButtons) { + outWintabInfo[i].type = GHOST_kEventButtonDown; } else { - m_tabletData.Xtilt = 0.0f; - m_tabletData.Ytilt = 0.0f; + outWintabInfo[i].type = GHOST_kEventButtonUp; } } + else { + outWintabInfo[i].type = GHOST_kEventCursorMove; + } + + m_wintab.sysButtonsPressed = pkt.pkButtons; + + outWintabInfo[i].time = system->millisSinceStart(pkt.pkTime); + outWintabInfo[i].tabletData = tabletData; } + + return GHOST_kSuccess; } -void GHOST_WindowWin32::bringTabletContextToFront() +/* Wintab (per documentation but may vary with implementation) does not update when its event + * buffer is full. This is an issue because we need some synchronization point between Wintab + * events and Win32 events, so we can't drain and process the queue immediately. We need to + * associate Wintab mouse events to Win32 mouse events because Wintab buttons are modal (a button + * associated to left click is not always a left click) and there's no way to reconstruct their + * mode from the Wintab API alone. There is no guaranteed ordering between Wintab and Win32 mouse + * events and no documented time stamp shared between the two, so we synchronize on mouse button + * events. */ +void GHOST_WindowWin32::updatePendingWintabEvents() { - if (!useTabletAPI(GHOST_kTabletWintab)) { + if (!(m_wintab.packetsGet && m_wintab.context)) { return; } + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); + + auto &pendingEvents = m_wintab.pendingEvents; + + /* Clear outdated events from queue. */ + GHOST_TUns64 currTime = system->getMilliSeconds(); + GHOST_TUns64 timeout = 300; + while (!pendingEvents.empty()) { + GHOST_TUns64 pktTime = system->millisSinceStart(pendingEvents.front().pkTime); + if (currTime - pktTime > timeout) { + pendingEvents.pop(); + } + else { + break; + } + } - if (m_wintab.overlap && m_wintab.tablet) { - m_wintab.overlap(m_wintab.tablet, TRUE); + /* Get new packets. */ + const int numPackets = m_wintab.packetsGet( + m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data()); + + int i = 0; + /* Don't queue outdated packets, such events can include packets that occurred before the current + * window lost and regained focus. */ + for (; i < numPackets; i++) { + GHOST_TUns64 pktTime = system->millisSinceStart(m_wintab.pkts[i].pkTime); + if (currTime - pktTime < timeout) { + break; + } + } + for (; i < numPackets; i++) { + pendingEvents.push(m_wintab.pkts[i]); } } diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 224ff53bf7b..a761d7d84dc 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -34,11 +34,14 @@ # include "GHOST_ImeWin32.h" #endif +#include <queue> #include <vector> #include <wintab.h> -#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) -#define PACKETMODE PK_BUTTONS +// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first +#define PACKETDATA \ + (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME) +#define PACKETMODE 0 #include <pktdef.h> class GHOST_SystemWin32; @@ -46,9 +49,13 @@ class GHOST_DropTargetWin32; // typedefs for WinTab functions to allow dynamic loading typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID); +typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA); +typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA); typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL); typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX); -typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); +typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID); +typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX); +typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int); typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL); typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL); @@ -229,7 +236,14 @@ struct GHOST_PointerInfoWin32 { GHOST_TButtonMask buttonMask; POINT pixelLocation; GHOST_TUns64 time; + GHOST_TabletData tabletData; +}; +struct GHOST_WintabInfoWin32 { + GHOST_TInt32 x, y; + GHOST_TEventType type; + GHOST_TButtonMask button; + GHOST_TUns64 time; GHOST_TabletData tabletData; }; @@ -248,16 +262,16 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Constructor. * Creates a new window and opens it. - * To check if the window was created properly, use the getValid() method. - * \param title The text shown in the title bar of the window. - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state the window is initially opened with. - * \param type The type of drawing context installed in this window. - * \param wantStereoVisual Stereo visual for quad buffered stereo. - * \param parentWindowHwnd + * To check if the window was created properly, use the #getValid() method. + * \param title: The text shown in the title bar of the window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state the window is initially opened with. + * \param type: The type of drawing context installed in this window. + * \param wantStereoVisual: Stereo visual for quad buffered stereo. + * \param parentWindowHwnd: TODO. */ GHOST_WindowWin32(GHOST_SystemWin32 *system, const char *title, @@ -293,7 +307,7 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Sets the title displayed in the title bar. - * \param title The title to display in the title bar. + * \param title: The title to display in the title bar. */ void setTitle(const char *title); @@ -307,33 +321,33 @@ class GHOST_WindowWin32 : public GHOST_Window { * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are * relative to the upper-left corner of the screen. - * \param bounds The bounding rectangle of the window. + * \param bounds: The bounding rectangle of the window. */ void getWindowBounds(GHOST_Rect &bounds) const; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * \param bounds The bounding rectangle of the client area of the window. + * \param bounds: The bounding rectangle of the client area of the window. */ void getClientBounds(GHOST_Rect &bounds) const; /** * Resizes client rectangle width. - * \param width The new width of the client area of the window. + * \param width: The new width of the client area of the window. */ GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. - * \param height The new height of the client area of the window. + * \param height: The new height of the client area of the window. */ GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param width: The new width of the client area of the window. + * \param height: The new height of the client area of the window. */ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); @@ -345,10 +359,10 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param inX: The x-coordinate on the screen. + * \param inY: The y-coordinate on the screen. + * \param outX: The x-coordinate in the client rectangle. + * \param outY: The y-coordinate in the client rectangle. */ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -357,10 +371,10 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX: The x-coordinate in the client rectangle. + * \param inY: The y-coordinate in the client rectangle. + * \param outX: The x-coordinate on the screen. + * \param outY: The y-coordinate on the screen. */ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, @@ -369,14 +383,14 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Sets the state of the window (normal, minimized, maximized). - * \param state The state of the window. + * \param state: The state of the window. * \return Indication of success. */ GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * \param order The order of the window. + * \param order: The order of the window. * \return Indication of success. */ GHOST_TSuccess setOrder(GHOST_TWindowOrder order); @@ -388,7 +402,7 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Sets the progress bar value displayed in the window/application icon - * \param progress The progress % + * \param progress: The progress percentage (0.0 to 1.0). */ GHOST_TSuccess setProgressBar(float progress); @@ -402,8 +416,8 @@ class GHOST_WindowWin32 : public GHOST_Window { * for any real button press, controls mouse * capturing). * - * \param event Whether mouse was pressed and released, or an operator grabbed or ungrabbed the - * mouse + * \param event: Whether mouse was pressed and released, + * or an operator grabbed or ungrabbed the mouse. */ void updateMouseCapture(GHOST_MouseCaptureEventWin32 event); @@ -417,34 +431,64 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Loads the windows equivalent of a standard GHOST cursor. - * \param visible Flag for cursor visibility. - * \param cursorShape The cursor shape. + * \param visible: Flag for cursor visibility. + * \param cursorShape: The cursor shape. */ HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const; void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; - const GHOST_TabletData &getTabletData() - { - return m_tabletData; - } + /** + * Handle setup and switch between Wintab and Pointer APIs. + * \param active: Whether the window is or will be in an active state. + * \param visible: Whether the window is currently (or will be) visible). + */ + void updateWintab(bool active, bool visible); - void setTabletData(GHOST_TabletData *tabletData); + /** + * Query whether given tablet API should be used. + * \param api: Tablet API to test. + */ bool useTabletAPI(GHOST_TTabletAPI api) const; /** * Translate WM_POINTER events into GHOST_PointerInfoWin32 structs. - * \param outPointerInfo Storage to return resulting GHOST_PointerInfoWin32 structs - * \param wParam WPARAM of the event - * \param lParam LPARAM of the event + * \param outPointerInfo: Storage to return resulting GHOST_PointerInfoWin32 structs. + * \param wParam: WPARAM of the event. + * \param lParam: LPARAM of the event. + * \return True if #outPointerInfo was updated. */ GHOST_TSuccess getPointerInfo(std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam); - void processWin32TabletActivateEvent(WORD state); - void processWin32TabletInitEvent(); - void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); - void bringTabletContextToFront(); + /** + * Handle Wintab coordinate changes when DisplayChange events occur. + */ + void processWintabDisplayChangeEvent(); + + /** + * Set tablet details when a cursor enters range. + * \param inRange: Whether the Wintab device is in tracking range. + */ + void processWintabProximityEvent(bool inRange); + + /** + * Handle Wintab info changes such as change in number of connected tablets. + * \param lParam: LPARAM of the event. + */ + void processWintabInfoChangeEvent(LPARAM lParam); + + /** + * Translate Wintab packets into GHOST_WintabInfoWin32 structs. + * \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 structs. + * \return Success if able to read packets, even if there are none. + */ + GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo); + + /** + * Updates stored pending Wintab events. + */ + void updatePendingWintabEvents(); GHOST_TSuccess beginFullScreen() const { @@ -459,12 +503,25 @@ class GHOST_WindowWin32 : public GHOST_Window { GHOST_TUns16 getDPIHint() override; /** - * Get whether there are currently any mouse buttons pressed - * \return True if there are any currently pressed mouse buttons + * Get whether there are currently any mouse buttons pressed. + * \return True if there are any currently pressed mouse buttons. */ bool getMousePressed() const; - /** Whether a tablet stylus is being tracked */ + /** + * Get if there are currently pressed Wintab buttons associated to a Windows mouse button press. + * \return True if there are currently any pressed Wintab buttons associated to a Windows + * mouse button press. + */ + bool wintabSysButPressed() const; + + /** + * Register a Wintab button has been associated to a Windows mouse button press. + * \param event: Whether the button was pressed or released. + */ + void updateWintabSysBut(GHOST_MouseCaptureEventWin32 event); + + /** Whether a tablet stylus is being tracked. */ bool m_tabletInRange; /** if the window currently resizing */ @@ -483,7 +540,7 @@ class GHOST_WindowWin32 : public GHOST_Window { private: /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type); @@ -497,7 +554,7 @@ class GHOST_WindowWin32 : public GHOST_Window { /** * Sets the cursor grab on the window using native window system calls. * Using registerMouseClickEvent. - * \param mode GHOST_TGrabCursorMode. + * \param mode: GHOST_TGrabCursorMode. */ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); @@ -547,28 +604,55 @@ class GHOST_WindowWin32 : public GHOST_Window { static const wchar_t *s_windowClassName; static const int s_maxTitleLength; - /** Tablet data for GHOST */ - GHOST_TabletData m_tabletData; - /* Wintab API */ struct { /** WinTab dll handle */ - HMODULE handle; + HMODULE handle = NULL; /** API functions */ - GHOST_WIN32_WTInfo info; - GHOST_WIN32_WTOpen open; - GHOST_WIN32_WTClose close; - GHOST_WIN32_WTPacket packet; - GHOST_WIN32_WTEnable enable; - GHOST_WIN32_WTOverlap overlap; + GHOST_WIN32_WTInfo info = NULL; + GHOST_WIN32_WTGet get = NULL; + GHOST_WIN32_WTSet set = NULL; + GHOST_WIN32_WTOpen open = NULL; + GHOST_WIN32_WTClose close = NULL; + GHOST_WIN32_WTPacketsGet packetsGet = NULL; + GHOST_WIN32_WTQueueSizeGet queueSizeGet = NULL; + GHOST_WIN32_WTQueueSizeSet queueSizeSet = NULL; + GHOST_WIN32_WTEnable enable = NULL; + GHOST_WIN32_WTOverlap overlap = NULL; /** Stores the Tablet context if detected Tablet features using WinTab.dll */ - HCTX tablet; - LONG maxPressure; - LONG maxAzimuth, maxAltitude; + HCTX context = NULL; + /** Number of connected Wintab digitizers */ + UINT numDevices = 0; + /** Number of cursors currently in contact mapped to system buttons */ + GHOST_TUns8 numSysButtons = 0; + /** Cursors currently in contact mapped to system buttons */ + DWORD sysButtonsPressed = 0; + LONG maxPressure = 0; + LONG maxAzimuth = 0, maxAltitude = 0; + /** Reusable buffer to read in Wintab Packets. */ + std::vector<PACKET> pkts; + /** Queue of packets to process. */ + std::queue<PACKET> pendingEvents; } m_wintab; + /** + * Wintab setup. + */ + void initializeWintab(); + + /** + * Convert Wintab system mapped (mouse) buttons into Ghost button mask. + * \param cursor: The Wintab cursor associated to the button. + * \param physicalButton: The physical button ID to inspect. + * \param buttonMask: Return pointer for button found. + * \return Whether an associated button was found. + */ + GHOST_TSuccess wintabMouseToGhost(UINT cursor, + WORD physicalButton, + GHOST_TButtonMask &buttonMask); + GHOST_TWindowState m_normal_state; /** user32 dll handle*/ diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index a4d17d1add3..01699e9d1ce 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -54,16 +54,16 @@ class GHOST_WindowX11 : public GHOST_Window { * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * \param title The text shown in the title bar of the window. - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state the window is initially opened with. - * \param parentWindow Parent (embedder) window - * \param type The type of drawing context installed in this window. - * \param stereoVisual Stereo visual for quad buffered stereo. - * \param alphaBackground Enable alpha blending of window with display background + * \param title: The text shown in the title bar of the window. + * \param left: The coordinate of the left edge of the window. + * \param top: The coordinate of the top edge of the window. + * \param width: The width the window. + * \param height: The height the window. + * \param state: The state the window is initially opened with. + * \param parentWindow: Parent (embedder) window. + * \param type: The type of drawing context installed in this window. + * \param stereoVisual: Stereo visual for quad buffered stereo. + * \param alphaBackground: Enable alpha blending of window with display background. */ GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, @@ -186,7 +186,7 @@ class GHOST_WindowX11 : public GHOST_Window { protected: /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type); diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp index 583bda9731a..2bf67c121f8 100644 --- a/intern/ghost/intern/GHOST_XrContext.cpp +++ b/intern/ghost/intern/GHOST_XrContext.cpp @@ -277,7 +277,7 @@ void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *c * \{ */ /** - * \param layer_name May be NULL for extensions not belonging to a specific layer. + * \param layer_name: May be NULL for extensions not belonging to a specific layer. */ void GHOST_XrContext::initExtensionsEx(std::vector<XrExtensionProperties> &extensions, const char *layer_name) diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index e43991853cb..73b73a8f046 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -222,7 +222,7 @@ GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent( m_oxr->session_state = lifecycle.state; /* Runtime may send events for apparently destroyed session. Our handle should be NULL then. */ - assert((m_oxr->session == XR_NULL_HANDLE) || (m_oxr->session == lifecycle.session)); + assert(m_oxr->session == XR_NULL_HANDLE || m_oxr->session == lifecycle.session); switch (lifecycle.state) { case XR_SESSION_STATE_READY: { diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index b6e3c0ecf5f..27a764cd050 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -233,8 +233,8 @@ else() set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include") endif() -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS}") +string(APPEND CMAKE_C_FLAGS " ${PLATFORM_CFLAGS}") +string(APPEND CMAKE_CXX_FLAGS " ${PLATFORM_CFLAGS}") # ----------------------------------------------------------------------------- # Executables diff --git a/intern/guardedalloc/tests/guardedalloc_overflow_test.cc b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc index e5754bc95ea..efbfc171fff 100644 --- a/intern/guardedalloc/tests/guardedalloc_overflow_test.cc +++ b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc @@ -5,11 +5,6 @@ #include "MEM_guardedalloc.h" /* We expect to abort on integer overflow, to prevent possible exploits. */ -#ifdef _WIN32 -# define ABORT_PREDICATE ::testing::ExitedWithCode(3) -#else -# define ABORT_PREDICATE ::testing::KilledBySignal(SIGABRT) -#endif #if defined(__GNUC__) && !defined(__clang__) /* Disable since it's the purpose of this test. */ diff --git a/intern/libmv/CMakeLists.txt b/intern/libmv/CMakeLists.txt index b372cfe92bb..6fcf664d1f5 100644 --- a/intern/libmv/CMakeLists.txt +++ b/intern/libmv/CMakeLists.txt @@ -51,8 +51,6 @@ if(WITH_LIBMV) list(APPEND INC ${GFLAGS_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS} - ../../extern/ceres/include - ../../extern/ceres/config ../guardedalloc ) @@ -60,6 +58,8 @@ if(WITH_LIBMV) ${EIGEN3_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} + ../../extern/ceres/include + ../../extern/ceres/config ) list(APPEND LIB diff --git a/intern/libmv/bundle.sh b/intern/libmv/bundle.sh index 48da102b801..db8f88845a8 100755 --- a/intern/libmv/bundle.sh +++ b/intern/libmv/bundle.sh @@ -127,8 +127,6 @@ if(WITH_LIBMV) list(APPEND INC \${GFLAGS_INCLUDE_DIRS} \${GLOG_INCLUDE_DIRS} - ../../extern/ceres/include - ../../extern/ceres/config ../guardedalloc ) @@ -136,6 +134,8 @@ if(WITH_LIBMV) \${EIGEN3_INCLUDE_DIRS} \${PNG_INCLUDE_DIRS} \${ZLIB_INCLUDE_DIRS} + ../../extern/ceres/include + ../../extern/ceres/config ) list(APPEND LIB diff --git a/intern/libmv/intern/reconstruction.cc b/intern/libmv/intern/reconstruction.cc index 64f00b19df0..0f4e890d4ca 100644 --- a/intern/libmv/intern/reconstruction.cc +++ b/intern/libmv/intern/reconstruction.cc @@ -95,12 +95,23 @@ void libmv_solveRefineIntrinsics( if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) { bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT; } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) { - bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1; - } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { - bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2; - } + +#define SET_DISTORTION_FLAG_CHECKED(type, coefficient) \ + do { \ + if (refine_intrinsics & LIBMV_REFINE_ ## type ##_DISTORTION_ ## coefficient) { \ + bundle_intrinsics |= libmv::BUNDLE_ ## type ## _ ## coefficient; \ + } \ + } while (0) + + SET_DISTORTION_FLAG_CHECKED(RADIAL, K1); + SET_DISTORTION_FLAG_CHECKED(RADIAL, K2); + SET_DISTORTION_FLAG_CHECKED(RADIAL, K3); + SET_DISTORTION_FLAG_CHECKED(RADIAL, K4); + + SET_DISTORTION_FLAG_CHECKED(TANGENTIAL, P1); + SET_DISTORTION_FLAG_CHECKED(TANGENTIAL, P2); + +#undef SET_DISTORTION_FLAG_CHECKED progress_update_callback(callback_customdata, 1.0, "Refining solution"); diff --git a/intern/libmv/intern/reconstruction.h b/intern/libmv/intern/reconstruction.h index 727a4943add..408ac884684 100644 --- a/intern/libmv/intern/reconstruction.h +++ b/intern/libmv/intern/reconstruction.h @@ -31,10 +31,22 @@ struct libmv_CameraIntrinsicsOptions; typedef struct libmv_Reconstruction libmv_Reconstruction; enum { - LIBMV_REFINE_FOCAL_LENGTH = (1 << 0), - LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1), - LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2), - LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 4), + LIBMV_REFINE_FOCAL_LENGTH = (1 << 0), + LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1), + + LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2), + LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 3), + LIBMV_REFINE_RADIAL_DISTORTION_K3 = (1 << 4), + LIBMV_REFINE_RADIAL_DISTORTION_K4 = (1 << 5), + LIBMV_REFINE_RADIAL_DISTORTION = (LIBMV_REFINE_RADIAL_DISTORTION_K1 | + LIBMV_REFINE_RADIAL_DISTORTION_K2 | + LIBMV_REFINE_RADIAL_DISTORTION_K3 | + LIBMV_REFINE_RADIAL_DISTORTION_K4), + + LIBMV_REFINE_TANGENTIAL_DISTORTION_P1 = (1 << 6), + LIBMV_REFINE_TANGENTIAL_DISTORTION_P2 = (1 << 7), + LIBMV_REFINE_TANGENTIAL_DISTORTION = (LIBMV_REFINE_TANGENTIAL_DISTORTION_P1 | + LIBMV_REFINE_TANGENTIAL_DISTORTION_P2), }; typedef struct libmv_ReconstructionOptions { diff --git a/intern/libmv/libmv/image/array_nd_test.cc b/intern/libmv/libmv/image/array_nd_test.cc index 313f21b60e9..dc7cfacf90d 100644 --- a/intern/libmv/libmv/image/array_nd_test.cc +++ b/intern/libmv/libmv/image/array_nd_test.cc @@ -191,10 +191,10 @@ TEST(ArrayND, CopyFrom) { a(1, 1, 0) = 4; ArrayND<float, 3> b; b.CopyFrom(a); - EXPECT_FLOAT_EQ(1.f, b(0, 0, 0)); - EXPECT_FLOAT_EQ(2.f, b(0, 1, 0)); - EXPECT_FLOAT_EQ(3.f, b(1, 0, 0)); - EXPECT_FLOAT_EQ(4.f, b(1, 1, 0)); + EXPECT_FLOAT_EQ(1.0f, b(0, 0, 0)); + EXPECT_FLOAT_EQ(2.0f, b(0, 1, 0)); + EXPECT_FLOAT_EQ(3.0f, b(1, 0, 0)); + EXPECT_FLOAT_EQ(4.0f, b(1, 1, 0)); } TEST(ArrayND, MultiplyElements) { diff --git a/intern/libmv/libmv/multiview/homography.h b/intern/libmv/libmv/multiview/homography.h index 6d810c845ed..a76aa9405a5 100644 --- a/intern/libmv/libmv/multiview/homography.h +++ b/intern/libmv/libmv/multiview/homography.h @@ -27,21 +27,23 @@ namespace libmv { /** * 2D homography transformation estimation. - * + * * This function estimates the homography transformation from a list of 2D * correspondences which represents either: * * - 3D points on a plane, with a general moving camera. * - 3D points with a rotating camera (pure rotation). * - 3D points + different planar projections - * - * \param x1 The first 2xN or 3xN matrix of euclidean or homogeneous points. - * \param x2 The second 2xN or 3xN matrix of euclidean or homogeneous points. - * \param H The 3x3 homography transformation matrix (8 dof) such that - * x2 = H * x1 with |a b c| - * H = |d e f| - * |g h 1| - * \param expected_precision The expected precision in order for instance + * + * \param x1: The first 2xN or 3xN matrix of euclidean or homogeneous points. + * \param x2: The second 2xN or 3xN matrix of euclidean or homogeneous points. + * \param H: The 3x3 homography transformation matrix (8 dof) such that + * <pre> + * x2 = H * x1 with |a b c| + * H = |d e f| + * |g h 1| + * </pre> + * \param expected_precision: The expected precision in order for instance * to accept almost homography matrices. * * \return True if the transformation estimation has succeeded. @@ -113,16 +115,18 @@ bool EstimateHomography2DFromCorrespondences( * \param[in] x1 The first 4xN matrix of homogeneous points * \param[in] x2 The second 4xN matrix of homogeneous points * \param[out] H The 4x4 homography transformation matrix (15 dof) such that - * x2 = H * x1 with |a b c d| - * H = |e f g h| - * |i j k l| - * |m n o 1| - * \param[in] expected_precision The expected precision in order for instance + * <pre> + * x2 = H * x1 with |a b c d| + * H = |e f g h| + * |i j k l| + * |m n o 1| + * </pre> + * \param[in] expected_precision The expected precision in order for instance * to accept almost homography matrices. * * \return true if the transformation estimation has succeeded * - * \note Need at least 5 non coplanar points + * \note Need at least 5 non coplanar points * \note Points coordinates must be in homogeneous coordinates */ bool Homography3DFromCorrespondencesLinear(const Mat &x1, diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc index 3df39ab8936..d62f0ebe94f 100644 --- a/intern/libmv/libmv/simple_pipeline/bundle.cc +++ b/intern/libmv/libmv/simple_pipeline/bundle.cc @@ -368,6 +368,8 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) { APPEND_BUNDLING_INTRINSICS("px, py", BUNDLE_PRINCIPAL_POINT); APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1); APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2); + APPEND_BUNDLING_INTRINSICS("k3", BUNDLE_RADIAL_K3); + APPEND_BUNDLING_INTRINSICS("k4", BUNDLE_RADIAL_K4); APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1); APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2); @@ -744,7 +746,8 @@ void EuclideanBundleCommonIntrinsics( std::vector<int> constant_intrinsics; #define MAYBE_SET_CONSTANT(bundle_enum, offset) \ - if (!(bundle_intrinsics & bundle_enum)) { \ + if (!(bundle_intrinsics & bundle_enum) || \ + !packed_intrinsics.IsParameterDefined(offset)) { \ constant_intrinsics.push_back(offset); \ } MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH, @@ -755,22 +758,19 @@ void EuclideanBundleCommonIntrinsics( PackedIntrinsics::OFFSET_PRINCIPAL_POINT_Y); MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, PackedIntrinsics::OFFSET_K1); MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, PackedIntrinsics::OFFSET_K2); + MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K3, PackedIntrinsics::OFFSET_K3); + MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K4, PackedIntrinsics::OFFSET_K4); MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, PackedIntrinsics::OFFSET_P1); MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, PackedIntrinsics::OFFSET_P2); #undef MAYBE_SET_CONSTANT - // Always set K3 and K4 constant, it's not used at the moment. - constant_intrinsics.push_back(PackedIntrinsics::OFFSET_K3); - constant_intrinsics.push_back(PackedIntrinsics::OFFSET_K4); + if (!constant_intrinsics.empty()) { + ceres::SubsetParameterization *subset_parameterization = + new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS, + constant_intrinsics); - // TODO(sergey): Mark all parameters which are not used by the distortion - // model as constant. - - ceres::SubsetParameterization *subset_parameterization = - new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS, - constant_intrinsics); - - problem.SetParameterization(intrinsics_block, subset_parameterization); + problem.SetParameterization(intrinsics_block, subset_parameterization); + } } // Configure the solver. diff --git a/intern/libmv/libmv/simple_pipeline/bundle.h b/intern/libmv/libmv/simple_pipeline/bundle.h index 781bd8476fe..5f420da0045 100644 --- a/intern/libmv/libmv/simple_pipeline/bundle.h +++ b/intern/libmv/libmv/simple_pipeline/bundle.h @@ -101,14 +101,22 @@ void EuclideanBundle(const Tracks &tracks, */ enum BundleIntrinsics { BUNDLE_NO_INTRINSICS = 0, - BUNDLE_FOCAL_LENGTH = 1, - BUNDLE_PRINCIPAL_POINT = 2, - BUNDLE_RADIAL_K1 = 4, - BUNDLE_RADIAL_K2 = 8, - BUNDLE_RADIAL = 12, - BUNDLE_TANGENTIAL_P1 = 16, - BUNDLE_TANGENTIAL_P2 = 32, - BUNDLE_TANGENTIAL = 48, + + BUNDLE_FOCAL_LENGTH = (1 << 0), + BUNDLE_PRINCIPAL_POINT = (1 << 1), + + BUNDLE_RADIAL_K1 = (1 << 2), + BUNDLE_RADIAL_K2 = (1 << 3), + BUNDLE_RADIAL_K3 = (1 << 4), + BUNDLE_RADIAL_K4 = (1 << 5), + BUNDLE_RADIAL = (BUNDLE_RADIAL_K1 | + BUNDLE_RADIAL_K2 | + BUNDLE_RADIAL_K3 | + BUNDLE_RADIAL_K4), + + BUNDLE_TANGENTIAL_P1 = (1 << 6), + BUNDLE_TANGENTIAL_P2 = (1 << 7), + BUNDLE_TANGENTIAL = (BUNDLE_TANGENTIAL_P1 | BUNDLE_TANGENTIAL_P2), }; enum BundleConstraints { BUNDLE_NO_CONSTRAINTS = 0, diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h index 30b0f1abf7b..ba67ec468dc 100644 --- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h +++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h @@ -292,7 +292,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics { PolynomialCameraIntrinsics(); PolynomialCameraIntrinsics(const PolynomialCameraIntrinsics &from); - DistortionModelType GetDistortionModelType() const { + DistortionModelType GetDistortionModelType() const override { return DISTORTION_MODEL_POLYNOMIAL; } @@ -316,7 +316,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics { void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, - double *image_y) const; + double *image_y) const override; // Invert camera intrinsics on the image point to get normalized coordinates. // @@ -325,7 +325,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics { void InvertIntrinsics(double image_x, double image_y, double *normalized_x, - double *normalized_y) const; + double *normalized_y) const override; virtual void Pack(PackedIntrinsics* packed_intrinsics) const override; virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override; @@ -354,7 +354,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics { DivisionCameraIntrinsics(); DivisionCameraIntrinsics(const DivisionCameraIntrinsics &from); - DistortionModelType GetDistortionModelType() const { + DistortionModelType GetDistortionModelType() const override { return DISTORTION_MODEL_DIVISION; } @@ -372,7 +372,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics { void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, - double *image_y) const; + double *image_y) const override; // Invert camera intrinsics on the image point to get normalized coordinates. // @@ -381,7 +381,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics { void InvertIntrinsics(double image_x, double image_y, double *normalized_x, - double *normalized_y) const; + double *normalized_y) const override; virtual void Pack(PackedIntrinsics* packed_intrinsics) const override; virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override; @@ -407,7 +407,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics { NukeCameraIntrinsics(); NukeCameraIntrinsics(const NukeCameraIntrinsics &from); - DistortionModelType GetDistortionModelType() const { + DistortionModelType GetDistortionModelType() const override { return DISTORTION_MODEL_NUKE; } @@ -425,7 +425,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics { void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, - double *image_y) const; + double *image_y) const override; // Invert camera intrinsics on the image point to get normalized coordinates. // @@ -434,7 +434,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics { void InvertIntrinsics(double image_x, double image_y, double *normalized_x, - double *normalized_y) const; + double *normalized_y) const override; virtual void Pack(PackedIntrinsics* packed_intrinsics) const override; virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override; @@ -464,7 +464,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics { BrownCameraIntrinsics(); BrownCameraIntrinsics(const BrownCameraIntrinsics &from); - DistortionModelType GetDistortionModelType() const { + DistortionModelType GetDistortionModelType() const override { return DISTORTION_MODEL_BROWN; } @@ -489,7 +489,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics { void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, - double *image_y) const; + double *image_y) const override; // Invert camera intrinsics on the image point to get normalized coordinates. // @@ -498,7 +498,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics { void InvertIntrinsics(double image_x, double image_y, double *normalized_x, - double *normalized_y) const; + double *normalized_y) const override; virtual void Pack(PackedIntrinsics* packed_intrinsics) const override; virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override; diff --git a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h index aa3eeaf193d..25253af32fe 100644 --- a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h +++ b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h @@ -38,11 +38,11 @@ namespace libmv { // and if expected error estimation is too large, keyframe candidate // is rejecting. // -// \param tracks contains all tracked correspondences between frames -// expected to be undistorted and normalized -// \param intrinsics is camera intrinsics -// \param keyframes will contain all images number which are considered -// good to be used for reconstruction +// \param tracks: contains all tracked correspondences between frames +// expected to be undistorted and normalized. +// \param intrinsics: is camera intrinsics. +// \param keyframes: will contain all images number which are considered +// good to be used for reconstruction. void SelectKeyframesBasedOnGRICAndVariance( const Tracks &tracks, const CameraIntrinsics &intrinsics, diff --git a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc index e9d7c2e78be..73ad4faed9c 100644 --- a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc +++ b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc @@ -47,7 +47,7 @@ double PackedIntrinsics::GetPrincipalPointY() const { void PackedIntrinsics::SetParameter(int index, double value) { parameters_.at(index) = value; - known_parameters_.at(index) = value; + known_parameters_.at(index) = true; } double PackedIntrinsics::GetParameter(int index) const { // TODO(sergey): Consider adding a check for whether the parameter is known. @@ -55,4 +55,8 @@ double PackedIntrinsics::GetParameter(int index) const { return parameters_.at(index); } +bool PackedIntrinsics::IsParameterDefined(int offset) { + return known_parameters_.at(offset); +} + } // namespace libmv diff --git a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h index e551fe74800..cbea599fccd 100644 --- a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h +++ b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h @@ -86,6 +86,8 @@ class PackedIntrinsics { double* GetParametersBlock() { return parameters_.data(); } const double* GetParametersBlock() const { return parameters_.data(); } + bool IsParameterDefined(int offset); + private: void SetParameter(int index, double value); double GetParameter(int index) const; diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h index 6827ac35050..e4ad4c66d8a 100644 --- a/intern/mantaflow/extern/manta_fluid_API.h +++ b/intern/mantaflow/extern/manta_fluid_API.h @@ -33,44 +33,44 @@ struct MANTA; /* Fluid functions */ struct MANTA *manta_init(int *res, struct FluidModifierData *fmd); void manta_free(struct MANTA *fluid); -int manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd); -int manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd); -int manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd); -int manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd); -int manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_read_data(struct MANTA *fluid, - struct FluidModifierData *fmd, - int framenr, - bool resumable); -int manta_read_noise(struct MANTA *fluid, +bool manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd); +bool manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd); +bool manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd); +bool manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd); +bool manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_read_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool resumable); -int manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_read_particles(struct MANTA *fluid, - struct FluidModifierData *fmd, - int framenr, - bool resumable); -int manta_read_guiding(struct MANTA *fluid, - struct FluidModifierData *fmd, - int framenr, - bool sourceDomain); -int manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); -int manta_has_guiding(struct MANTA *fluid, +bool manta_read_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, - bool domain); + bool resumable); +bool manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_read_particles(struct MANTA *fluid, + struct FluidModifierData *fmd, + int framenr, + bool resumable); +bool manta_read_guiding(struct MANTA *fluid, + struct FluidModifierData *fmd, + int framenr, + bool sourceDomain); +bool manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr); +bool manta_has_guiding(struct MANTA *fluid, + struct FluidModifierData *fmd, + int framenr, + bool domain); void manta_update_variables(struct MANTA *fluid, struct FluidModifierData *fmd); int manta_get_frame(struct MANTA *fluid); @@ -113,7 +113,7 @@ float *manta_get_phi(struct MANTA *fluid); float *manta_get_pressure(struct MANTA *fluid); /* Smoke functions */ -void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); +bool manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); void manta_smoke_get_rgba(struct MANTA *smoke, float *data, int sequential); void manta_noise_get_rgba(struct MANTA *smoke, float *data, int sequential); void manta_smoke_get_rgba_fixed_color(struct MANTA *smoke, @@ -124,9 +124,9 @@ void manta_noise_get_rgba_fixed_color(struct MANTA *smoke, float color[3], float *data, int sequential); -int manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd); -int manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd); -int manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd); +bool manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd); +bool manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd); +bool manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd); /* Smoke accessors */ float *manta_smoke_get_density(struct MANTA *smoke); @@ -147,9 +147,9 @@ float *manta_smoke_get_color_b_in(struct MANTA *smoke); float *manta_smoke_get_fuel_in(struct MANTA *smoke); float *manta_smoke_get_react_in(struct MANTA *smoke); float *manta_smoke_get_emission_in(struct MANTA *smoke); -int manta_smoke_has_heat(struct MANTA *smoke); -int manta_smoke_has_fuel(struct MANTA *smoke); -int manta_smoke_has_colors(struct MANTA *smoke); +bool manta_smoke_has_heat(struct MANTA *smoke); +bool manta_smoke_has_fuel(struct MANTA *smoke); +bool manta_smoke_has_colors(struct MANTA *smoke); float *manta_noise_get_density(struct MANTA *smoke); float *manta_noise_get_fuel(struct MANTA *smoke); float *manta_noise_get_react(struct MANTA *smoke); @@ -163,14 +163,14 @@ float *manta_noise_get_texture_u2(struct MANTA *smoke); float *manta_noise_get_texture_v2(struct MANTA *smoke); float *manta_noise_get_texture_w2(struct MANTA *smoke); float *manta_noise_get_flame(struct MANTA *smoke); -int manta_noise_has_fuel(struct MANTA *smoke); -int manta_noise_has_colors(struct MANTA *smoke); +bool manta_noise_has_fuel(struct MANTA *smoke); +bool manta_noise_has_colors(struct MANTA *smoke); void manta_noise_get_res(struct MANTA *smoke, int *res); int manta_noise_get_cells(struct MANTA *smoke); /* Liquid functions */ -void manta_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); -int manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd); +bool manta_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); +bool manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd); /* Liquid accessors */ int manta_liquid_get_particle_res_x(struct MANTA *liquid); @@ -212,9 +212,6 @@ float manta_liquid_get_snd_particle_position_z_at(struct MANTA *liquid, int i); float manta_liquid_get_snd_particle_velocity_x_at(struct MANTA *liquid, int i); float manta_liquid_get_snd_particle_velocity_y_at(struct MANTA *liquid, int i); float manta_liquid_get_snd_particle_velocity_z_at(struct MANTA *liquid, int i); -bool manta_liquid_flip_from_file(struct MANTA *liquid); -bool manta_liquid_mesh_from_file(struct MANTA *liquid); -bool manta_liquid_particle_from_file(struct MANTA *liquid); #ifdef __cplusplus } diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index dec05831e61..fef6399ab23 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -458,8 +458,7 @@ bool MANTA::initObstacle(FluidModifierData *fmd) string finalString = parseScript(tmpString, fmd); pythonCommands.push_back(finalString); - mUsingObstacle = true; - return runPythonString(pythonCommands); + return (mUsingObstacle = runPythonString(pythonCommands)); } return false; } @@ -473,8 +472,7 @@ bool MANTA::initGuiding(FluidModifierData *fmd) string finalString = parseScript(tmpString, fmd); pythonCommands.push_back(finalString); - mUsingGuiding = true; - return runPythonString(pythonCommands); + return (mUsingGuiding = runPythonString(pythonCommands)); } return false; } @@ -486,8 +484,7 @@ bool MANTA::initFractions(FluidModifierData *fmd) string finalString = parseScript(tmpString, fmd); pythonCommands.push_back(finalString); - mUsingFractions = true; - return runPythonString(pythonCommands); + return (mUsingFractions = runPythonString(pythonCommands)); } bool MANTA::initInVelocity(FluidModifierData *fmd) @@ -498,8 +495,7 @@ bool MANTA::initInVelocity(FluidModifierData *fmd) string finalString = parseScript(tmpString, fmd); pythonCommands.push_back(finalString); - mUsingInvel = true; - return runPythonString(pythonCommands); + return (mUsingInvel = runPythonString(pythonCommands)); } return false; } @@ -512,8 +508,7 @@ bool MANTA::initOutflow(FluidModifierData *fmd) string finalString = parseScript(tmpString, fmd); pythonCommands.push_back(finalString); - mUsingOutflow = true; - return runPythonString(pythonCommands); + return (mUsingOutflow = runPythonString(pythonCommands)); } return false; } @@ -565,7 +560,7 @@ MANTA::~MANTA() pythonCommands.push_back(finalString); result = runPythonString(pythonCommands); - assert(result); + BLI_assert(result); UNUSED_VARS(result); } @@ -610,7 +605,7 @@ bool MANTA::runPythonString(vector<string> commands) } PyGILState_Release(gilstate); - assert(success); + BLI_assert(success); return success; } @@ -697,12 +692,6 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd) if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) borderCollisions += "Z"; - string simulationMethod = ""; - if (fds->simulation_method & FLUID_DOMAIN_METHOD_FLIP) - simulationMethod += "'FLIP'"; - else if (fds->simulation_method & FLUID_DOMAIN_METHOD_APIC) - simulationMethod += "'APIC'"; - string particleTypesStr = ""; if (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) particleTypesStr += "PtypeSpray"; @@ -837,7 +826,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd) mRNAMap["CACHE_MESH_FORMAT"] = getCacheFileEnding(fds->cache_mesh_format); mRNAMap["CACHE_NOISE_FORMAT"] = getCacheFileEnding(fds->cache_noise_format); mRNAMap["CACHE_PARTICLE_FORMAT"] = getCacheFileEnding(fds->cache_particle_format); - mRNAMap["SIMULATION_METHOD"] = simulationMethod; + mRNAMap["USING_APIC"] = getBooleanString(fds->simulation_method == FLUID_DOMAIN_METHOD_APIC); mRNAMap["FLIP_RATIO"] = to_string(fds->flip_ratio); mRNAMap["PARTICLE_RANDOMNESS"] = to_string(fds->particle_randomness); mRNAMap["PARTICLE_NUMBER"] = to_string(fds->particle_number); @@ -1596,7 +1585,7 @@ bool MANTA::updateVariables(FluidModifierData *fmd) return runPythonString(pythonCommands); } -void MANTA::exportSmokeScript(FluidModifierData *fmd) +bool MANTA::exportSmokeScript(FluidModifierData *fmd) { if (with_debug) cout << "MANTA::exportSmokeScript()" << endl; @@ -1702,9 +1691,14 @@ void MANTA::exportSmokeScript(FluidModifierData *fmd) myfile.open(cacheDirScript); myfile << final_script; myfile.close(); + if (!myfile) { + cerr << "Fluid Error -- Could not export standalone Mantaflow smoke domain script"; + return false; + } + return true; } -void MANTA::exportLiquidScript(FluidModifierData *fmd) +bool MANTA::exportLiquidScript(FluidModifierData *fmd) { if (with_debug) cout << "MANTA::exportLiquidScript()" << endl; @@ -1810,6 +1804,11 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd) myfile.open(cacheDirScript); myfile << final_script; myfile.close(); + if (!myfile) { + cerr << "Fluid Error -- Could not export standalone Mantaflow liquid domain script"; + return false; + } + return true; } /* Call Mantaflow Python functions through this function. Use isAttribute for object attributes, diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index 6425614cf4b..163b168e43d 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -104,8 +104,8 @@ struct MANTA { bool bakeGuiding(FluidModifierData *fmd, int framenr); /* IO for Mantaflow scene script. */ - void exportSmokeScript(struct FluidModifierData *fmd); - void exportLiquidScript(struct FluidModifierData *fmd); + bool exportSmokeScript(struct FluidModifierData *fmd); + bool exportLiquidScript(struct FluidModifierData *fmd); /* Check cache status by frame. */ bool hasConfig(FluidModifierData *fmd, int framenr); diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp index e4754131f34..c04180c8c46 100644 --- a/intern/mantaflow/intern/manta_fluid_API.cpp +++ b/intern/mantaflow/intern/manta_fluid_API.cpp @@ -37,203 +37,145 @@ void manta_free(MANTA *fluid) fluid = nullptr; } -int manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd) +bool manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd) { - if (!fluid || !fmd) - return 0; return fluid->initObstacle(fmd); } -int manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd) +bool manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd) { - if (!fluid || !fmd) - return 0; return fluid->initGuiding(fmd); } -int manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd) +bool manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd) { - if (!fluid || !fmd) - return 0; return fluid->initInVelocity(fmd); } -int manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd) +bool manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd) { - if (!fluid || !fmd) - return 0; return fluid->initOutflow(fmd); } -int manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->writeConfiguration(fmd, framenr); } -int manta_write_data(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_write_data(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->writeData(fmd, framenr); } -int manta_write_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_write_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->writeNoise(fmd, framenr); } -int manta_read_config(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_read_config(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->readConfiguration(fmd, framenr); } -int manta_read_data(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) +bool manta_read_data(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) { - if (!fluid || !fmd) - return 0; return fluid->readData(fmd, framenr, resumable); } -int manta_read_noise(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) +bool manta_read_noise(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) { - if (!fluid || !fmd) - return 0; return fluid->readNoise(fmd, framenr, resumable); } -int manta_read_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_read_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->readMesh(fmd, framenr); } -int manta_read_particles(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) +bool manta_read_particles(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable) { - if (!fluid || !fmd) - return 0; return fluid->readParticles(fmd, framenr, resumable); } -int manta_read_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool sourceDomain) +bool manta_read_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool sourceDomain) { - if (!fluid || !fmd) - return 0; return fluid->readGuiding(fmd, framenr, sourceDomain); } -int manta_bake_data(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_bake_data(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->bakeData(fmd, framenr); } -int manta_bake_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_bake_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->bakeNoise(fmd, framenr); } -int manta_bake_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_bake_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->bakeMesh(fmd, framenr); } -int manta_bake_particles(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_bake_particles(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->bakeParticles(fmd, framenr); } -int manta_bake_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_bake_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->bakeGuiding(fmd, framenr); } -int manta_has_data(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_has_data(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->hasData(fmd, framenr); } -int manta_has_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_has_noise(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->hasNoise(fmd, framenr); } -int manta_has_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_has_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->hasMesh(fmd, framenr); } -int manta_has_particles(MANTA *fluid, FluidModifierData *fmd, int framenr) +bool manta_has_particles(MANTA *fluid, FluidModifierData *fmd, int framenr) { - if (!fluid || !fmd) - return 0; return fluid->hasParticles(fmd, framenr); } -int manta_has_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool domain) +bool manta_has_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool domain) { - if (!fluid || !fmd) - return 0; return fluid->hasGuiding(fmd, framenr, domain); } void manta_update_variables(MANTA *fluid, FluidModifierData *fmd) { - if (!fluid) - return; fluid->updateVariables(fmd); } int manta_get_frame(MANTA *fluid) { - if (!fluid) - return 0; return fluid->getFrame(); } float manta_get_timestep(MANTA *fluid) { - if (!fluid) - return 0; return fluid->getTimestep(); } void manta_adapt_timestep(MANTA *fluid) { - if (!fluid) - return; fluid->adaptTimestep(); } bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd) { - if (!fluid || !fmd) - return false; return fluid->needsRealloc(fmd); } void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush) { - if (!fluid || !fmd) - return; fluid->updatePointers(fmd, flush); } @@ -372,11 +314,9 @@ float *manta_get_pressure(MANTA *fluid) } /* Smoke functions */ -void manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd) +bool manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd) { - if (!smoke || !fmd) - return; - smoke->exportSmokeScript(fmd); + return smoke->exportSmokeScript(fmd); } static void get_rgba( @@ -452,18 +392,13 @@ void manta_noise_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, get_rgba_fixed_color(color, smoke->getTotalCellsHigh(), data, sequential); } -int manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd) +bool manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd) { - if (!smoke || !fmd) - return 0; return smoke->initHeat(fmd); } -int manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd) +bool manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd) { - if (!smoke || !fmd) - return 0; - bool result = smoke->initFire(fmd); if (smoke->usingNoise()) { result &= smoke->initFireHigh(fmd); @@ -471,11 +406,8 @@ int manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd) return result; } -int manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd) +bool manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd) { - if (!smoke || !fmd) - return 0; - bool result = smoke->initColors(fmd); if (smoke->usingNoise()) { result &= smoke->initColorsHigh(fmd); @@ -560,107 +492,104 @@ float *manta_smoke_get_emission_in(MANTA *smoke) return smoke->getEmissionIn(); } -int manta_smoke_has_heat(MANTA *smoke) +bool manta_smoke_has_heat(MANTA *smoke) { - return (smoke->getHeat()) ? 1 : 0; + return smoke->getHeat() != nullptr; + ; } -int manta_smoke_has_fuel(MANTA *smoke) +bool manta_smoke_has_fuel(MANTA *smoke) { - return (smoke->getFuel()) ? 1 : 0; + return smoke->getFuel() != nullptr; } -int manta_smoke_has_colors(MANTA *smoke) +bool manta_smoke_has_colors(MANTA *smoke) { - return (smoke->getColorR() && smoke->getColorG() && smoke->getColorB()) ? 1 : 0; + return smoke->getColorR() != nullptr && smoke->getColorG() != nullptr && + smoke->getColorB() != nullptr; } float *manta_noise_get_density(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getDensityHigh() : nullptr; + return smoke->getDensityHigh(); } float *manta_noise_get_fuel(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getFuelHigh() : nullptr; + return smoke->getFuelHigh(); } float *manta_noise_get_react(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getReactHigh() : nullptr; + return smoke->getReactHigh(); } float *manta_noise_get_color_r(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getColorRHigh() : nullptr; + return smoke->getColorRHigh(); } float *manta_noise_get_color_g(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getColorGHigh() : nullptr; + return smoke->getColorGHigh(); } float *manta_noise_get_color_b(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getColorBHigh() : nullptr; + return smoke->getColorBHigh(); } float *manta_noise_get_flame(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getFlameHigh() : nullptr; + return smoke->getFlameHigh(); } float *manta_noise_get_texture_u(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureU() : nullptr; + return smoke->getTextureU(); } float *manta_noise_get_texture_v(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureV() : nullptr; + return smoke->getTextureV(); } float *manta_noise_get_texture_w(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureW() : nullptr; + return smoke->getTextureW(); } float *manta_noise_get_texture_u2(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureU2() : nullptr; + return smoke->getTextureU2(); } float *manta_noise_get_texture_v2(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureV2() : nullptr; + return smoke->getTextureV2(); } float *manta_noise_get_texture_w2(MANTA *smoke) { - return (smoke && smoke->usingNoise()) ? smoke->getTextureW2() : nullptr; + return smoke->getTextureW2(); } -int manta_noise_has_fuel(MANTA *smoke) +bool manta_noise_has_fuel(MANTA *smoke) { - return (smoke->getFuelHigh()) ? 1 : 0; + return smoke->getFuelHigh() != nullptr; } -int manta_noise_has_colors(MANTA *smoke) +bool manta_noise_has_colors(MANTA *smoke) { - return (smoke->getColorRHigh() && smoke->getColorGHigh() && smoke->getColorBHigh()) ? 1 : 0; + return smoke->getColorRHigh() != nullptr && smoke->getColorGHigh() != nullptr && + smoke->getColorBHigh() != nullptr; + ; } void manta_noise_get_res(MANTA *smoke, int *res) { - if (smoke && smoke->usingNoise()) { - res[0] = smoke->getResXHigh(); - res[1] = smoke->getResYHigh(); - res[2] = smoke->getResZHigh(); - } + res[0] = smoke->getResXHigh(); + res[1] = smoke->getResYHigh(); + res[2] = smoke->getResZHigh(); } int manta_noise_get_cells(MANTA *smoke) { - int total_cells_high = smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh(); - return (smoke && smoke->usingNoise()) ? total_cells_high : 0; + return smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh(); } /* Liquid functions */ -void manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd) +bool manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd) { - if (!liquid || !fmd) - return; - liquid->exportLiquidScript(fmd); + return liquid->exportLiquidScript(fmd); } -int manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd) +bool manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd) { - if (!liquid || !fmd) - return 0; return liquid->initLiquidSndParts(fmd); } @@ -834,16 +763,3 @@ float manta_liquid_get_snd_particle_velocity_z_at(MANTA *liquid, int i) { return liquid->getSndParticleVelocityZAt(i); } - -bool manta_liquid_flip_from_file(MANTA *liquid) -{ - return liquid->usingFlipFromFile(); -} -bool manta_liquid_mesh_from_file(MANTA *liquid) -{ - return liquid->usingMeshFromFile(); -} -bool manta_liquid_particle_from_file(MANTA *liquid) -{ - return liquid->usingParticleFromFile(); -} diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index c416a84c71c..1f22f4b3d21 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -39,11 +39,7 @@ isWindows = platform.system() != 'Darwin' and platform.system() != 'Linux'\n\ #try:\n\ # multiprocessing.set_start_method('spawn')\n\ #except:\n\ -# pass\n\ -\n\ -bpy = sys.modules.get('bpy')\n\ -if bpy is not None:\n\ - sys.executable = bpy.app.binary_path_python\n"; +# pass\n"; ////////////////////////////////////////////////////////////////////// // DEBUG diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index 7622fc5a602..8e0d113d680 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -50,7 +50,8 @@ smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\ smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\ randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\ surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\ -maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n"; +maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\ +using_apic_s$ID$ = $USING_APIC$\n"; const std::string liquid_variables_particles = "\n\ @@ -91,6 +92,14 @@ curvature_s$ID$ = None\n\ pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\ pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\ \n\ +pCx_pp$ID$ = None\n\ +pCy_pp$ID$ = None\n\ +pCz_pp$ID$ = None\n\ +if using_apic_s$ID$:\n\ + pCx_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\ + pCy_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\ + pCz_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\ +\n\ # Acceleration data for particle nbs\n\ pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\ gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\ @@ -275,8 +284,12 @@ def liquid_step_$ID$():\n\ resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\ flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\ \n\ - # combine particles velocities with advected grid velocities\n\ - mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\ + # combine particle velocities with advected grid velocities\n\ + if using_apic_s$ID$:\n\ + apicMapPartsToMAC(flags=flags_s$ID$, vel=vel_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$)\n\ + else:\n\ + mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\ + \n\ extrapolateMACFromWeight(vel=velParts_s$ID$, distance=2, weight=mapWeights_s$ID$)\n\ combineGridVel(vel=velParts_s$ID$, weight=mapWeights_s$ID$, combineVel=vel_s$ID$, phi=phi_s$ID$, narrowBand=combineBandWidth_s$ID$, thresh=0)\n\ velOld_s$ID$.copyFrom(vel_s$ID$)\n\ @@ -319,7 +332,11 @@ def liquid_step_$ID$():\n\ # set source grids for resampling, used in adjustNumber!\n\ pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\ adjustNumber(parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$, minParticles=minParticles_s$ID$, maxParticles=maxParticles_s$ID$, phi=phi_s$ID$, exclude=phiObs_s$ID$, radiusFactor=radiusFactor_s$ID$, narrowBand=adjustedNarrowBandWidth_s$ID$)\n\ - flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n"; + \n\ + if using_apic_s$ID$:\n\ + apicMapMACGridToParts(partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$, parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$)\n\ + else:\n\ + flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n"; const std::string liquid_step_mesh = "\n\ diff --git a/intern/sky/source/sky_model.cpp b/intern/sky/source/sky_model.cpp index e835e04d164..165444003d3 100644 --- a/intern/sky/source/sky_model.cpp +++ b/intern/sky/source/sky_model.cpp @@ -272,9 +272,8 @@ static double ArHosekSkyModel_CookRadianceConfiguration(ArHosekSkyModel_Radiance return res; } -static double ArHosekSkyModel_GetRadianceInternal(SKY_ArHosekSkyModelConfiguration configuration, - double theta, - double gamma) +static double ArHosekSkyModel_GetRadianceInternal( + const SKY_ArHosekSkyModelConfiguration configuration, const double theta, const double gamma) { const double expM = exp(configuration[4] * gamma); const double rayM = cos(gamma) * cos(gamma); diff --git a/intern/sky/source/sky_nishita.cpp b/intern/sky/source/sky_nishita.cpp index f36bfcc3d7b..e3b6ca021fe 100644 --- a/intern/sky/source/sky_nishita.cpp +++ b/intern/sky/source/sky_nishita.cpp @@ -87,7 +87,7 @@ static float3 geographical_to_direction(float lat, float lon) return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat)); } -static float3 spec_to_xyz(float *spectrum) +static float3 spec_to_xyz(const float *spectrum) { float3 xyz = make_float3(0.0f, 0.0f, 0.0f); for (int i = 0; i < num_wavelengths; i++) { @@ -112,10 +112,12 @@ static float density_mie(float height) static float density_ozone(float height) { float den = 0.0f; - if (height >= 10000.0f && height < 25000.0f) + if (height >= 10000.0f && height < 25000.0f) { den = 1.0f / 15000.0f * height - 2.0f / 3.0f; - else if (height >= 25000 && height < 40000) + } + else if (height >= 25000 && height < 40000) { den = -(1.0f / 15000.0f * height - 8.0f / 3.0f); + } return den; } @@ -133,15 +135,16 @@ static float phase_mie(float mu) /* Intersection helpers */ static bool surface_intersection(float3 pos, float3 dir) { - if (dir.z >= 0) + if (dir.z >= 0) { return false; + } float b = -2.0f * dot(dir, -pos); float c = len_squared(pos) - sqr(earth_radius); float t = b * b - 4.0f * c; - if (t >= 0.0f) + if (t >= 0.0f) { return true; - else - return false; + } + return false; } static float3 atmosphere_intersection(float3 pos, float3 dir) |