Cleanup: use braces for sources in intern/

Omitted intern/itasc as some of these sources are from KDL:
https://www.orocos.org/kdl.html
This commit is contained in:
Campbell Barton 2023-09-17 09:01:48 +10:00
parent e3444fd314
commit 5b9740c913
94 changed files with 2091 additions and 1046 deletions

@ -22,15 +22,17 @@ void AUD_destroySet(void *set)
char AUD_removeSet(void *set, void *entry) char AUD_removeSet(void *set, void *entry)
{ {
if (set) if (set) {
return reinterpret_cast<std::set<void *> *>(set)->erase(entry); return reinterpret_cast<std::set<void *> *>(set)->erase(entry);
}
return 0; return 0;
} }
void AUD_addSet(void *set, void *entry) void AUD_addSet(void *set, void *entry)
{ {
if (entry) if (entry) {
reinterpret_cast<std::set<void *> *>(set)->insert(entry); reinterpret_cast<std::set<void *> *>(set)->insert(entry);
}
} }
void *AUD_getSet(void *set) void *AUD_getSet(void *set)

@ -61,8 +61,9 @@ static void session_print(const string &str)
int len = str.size(); int len = str.size();
maxlen = max(len, maxlen); maxlen = max(len, maxlen);
for (int i = len; i < maxlen; i++) for (int i = len; i < maxlen; i++) {
printf(" "); printf(" ");
}
/* flush because we don't write an end of line */ /* flush because we don't write an end of line */
fflush(stdout); fflush(stdout);
@ -76,8 +77,9 @@ static void session_print_status()
double progress = options.session->progress.get_progress(); double progress = options.session->progress.get_progress();
options.session->progress.get_status(status, substatus); options.session->progress.get_status(status, substatus);
if (substatus != "") if (substatus != "") {
status += ": " + substatus; status += ": " + substatus;
}
/* print status */ /* print status */
status = string_printf("Progress %05.2f %s", (double)progress * 100, status.c_str()); status = string_printf("Progress %05.2f %s", (double)progress * 100, status.c_str());
@ -141,8 +143,9 @@ static void session_init()
options.output_filepath, options.output_pass, session_print)); options.output_filepath, options.output_pass, session_print));
} }
if (options.session_params.background && !options.quiet) if (options.session_params.background && !options.quiet) {
options.session->progress.set_update_callback(function_bind(&session_print_status)); options.session->progress.set_update_callback(function_bind(&session_print_status));
}
#ifdef WITH_CYCLES_STANDALONE_GUI #ifdef WITH_CYCLES_STANDALONE_GUI
else else
options.session->progress.set_update_callback(function_bind(&window_redraw)); options.session->progress.set_update_callback(function_bind(&window_redraw));
@ -347,8 +350,9 @@ static void keyboard(unsigned char key)
static int files_parse(int argc, const char *argv[]) static int files_parse(int argc, const char *argv[])
{ {
if (argc > 0) if (argc > 0) {
options.filepath = argv[0]; options.filepath = argv[0];
}
return 0; return 0;
} }
@ -371,8 +375,9 @@ static void options_parse(int argc, const char **argv)
/* List devices for which support is compiled in. */ /* List devices for which support is compiled in. */
vector<DeviceType> types = Device::available_types(); vector<DeviceType> types = Device::available_types();
foreach (DeviceType type, types) { foreach (DeviceType type, types) {
if (device_names != "") if (device_names != "") {
device_names += ", "; device_names += ", ";
}
device_names += Device::string_from_type(type); device_names += Device::string_from_type(type);
} }
@ -478,10 +483,12 @@ static void options_parse(int argc, const char **argv)
options.session_params.use_profiling = profile; options.session_params.use_profiling = profile;
if (ssname == "osl") if (ssname == "osl") {
options.scene_params.shadingsystem = SHADINGSYSTEM_OSL; options.scene_params.shadingsystem = SHADINGSYSTEM_OSL;
else if (ssname == "svm") }
else if (ssname == "svm") {
options.scene_params.shadingsystem = SHADINGSYSTEM_SVM; options.scene_params.shadingsystem = SHADINGSYSTEM_SVM;
}
#ifndef WITH_CYCLES_STANDALONE_GUI #ifndef WITH_CYCLES_STANDALONE_GUI
options.session_params.background = true; options.session_params.background = true;

@ -130,8 +130,9 @@ static bool xml_read_float3_array(vector<float3> &value, xml_node node, const ch
vector<float> array; vector<float> array;
if (xml_read_float_array(array, node, name)) { if (xml_read_float_array(array, node, name)) {
for (size_t i = 0; i < array.size(); i += 3) for (size_t i = 0; i < array.size(); i += 3) {
value.push_back(make_float3(array[i + 0], array[i + 1], array[i + 2])); value.push_back(make_float3(array[i + 0], array[i + 1], array[i + 2]));
}
return true; return true;
} }
@ -167,8 +168,9 @@ static bool xml_equal_string(xml_node node, const char *name, const char *value)
{ {
xml_attribute attr = node.attribute(name); xml_attribute attr = node.attribute(name);
if (attr) if (attr) {
return string_iequals(attr.value(), value); return string_iequals(attr.value(), value);
}
return false; return false;
} }
@ -255,40 +257,48 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node
ShaderNode *fromnode = (ShaderNode *)graph_reader.node_map[from_node_name]; ShaderNode *fromnode = (ShaderNode *)graph_reader.node_map[from_node_name];
foreach (ShaderOutput *out, fromnode->outputs) foreach (ShaderOutput *out, fromnode->outputs)
if (string_iequals(out->socket_type.name.string(), from_socket_name.string())) if (string_iequals(out->socket_type.name.string(), from_socket_name.string())) {
output = out; output = out;
}
if (!output) if (!output) {
fprintf(stderr, fprintf(stderr,
"Unknown output socket name \"%s\" on \"%s\".\n", "Unknown output socket name \"%s\" on \"%s\".\n",
from_node_name.c_str(), from_node_name.c_str(),
from_socket_name.c_str()); from_socket_name.c_str());
} }
else }
else {
fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str()); fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str());
}
if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) { if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) {
ShaderNode *tonode = (ShaderNode *)graph_reader.node_map[to_node_name]; ShaderNode *tonode = (ShaderNode *)graph_reader.node_map[to_node_name];
foreach (ShaderInput *in, tonode->inputs) foreach (ShaderInput *in, tonode->inputs)
if (string_iequals(in->socket_type.name.string(), to_socket_name.string())) if (string_iequals(in->socket_type.name.string(), to_socket_name.string())) {
input = in; input = in;
}
if (!input) if (!input) {
fprintf(stderr, fprintf(stderr,
"Unknown input socket name \"%s\" on \"%s\".\n", "Unknown input socket name \"%s\" on \"%s\".\n",
to_socket_name.c_str(), to_socket_name.c_str(),
to_node_name.c_str()); to_node_name.c_str());
} }
else }
else {
fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str()); fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str());
}
/* connect */ /* connect */
if (output && input) if (output && input) {
graph->connect(output, input); graph->connect(output, input);
} }
else }
else {
fprintf(stderr, "Invalid from or to value for connect node.\n"); fprintf(stderr, "Invalid from or to value for connect node.\n");
}
continue; continue;
} }
@ -328,8 +338,9 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node
#endif #endif
{ {
/* exception for name collision */ /* exception for name collision */
if (node_name == "background") if (node_name == "background") {
node_name = "background_shader"; node_name = "background_shader";
}
const NodeType *node_type = NodeType::find(node_name); const NodeType *node_type = NodeType::find(node_name);
@ -446,8 +457,9 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
mesh->set_verts(P_array); mesh->set_verts(P_array);
size_t num_triangles = 0; size_t num_triangles = 0;
for (size_t i = 0; i < nverts.size(); i++) for (size_t i = 0; i < nverts.size(); i++) {
num_triangles += nverts[i] - 2; num_triangles += nverts[i] - 2;
}
mesh->reserve_mesh(mesh->get_verts().size(), num_triangles); mesh->reserve_mesh(mesh->get_verts().size(), num_triangles);
/* create triangles */ /* create triangles */
@ -615,17 +627,20 @@ static void xml_read_state(XMLReadState &state, xml_node node)
} }
} }
if (!found) if (!found) {
fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str()); fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str());
} }
}
xml_read_float(&state.dicing_rate, node, "dicing_rate"); xml_read_float(&state.dicing_rate, node, "dicing_rate");
/* read smooth/flat */ /* read smooth/flat */
if (xml_equal_string(node, "interpolation", "smooth")) if (xml_equal_string(node, "interpolation", "smooth")) {
state.smooth = true; state.smooth = true;
else if (xml_equal_string(node, "interpolation", "flat")) }
else if (xml_equal_string(node, "interpolation", "flat")) {
state.smooth = false; state.smooth = false;
}
} }
/* Scene */ /* Scene */
@ -671,17 +686,19 @@ static void xml_read_scene(XMLReadState &state, xml_node scene_node)
else if (string_iequals(node.name(), "include")) { else if (string_iequals(node.name(), "include")) {
string src; string src;
if (xml_read_string(&src, node, "src")) if (xml_read_string(&src, node, "src")) {
xml_read_include(state, src); xml_read_include(state, src);
} }
}
#ifdef WITH_ALEMBIC #ifdef WITH_ALEMBIC
else if (string_iequals(node.name(), "alembic")) { else if (string_iequals(node.name(), "alembic")) {
xml_read_alembic(state, node); xml_read_alembic(state, node);
} }
#endif #endif
else else {
fprintf(stderr, "Unknown node \"%s\".\n", node.name()); fprintf(stderr, "Unknown node \"%s\".\n", node.name());
} }
}
} }
/* Include */ /* Include */

@ -174,8 +174,9 @@ static void window_display()
glRasterPos3f(0, 0, 0); glRasterPos3f(0, 0, 0);
if (V.display) if (V.display) {
V.display(); V.display();
}
SDL_GL_SwapWindow(V.window); SDL_GL_SwapWindow(V.window);
window_opengl_context_disable(); window_opengl_context_disable();
@ -195,12 +196,14 @@ static void window_reshape(int width, int height)
static bool window_keyboard(unsigned char key) static bool window_keyboard(unsigned char key)
{ {
if (V.keyboard) if (V.keyboard) {
V.keyboard(key); V.keyboard(key);
}
if (key == 'q') { if (key == 'q') {
if (V.exitf) if (V.exitf) {
V.exitf(); V.exitf();
}
return true; return true;
} }
@ -237,8 +240,9 @@ static void window_motion(int x, int y)
const int distX = x - V.mouseX; const int distX = x - V.mouseX;
const int distY = y - V.mouseY; const int distY = y - V.mouseY;
if (V.motion) if (V.motion) {
V.motion(distX, distY, but); V.motion(distX, distY, but);
}
V.mouseX = x; V.mouseX = x;
V.mouseY = y; V.mouseY = y;

@ -142,8 +142,9 @@ static float blender_camera_focal_distance(BL::RenderEngine &b_engine,
{ {
BL::Object b_dof_object = b_camera.dof().focus_object(); BL::Object b_dof_object = b_camera.dof().focus_object();
if (!b_dof_object) if (!b_dof_object) {
return b_camera.dof().focus_distance(); return b_camera.dof().focus_distance();
}
Transform dofmat = get_transform(b_dof_object.matrix_world()); Transform dofmat = get_transform(b_dof_object.matrix_world());
@ -202,10 +203,12 @@ static void blender_camera_from_object(BlenderCamera *bcam,
bcam->type = CAMERA_ORTHOGRAPHIC; bcam->type = CAMERA_ORTHOGRAPHIC;
break; break;
case BL::Camera::type_PANO: case BL::Camera::type_PANO:
if (!skip_panorama) if (!skip_panorama) {
bcam->type = CAMERA_PANORAMA; bcam->type = CAMERA_PANORAMA;
else }
else {
bcam->type = CAMERA_PERSPECTIVE; bcam->type = CAMERA_PERSPECTIVE;
}
break; break;
case BL::Camera::type_PERSP: case BL::Camera::type_PERSP:
default: default:
@ -252,10 +255,12 @@ static void blender_camera_from_object(BlenderCamera *bcam,
float fstop = b_camera.dof().aperture_fstop(); float fstop = b_camera.dof().aperture_fstop();
fstop = max(fstop, 1e-5f); fstop = max(fstop, 1e-5f);
if (bcam->type == CAMERA_ORTHOGRAPHIC) if (bcam->type == CAMERA_ORTHOGRAPHIC) {
bcam->aperturesize = 1.0f / (2.0f * fstop); bcam->aperturesize = 1.0f / (2.0f * fstop);
else }
else {
bcam->aperturesize = (bcam->lens * 1e-3f) / (2.0f * fstop); bcam->aperturesize = (bcam->lens * 1e-3f) / (2.0f * fstop);
}
bcam->apertureblades = b_camera.dof().aperture_blades(); bcam->apertureblades = b_camera.dof().aperture_blades();
bcam->aperturerotation = b_camera.dof().aperture_rotation(); bcam->aperturerotation = b_camera.dof().aperture_rotation();
@ -277,13 +282,16 @@ static void blender_camera_from_object(BlenderCamera *bcam,
bcam->sensor_width = b_camera.sensor_width(); bcam->sensor_width = b_camera.sensor_width();
bcam->sensor_height = b_camera.sensor_height(); bcam->sensor_height = b_camera.sensor_height();
if (b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO) if (b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO) {
bcam->sensor_fit = BlenderCamera::AUTO; bcam->sensor_fit = BlenderCamera::AUTO;
else if (b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL) }
else if (b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL) {
bcam->sensor_fit = BlenderCamera::HORIZONTAL; bcam->sensor_fit = BlenderCamera::HORIZONTAL;
else }
else {
bcam->sensor_fit = BlenderCamera::VERTICAL; bcam->sensor_fit = BlenderCamera::VERTICAL;
} }
}
else if (b_ob_data.is_a(&RNA_Light)) { else if (b_ob_data.is_a(&RNA_Light)) {
/* Can also look through spot light. */ /* Can also look through spot light. */
BL::SpotLight b_light(b_ob_data); BL::SpotLight b_light(b_ob_data);
@ -509,13 +517,16 @@ static void blender_camera_sync(Camera *cam,
cam->set_use_spherical_stereo(bcam->use_spherical_stereo); cam->set_use_spherical_stereo(bcam->use_spherical_stereo);
if (cam->get_use_spherical_stereo()) { if (cam->get_use_spherical_stereo()) {
if (strcmp(viewname, "left") == 0) if (strcmp(viewname, "left") == 0) {
cam->set_stereo_eye(Camera::STEREO_LEFT); cam->set_stereo_eye(Camera::STEREO_LEFT);
else if (strcmp(viewname, "right") == 0) }
else if (strcmp(viewname, "right") == 0) {
cam->set_stereo_eye(Camera::STEREO_RIGHT); cam->set_stereo_eye(Camera::STEREO_RIGHT);
else }
else {
cam->set_stereo_eye(Camera::STEREO_NONE); cam->set_stereo_eye(Camera::STEREO_NONE);
} }
}
cam->set_use_pole_merge(bcam->use_pole_merge); 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_from(bcam->pole_merge_angle_from);
@ -604,8 +615,9 @@ void BlenderSync::sync_camera(BL::RenderSettings &b_render,
/* camera object */ /* camera object */
BL::Object b_ob = b_scene.camera(); BL::Object b_ob = b_scene.camera();
if (b_override) if (b_override) {
b_ob = b_override; b_ob = b_override;
}
if (b_ob) { if (b_ob) {
BL::Array<float, 16> b_ob_matrix; BL::Array<float, 16> b_ob_matrix;
@ -641,8 +653,9 @@ void BlenderSync::sync_camera(BL::RenderSettings &b_render,
void BlenderSync::sync_camera_motion( void BlenderSync::sync_camera_motion(
BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time) BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time)
{ {
if (!b_ob) if (!b_ob) {
return; return;
}
Camera *cam = scene->camera; Camera *cam = scene->camera;
BL::Array<float, 16> b_ob_matrix; BL::Array<float, 16> b_ob_matrix;
@ -771,10 +784,12 @@ static void blender_camera_from_view(BlenderCamera *bcam,
bcam->nearclip = -bcam->farclip; bcam->nearclip = -bcam->farclip;
float sensor_size; float sensor_size;
if (bcam->sensor_fit == BlenderCamera::VERTICAL) if (bcam->sensor_fit == BlenderCamera::VERTICAL) {
sensor_size = bcam->sensor_height; sensor_size = bcam->sensor_height;
else }
else {
sensor_size = bcam->sensor_width; sensor_size = bcam->sensor_width;
}
bcam->type = CAMERA_ORTHOGRAPHIC; bcam->type = CAMERA_ORTHOGRAPHIC;
bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens(); bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens();
@ -890,8 +905,9 @@ static void blender_camera_border(BlenderCamera *bcam,
BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera(); BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera();
if (!b_ob) if (!b_ob) {
return; return;
}
/* Determine camera border inside the viewport. */ /* Determine camera border inside the viewport. */
BoundBox2D full_border; BoundBox2D full_border;
@ -970,11 +986,13 @@ BufferParams BlenderSync::get_buffer_params(
params.full_width = width; params.full_width = width;
params.full_height = height; params.full_height = height;
if (b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA) if (b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA) {
use_border = b_v3d.use_render_border(); use_border = b_v3d.use_render_border();
else }
else {
/* the camera can always have a passepartout */ /* the camera can always have a passepartout */
use_border = true; use_border = true;
}
if (use_border) { if (use_border) {
/* border render */ /* border render */

@ -33,11 +33,13 @@ static float shaperadius(float shape, float root, float tip, float time)
float radius = 1.0f - time; float radius = 1.0f - time;
if (shape != 0.0f) { if (shape != 0.0f) {
if (shape < 0.0f) if (shape < 0.0f) {
radius = powf(radius, 1.0f + shape); radius = powf(radius, 1.0f + shape);
else }
else {
radius = powf(radius, 1.0f / (1.0f - shape)); radius = powf(radius, 1.0f / (1.0f - shape));
} }
}
return (radius * (root - tip)) + tip; return (radius * (root - tip)) + tip;
} }
@ -49,8 +51,9 @@ static bool ObtainCacheParticleData(
int curvenum = 0; int curvenum = 0;
int keyno = 0; int keyno = 0;
if (!(hair && b_mesh && b_ob && CData)) if (!(hair && b_mesh && b_ob && CData)) {
return false; return false;
}
Transform tfm = get_transform(b_ob->matrix_world()); Transform tfm = get_transform(b_ob->matrix_world());
Transform itfm = transform_inverse(tfm); Transform itfm = transform_inverse(tfm);
@ -147,8 +150,9 @@ static bool ObtainCacheParticleUV(Hair *hair,
bool background, bool background,
int uv_num) int uv_num)
{ {
if (!(hair && b_mesh && b_ob && CData)) if (!(hair && b_mesh && b_ob && CData)) {
return false; return false;
}
CData->curve_uv.clear(); CData->curve_uv.clear();
@ -211,8 +215,9 @@ static bool ObtainCacheParticleVcol(Hair *hair,
bool background, bool background,
int vcol_num) int vcol_num)
{ {
if (!(hair && b_mesh && b_ob && CData)) if (!(hair && b_mesh && b_ob && CData)) {
return false; return false;
}
CData->curve_vcol.clear(); CData->curve_vcol.clear();
@ -273,22 +278,27 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
int num_keys = 0; int num_keys = 0;
int num_curves = 0; int num_curves = 0;
if (hair->num_curves()) if (hair->num_curves()) {
return; return;
}
Attribute *attr_normal = NULL; Attribute *attr_normal = NULL;
Attribute *attr_intercept = NULL; Attribute *attr_intercept = NULL;
Attribute *attr_length = NULL; Attribute *attr_length = NULL;
Attribute *attr_random = NULL; Attribute *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_VERTEX_NORMAL)) if (hair->need_attribute(scene, ATTR_STD_VERTEX_NORMAL)) {
attr_normal = hair->attributes.add(ATTR_STD_VERTEX_NORMAL); attr_normal = hair->attributes.add(ATTR_STD_VERTEX_NORMAL);
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) }
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT); attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH)) }
if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH)) {
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH); attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH);
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) }
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM); attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM);
}
/* compute and reserve size of arrays */ /* compute and reserve size of arrays */
for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
@ -330,8 +340,9 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
radius = 0.0f; radius = 0.0f;
} }
hair->add_curve_key(ickey_loc, radius); hair->add_curve_key(ickey_loc, radius);
if (attr_intercept) if (attr_intercept) {
attr_intercept->add(time); attr_intercept->add(time);
}
if (attr_normal) { if (attr_normal) {
/* NOTE: the geometry normals are not computed for legacy particle hairs. This hair /* NOTE: the geometry normals are not computed for legacy particle hairs. This hair
@ -374,7 +385,9 @@ static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve,
if (CData->psys_closetip[sys] && if (CData->psys_closetip[sys] &&
(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
{
radius = 0.0f; radius = 0.0f;
}
/* curve motion keys store both position and radius in float4 */ /* curve motion keys store both position and radius in float4 */
float4 mP = float3_to_float4(ickey_loc); float4 mP = float3_to_float4(ickey_loc);
@ -476,10 +489,11 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
* space, so we use an epsilon to detect actual changes */ * space, so we use an epsilon to detect actual changes */
float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]); float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]);
curve_key.w = hair->get_curve_radius()[i]; curve_key.w = hair->get_curve_radius()[i];
if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f) if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f) {
have_motion = true; have_motion = true;
} }
} }
}
i++; i++;
} }
} }
@ -550,10 +564,12 @@ void BlenderSync::sync_particle_hair(
ObtainCacheParticleData(hair, &b_mesh, &b_ob, &CData, !preview); ObtainCacheParticleData(hair, &b_mesh, &b_ob, &CData, !preview);
/* add hair geometry */ /* add hair geometry */
if (motion) if (motion) {
ExportCurveSegmentsMotion(hair, &CData, motion_step); ExportCurveSegmentsMotion(hair, &CData, motion_step);
else }
else {
ExportCurveSegments(scene, hair, &CData); ExportCurveSegments(scene, hair, &CData);
}
/* generated coordinates from first key. we should ideally get this from /* generated coordinates from first key. we should ideally get this from
* blender to handle deforming objects */ * blender to handle deforming objects */
@ -578,8 +594,9 @@ void BlenderSync::sync_particle_hair(
int vcol_num = 0; int vcol_num = 0;
for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) { for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
if (!hair->need_attribute(scene, ustring(l->name().c_str()))) if (!hair->need_attribute(scene, ustring(l->name().c_str()))) {
continue; continue;
}
ObtainCacheParticleVcol(hair, &b_mesh, &b_ob, &CData, !preview, vcol_num); ObtainCacheParticleVcol(hair, &b_mesh, &b_ob, &CData, !preview, vcol_num);
@ -615,10 +632,12 @@ void BlenderSync::sync_particle_hair(
ObtainCacheParticleUV(hair, &b_mesh, &b_ob, &CData, !preview, uv_num); ObtainCacheParticleUV(hair, &b_mesh, &b_ob, &CData, !preview, uv_num);
if (active_render) if (active_render) {
attr_uv = hair->attributes.add(std, name); attr_uv = hair->attributes.add(std, name);
else }
else {
attr_uv = hair->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE); attr_uv = hair->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
}
float2 *uv = attr_uv->data_float2(); float2 *uv = attr_uv->data_float2();

@ -25,10 +25,12 @@ int blender_device_threads(BL::Scene &b_scene)
{ {
BL::RenderSettings b_r = b_scene.render(); BL::RenderSettings b_r = b_scene.render();
if (b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED) if (b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED) {
return b_r.threads(); return b_r.threads();
else }
else {
return 0; return 0;
}
} }
void static adjust_device_info_from_preferences(DeviceInfo &info, PointerRNA cpreferences) void static adjust_device_info_from_preferences(DeviceInfo &info, PointerRNA cpreferences)

@ -56,11 +56,13 @@ array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob)
} }
if (used_shaders.size() == 0) { if (used_shaders.size() == 0) {
if (material_override) if (material_override) {
find_shader(material_override, used_shaders, default_shader); find_shader(material_override, used_shaders, default_shader);
else }
else {
used_shaders.push_back_slow(default_shader); used_shaders.push_back_slow(default_shader);
} }
}
return used_shaders; return used_shaders;
} }
@ -149,8 +151,9 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
geom->set_used_shaders(used_shaders); geom->set_used_shaders(used_shaders);
auto sync_func = [=]() mutable { auto sync_func = [=]() mutable {
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
progress.set_sync_status("Synchronizing object", b_ob_info.real_object.name()); progress.set_sync_status("Synchronizing object", b_ob_info.real_object.name());
@ -203,8 +206,9 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
/* Ensure we only motion sync geometry that also had geometry synced, to avoid /* Ensure we only motion sync geometry that also had geometry synced, to avoid
* unnecessary work and to ensure that its attributes were clear. */ * unnecessary work and to ensure that its attributes were clear. */
if (geometry_synced.find(geom) == geometry_synced.end()) if (geometry_synced.find(geom) == geometry_synced.end()) {
return; return;
}
/* Find time matching motion step required by geometry. */ /* Find time matching motion step required by geometry. */
int motion_step = geom->motion_step(motion_time); int motion_step = geom->motion_step(motion_time);
@ -213,8 +217,9 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
} }
auto sync_func = [=]() mutable { auto sync_func = [=]() mutable {
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) { if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) {
Hair *hair = static_cast<Hair *>(geom); Hair *hair = static_cast<Hair *>(geom);

@ -33,8 +33,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) { if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) {
Shader *shader; Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) { if (!shader_map.add_or_update(&shader, b_light)) {
if (light->get_is_portal()) if (light->get_is_portal()) {
*use_portal = true; *use_portal = true;
}
return; return;
} }
} }
@ -126,13 +127,16 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0)); light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0));
} }
if (light->get_light_type() == LIGHT_AREA) if (light->get_light_type() == LIGHT_AREA) {
light->set_is_portal(get_boolean(clight, "is_portal")); light->set_is_portal(get_boolean(clight, "is_portal"));
else }
else {
light->set_is_portal(false); light->set_is_portal(false);
}
if (light->get_is_portal()) if (light->get_is_portal()) {
*use_portal = true; *use_portal = true;
}
/* visibility */ /* visibility */
uint visibility = object_ray_visibility(b_ob_info.real_object); uint visibility = object_ray_visibility(b_ob_info.real_object);

@ -648,10 +648,12 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
/* UV map */ /* UV map */
if (need_uv || need_tangent) { if (need_uv || need_tangent) {
if (active_render) if (active_render) {
uv_attr = mesh->subd_attributes.add(uv_std, uv_name); uv_attr = mesh->subd_attributes.add(uv_std, uv_name);
else }
else {
uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
}
if (subdivide_uvs) { if (subdivide_uvs) {
uv_attr->flags |= ATTR_SUBDIVIDED; uv_attr->flags |= ATTR_SUBDIVIDED;
@ -1344,7 +1346,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
0.0f; 0.0f;
/* Sync mesh itself. */ /* Sync mesh itself. */
if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE) if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
create_subd_mesh(scene, create_subd_mesh(scene,
&new_mesh, &new_mesh,
b_ob_info, b_ob_info,
@ -1354,7 +1356,8 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
motion_scale, motion_scale,
dicing_rate, dicing_rate,
max_subdivisions); max_subdivisions);
else }
else {
create_mesh(scene, create_mesh(scene,
&new_mesh, &new_mesh,
b_mesh, b_mesh,
@ -1362,6 +1365,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
need_motion, need_motion,
motion_scale, motion_scale,
false); false);
}
free_object_to_mesh(b_data, b_ob_info, b_mesh); free_object_to_mesh(b_data, b_ob_info, b_mesh);
} }
@ -1434,8 +1438,9 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
/* Add new attributes if they don't exist already. */ /* Add new attributes if they don't exist already. */
if (!attr_mP) { if (!attr_mP) {
attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_N) if (attr_N) {
attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
}
new_attribute = true; new_attribute = true;
} }
@ -1471,9 +1476,10 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
VLOG_DEBUG << "No actual deformation motion for object " << ob_name; VLOG_DEBUG << "No actual deformation motion for object " << ob_name;
} }
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mN) if (attr_mN) {
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL); mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
} }
}
else if (motion_step > 0) { else if (motion_step > 0) {
VLOG_DEBUG << "Filling deformation motion for object " << ob_name; VLOG_DEBUG << "Filling deformation motion for object " << ob_name;
/* motion, fill up previous steps that we might have skipped because /* motion, fill up previous steps that we might have skipped because
@ -1482,11 +1488,12 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
float3 *N = (attr_N) ? attr_N->data_float3() : NULL; float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
for (int step = 0; step < motion_step; step++) { for (int step = 0; step < motion_step; step++) {
memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts); memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
if (attr_mN) if (attr_mN) {
memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts); memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts);
} }
} }
} }
}
else { else {
if (b_verts_num != numverts) { if (b_verts_num != numverts) {
VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name

@ -260,10 +260,11 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
} }
/* mesh deformation */ /* mesh deformation */
if (object->get_geometry()) if (object->get_geometry()) {
sync_geometry_motion( sync_geometry_motion(
b_depsgraph, b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool); b_depsgraph, b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool);
} }
}
return object; return object;
} }
@ -669,13 +670,15 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
int height, int height,
void **python_thread_state) void **python_thread_state)
{ {
if (scene->need_motion() == Scene::MOTION_NONE) if (scene->need_motion() == Scene::MOTION_NONE) {
return; return;
}
/* get camera object here to deal with camera switch */ /* get camera object here to deal with camera switch */
BL::Object b_cam = b_scene.camera(); BL::Object b_cam = b_scene.camera();
if (b_override) if (b_override) {
b_cam = b_override; b_cam = b_override;
}
int frame_center = b_scene.frame_current(); int frame_center = b_scene.frame_current();
float subframe_center = b_scene.frame_subframe(); float subframe_center = b_scene.frame_subframe();

@ -21,20 +21,23 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
{ {
/* Test if this dupli was generated from a particle system. */ /* Test if this dupli was generated from a particle system. */
BL::ParticleSystem b_psys = b_instance.particle_system(); BL::ParticleSystem b_psys = b_instance.particle_system();
if (!b_psys) if (!b_psys) {
return false; return false;
}
object->set_hide_on_missing_motion(true); object->set_hide_on_missing_motion(true);
/* test if we need particle data */ /* test if we need particle data */
if (!object->get_geometry()->need_attribute(scene, ATTR_STD_PARTICLE)) if (!object->get_geometry()->need_attribute(scene, ATTR_STD_PARTICLE)) {
return false; return false;
}
/* don't handle child particles yet */ /* don't handle child particles yet */
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_instance.persistent_id(); BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_instance.persistent_id();
if (persistent_id[0] >= b_psys.particles.length()) if (persistent_id[0] >= b_psys.particles.length()) {
return false; return false;
}
/* find particle system */ /* find particle system */
ParticleSystemKey key(b_ob, persistent_id); ParticleSystemKey key(b_ob, persistent_id);
@ -46,7 +49,9 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
/* no update needed? */ /* no update needed? */
if (!need_update && !object->get_geometry()->is_modified() && if (!need_update && !object->get_geometry()->is_modified() &&
!scene->object_manager->need_update()) !scene->object_manager->need_update())
{
return true; return true;
}
/* first time used in this sync loop? clear and tag update */ /* first time used in this sync loop? clear and tag update */
if (first_use) { if (first_use) {
@ -72,8 +77,9 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
object->set_particle_system(psys); object->set_particle_system(psys);
object->set_particle_index(psys->particles.size() - 1); object->set_particle_index(psys->particles.size() - 1);
if (object->particle_index_is_modified()) if (object->particle_index_is_modified()) {
scene->object_manager->tag_update(scene, ObjectManager::PARTICLE_MODIFIED); scene->object_manager->tag_update(scene, ObjectManager::PARTICLE_MODIFIED);
}
/* return that this object has particle data */ /* return that this object has particle data */
return true; return true;

@ -44,8 +44,9 @@ bool debug_flags_set = false;
void *pylong_as_voidptr_typesafe(PyObject *object) void *pylong_as_voidptr_typesafe(PyObject *object)
{ {
if (object == Py_None) if (object == Py_None) {
return NULL; return NULL;
}
return PyLong_AsVoidPtr(object); return PyLong_AsVoidPtr(object);
} }
@ -224,8 +225,9 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pysession, *pydepsgraph; PyObject *pysession, *pydepsgraph;
if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) {
return NULL; return NULL;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession); BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
@ -300,7 +302,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
&pass_filter, &pass_filter,
&width, &width,
&height)) &height))
{
return NULL; return NULL;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession); BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
@ -324,8 +328,9 @@ static PyObject *view_draw_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pysession, *pygraph, *pyv3d, *pyrv3d; PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
if (!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d)) if (!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d)) {
return NULL; return NULL;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession); BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
@ -344,8 +349,9 @@ static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pysession, *pydata, *pydepsgraph; PyObject *pysession, *pydata, *pydepsgraph;
if (!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph)) if (!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph)) {
return NULL; return NULL;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession); BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
@ -369,8 +375,9 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pysession, *pydepsgraph; PyObject *pysession, *pydepsgraph;
if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) {
return NULL; return NULL;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession); BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);

@ -446,9 +446,10 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
printf("Render statistics:\n%s\n", stats.full_report().c_str()); printf("Render statistics:\n%s\n", stats.full_report().c_str());
} }
if (session->progress.get_cancel()) if (session->progress.get_cancel()) {
break; break;
} }
}
/* add metadata */ /* add metadata */
stamp_view_layer_metadata(scene, b_rlay_name); stamp_view_layer_metadata(scene, b_rlay_name);
@ -741,8 +742,9 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_) void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
{ {
/* only used for viewport render */ /* only used for viewport render */
if (!b_v3d) if (!b_v3d) {
return; return;
}
/* on session/scene parameter changes, we recreate session entirely */ /* on session/scene parameter changes, we recreate session entirely */
const SessionParams session_params = BlenderSync::get_session_params( const SessionParams session_params = BlenderSync::get_session_params(
@ -786,10 +788,12 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
sync->sync_data( sync->sync_data(
b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state); b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
if (b_rv3d) if (b_rv3d) {
sync->sync_view(b_v3d, b_rv3d, width, height); sync->sync_view(b_v3d, b_rv3d, width, height);
else }
else {
sync->sync_camera(b_render, b_camera_override, width, height, ""); sync->sync_camera(b_render, b_camera_override, width, height, "");
}
/* get buffer parameters */ /* get buffer parameters */
const BufferParams buffer_params = BlenderSync::get_buffer_params( const BufferParams buffer_params = BlenderSync::get_buffer_params(
@ -891,8 +895,9 @@ void BlenderSession::view_draw(int w, int h)
sync->sync_view(b_v3d, b_rv3d, width, height); sync->sync_view(b_v3d, b_rv3d, width, height);
if (scene->camera->is_modified()) if (scene->camera->is_modified()) {
reset = true; reset = true;
}
session->scene->mutex.unlock(); session->scene->mutex.unlock();
} }
@ -960,13 +965,16 @@ void BlenderSession::update_status_progress()
} }
if (background) { if (background) {
if (scene) if (scene) {
scene_status += " | " + scene->name; scene_status += " | " + scene->name;
if (b_rlay_name != "") }
if (b_rlay_name != "") {
scene_status += ", " + b_rlay_name; scene_status += ", " + b_rlay_name;
}
if (b_rview_name != "") if (b_rview_name != "") {
scene_status += ", " + b_rview_name; scene_status += ", " + b_rview_name;
}
if (remaining_time > 0) { if (remaining_time > 0) {
timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | "; timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | ";
@ -974,11 +982,13 @@ void BlenderSession::update_status_progress()
timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak); timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
if (status.size() > 0) if (status.size() > 0) {
status = " | " + status; status = " | " + status;
if (substatus.size() > 0) }
if (substatus.size() > 0) {
status += " | " + substatus; status += " | " + substatus;
} }
}
double current_time = time_dt(); double current_time = time_dt();
/* When rendering in a window, redraw the status at least once per second to keep the elapsed /* When rendering in a window, redraw the status at least once per second to keep the elapsed
@ -1046,9 +1056,11 @@ void BlenderSession::tag_redraw()
void BlenderSession::test_cancel() void BlenderSession::test_cancel()
{ {
/* test if we need to cancel rendering */ /* test if we need to cancel rendering */
if (background) if (background) {
if (b_engine.test_break()) if (b_engine.test_break()) {
session->progress.set_cancel("Cancelled"); session->progress.set_cancel("Cancelled");
}
}
} }
void BlenderSession::free_blender_memory_if_possible() void BlenderSession::free_blender_memory_if_possible()

@ -254,8 +254,9 @@ static void set_default_value(ShaderInput *input,
static void get_tex_mapping(TextureNode *mapping, BL::TexMapping &b_mapping) static void get_tex_mapping(TextureNode *mapping, BL::TexMapping &b_mapping)
{ {
if (!b_mapping) if (!b_mapping) {
return; return;
}
mapping->set_tex_mapping_translation(get_float3(b_mapping.translation())); mapping->set_tex_mapping_translation(get_float3(b_mapping.translation()));
mapping->set_tex_mapping_rotation(get_float3(b_mapping.rotation())); mapping->set_tex_mapping_rotation(get_float3(b_mapping.rotation()));
@ -1084,8 +1085,9 @@ static ShaderNode *add_node(Scene *scene,
static bool node_use_modified_socket_name(ShaderNode *node) static bool node_use_modified_socket_name(ShaderNode *node)
{ {
if (node->special_type == SHADER_SPECIAL_TYPE_OSL) if (node->special_type == SHADER_SPECIAL_TYPE_OSL) {
return false; return false;
}
return true; return true;
} }

@ -793,15 +793,19 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene,
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system"); const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
if (shadingsystem == 0) if (shadingsystem == 0) {
params.shadingsystem = SHADINGSYSTEM_SVM; params.shadingsystem = SHADINGSYSTEM_SVM;
else if (shadingsystem == 1) }
else if (shadingsystem == 1) {
params.shadingsystem = SHADINGSYSTEM_OSL; params.shadingsystem = SHADINGSYSTEM_OSL;
}
if (background || (use_developer_ui && get_enum(cscene, "debug_bvh_type"))) if (background || (use_developer_ui && get_enum(cscene, "debug_bvh_type"))) {
params.bvh_type = BVH_TYPE_STATIC; params.bvh_type = BVH_TYPE_STATIC;
else }
else {
params.bvh_type = BVH_TYPE_DYNAMIC; params.bvh_type = BVH_TYPE_DYNAMIC;
}
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
params.use_bvh_compact_structure = RNA_boolean_get(&cscene, "debug_use_compact_bvh"); params.use_bvh_compact_structure = RNA_boolean_get(&cscene, "debug_use_compact_bvh");
@ -903,10 +907,12 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* shading system - scene level needs full refresh */ /* shading system - scene level needs full refresh */
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system"); const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
if (shadingsystem == 0) if (shadingsystem == 0) {
params.shadingsystem = SHADINGSYSTEM_SVM; params.shadingsystem = SHADINGSYSTEM_SVM;
else if (shadingsystem == 1) }
else if (shadingsystem == 1) {
params.shadingsystem = SHADINGSYSTEM_OSL; params.shadingsystem = SHADINGSYSTEM_OSL;
}
/* Time limit. */ /* Time limit. */
if (background) { if (background) {

@ -12,12 +12,15 @@ namespace {
void density_texture_space_invert(float3 &loc, float3 &size) void density_texture_space_invert(float3 &loc, float3 &size)
{ {
if (size.x != 0.0f) if (size.x != 0.0f) {
size.x = 0.5f / size.x; size.x = 0.5f / size.x;
if (size.y != 0.0f) }
if (size.y != 0.0f) {
size.y = 0.5f / size.y; size.y = 0.5f / size.y;
if (size.z != 0.0f) }
if (size.z != 0.0f) {
size.z = 0.5f / size.z; size.z = 0.5f / size.z;
}
loc = loc * size - make_float3(0.5f, 0.5f, 0.5f); loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
} }

@ -41,12 +41,15 @@ __forceinline int get_best_dimension(const float4 &bestSAH)
float minSAH = min(bestSAH.x, min(bestSAH.y, bestSAH.z)); float minSAH = min(bestSAH.x, min(bestSAH.y, bestSAH.z));
if (bestSAH.x == minSAH) if (bestSAH.x == minSAH) {
return 0; return 0;
else if (bestSAH.y == minSAH) }
else if (bestSAH.y == minSAH) {
return 1; return 1;
else }
else {
return 2; return 2;
}
} }
/* BVH Object Binning */ /* BVH Object Binning */

@ -383,8 +383,9 @@ static size_t count_curve_segments(Hair *hair)
{ {
size_t num = 0, num_curves = hair->num_curves(); size_t num = 0, num_curves = hair->num_curves();
for (size_t i = 0; i < num_curves; i++) for (size_t i = 0; i < num_curves; i++) {
num += hair->get_curve(i).num_keys - 1; num += hair->get_curve(i).num_keys - 1;
}
return num; return num;
} }
@ -441,23 +442,28 @@ void BVHBuild::add_references(BVHRange &root)
++i; ++i;
continue; continue;
} }
if (!ob->get_geometry()->is_instanced()) if (!ob->get_geometry()->is_instanced()) {
add_reference_geometry(bounds, center, ob->get_geometry(), i); add_reference_geometry(bounds, center, ob->get_geometry(), i);
else }
else {
add_reference_object(bounds, center, ob, i); add_reference_object(bounds, center, ob, i);
} }
else }
else {
add_reference_geometry(bounds, center, ob->get_geometry(), i); add_reference_geometry(bounds, center, ob->get_geometry(), i);
}
i++; i++;
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
}
/* happens mostly on empty meshes */ /* happens mostly on empty meshes */
if (!bounds.valid()) if (!bounds.valid()) {
bounds.grow(zero_float3()); bounds.grow(zero_float3());
}
root = BVHRange(bounds, center, 0, references.size()); root = BVHRange(bounds, center, 0, references.size());
} }
@ -471,8 +477,9 @@ BVHNode *BVHBuild::run()
/* add references */ /* add references */
add_references(root); add_references(root);
if (progress.get_cancel()) if (progress.get_cancel()) {
return NULL; return NULL;
}
/* init spatial splits */ /* init spatial splits */
if (params.top_level) { if (params.top_level) {
@ -566,8 +573,9 @@ BVHNode *BVHBuild::run()
void BVHBuild::progress_update() void BVHBuild::progress_update()
{ {
if (time_dt() - progress_start_time < 0.25) if (time_dt() - progress_start_time < 0.25) {
return; return;
}
double progress_start = (double)progress_count / (double)progress_total; double progress_start = (double)progress_count / (double)progress_total;
double duplicates = (double)(progress_total - progress_original_total) / (double)progress_total; double duplicates = (double)(progress_total - progress_original_total) / (double)progress_total;
@ -584,8 +592,9 @@ void BVHBuild::thread_build_node(InnerNode *inner,
const BVHObjectBinning &range, const BVHObjectBinning &range,
int level) int level)
{ {
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* build nodes */ /* build nodes */
BVHNode *node = build_node(range, level); BVHNode *node = build_node(range, level);
@ -631,8 +640,9 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size), size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size),
params.max_point_leaf_size); params.max_point_leaf_size);
if (size > max_leaf_size) if (size > max_leaf_size) {
return false; return false;
}
size_t num_triangles = 0; size_t num_triangles = 0;
size_t num_motion_triangles = 0; size_t num_motion_triangles = 0;
@ -1174,22 +1184,26 @@ void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations)
{ {
/* In tested scenes, this resulted in slightly slower ray-tracing, so disabled /* In tested scenes, this resulted in slightly slower ray-tracing, so disabled
* it for now. could be implementation bug, or depend on the scene. */ * it for now. could be implementation bug, or depend on the scene. */
if (node) if (node) {
for (int i = 0; i < iterations; i++) for (int i = 0; i < iterations; i++) {
rotate(node, max_depth); rotate(node, max_depth);
}
}
} }
void BVHBuild::rotate(BVHNode *node, int max_depth) void BVHBuild::rotate(BVHNode *node, int max_depth)
{ {
/* nothing to rotate if we reached a leaf node. */ /* nothing to rotate if we reached a leaf node. */
if (node->is_leaf() || max_depth < 0) if (node->is_leaf() || max_depth < 0) {
return; return;
}
InnerNode *parent = (InnerNode *)node; InnerNode *parent = (InnerNode *)node;
/* rotate all children first */ /* rotate all children first */
for (size_t c = 0; c < 2; c++) for (size_t c = 0; c < 2; c++) {
rotate(parent->children[c], max_depth - 1); rotate(parent->children[c], max_depth - 1);
}
/* compute current area of all children */ /* compute current area of all children */
BoundBox bounds0 = parent->children[0]->bounds; BoundBox bounds0 = parent->children[0]->bounds;
@ -1206,8 +1220,9 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
for (size_t c = 0; c < 2; c++) { for (size_t c = 0; c < 2; c++) {
/* ignore leaf nodes as we cannot descent into */ /* ignore leaf nodes as we cannot descent into */
if (parent->children[c]->is_leaf()) if (parent->children[c]->is_leaf()) {
continue; continue;
}
InnerNode *child = (InnerNode *)parent->children[c]; InnerNode *child = (InnerNode *)parent->children[c];
BoundBox &other = (c == 0) ? bounds1 : bounds0; BoundBox &other = (c == 0) ? bounds1 : bounds0;
@ -1236,8 +1251,9 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
} }
/* if we did not find a swap that improves the SAH then do nothing */ /* if we did not find a swap that improves the SAH then do nothing */
if (best_cost >= 0) if (best_cost >= 0) {
return; return;
}
assert(best_child == 0 || best_child == 1); assert(best_child == 0 || best_child == 1);
assert(best_target != -1); assert(best_target != -1);

@ -92,8 +92,9 @@ void BVH2::refit(Progress &progress)
progress.set_substatus("Packing BVH primitives"); progress.set_substatus("Packing BVH primitives");
pack_primitives(); pack_primitives();
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
progress.set_substatus("Refitting BVH nodes"); progress.set_substatus("Refitting BVH nodes");
refit_nodes(); refit_nodes();
@ -393,11 +394,12 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility
size_t steps = hair->get_motion_steps() - 1; size_t steps = hair->get_motion_steps() - 1;
float3 *key_steps = attr->data_float3(); float3 *key_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++) for (size_t i = 0; i < steps; i++) {
curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox); curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox);
} }
} }
} }
}
else if (pack.prim_type[prim] & PRIMITIVE_POINT) { else if (pack.prim_type[prim] & PRIMITIVE_POINT) {
/* Points. */ /* Points. */
const PointCloud *pointcloud = static_cast<const PointCloud *>(ob->get_geometry()); const PointCloud *pointcloud = static_cast<const PointCloud *>(ob->get_geometry());
@ -417,11 +419,12 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility
size_t steps = pointcloud->get_motion_steps() - 1; size_t steps = pointcloud->get_motion_steps() - 1;
float3 *point_steps = attr->data_float3(); float3 *point_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++) for (size_t i = 0; i < steps; i++) {
point.bounds_grow(point_steps + i * pointcloud_size, radius, bbox); point.bounds_grow(point_steps + i * pointcloud_size, radius, bbox);
} }
} }
} }
}
else { else {
/* Triangles. */ /* Triangles. */
const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry()); const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
@ -440,12 +443,13 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility
size_t steps = mesh->motion_steps - 1; size_t steps = mesh->motion_steps - 1;
float3 *vert_steps = attr->data_float3(); float3 *vert_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++) for (size_t i = 0; i < steps; i++) {
triangle.bounds_grow(vert_steps + i * mesh_size, bbox); triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
} }
} }
} }
} }
}
visibility |= ob->visibility_for_tracing(); visibility |= ob->visibility_for_tracing();
} }
} }
@ -563,10 +567,12 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
int geom_prim_offset = geom->prim_offset; int geom_prim_offset = geom->prim_offset;
/* fill in node indexes for instances */ /* fill in node indexes for instances */
if (bvh->pack.root_index == -1) if (bvh->pack.root_index == -1) {
pack.object_node[object_offset++] = -noffset_leaf - 1; pack.object_node[object_offset++] = -noffset_leaf - 1;
else }
else {
pack.object_node[object_offset++] = noffset; pack.object_node[object_offset++] = noffset;
}
geometry_map[geom] = pack.object_node[object_offset - 1]; geometry_map[geom] = pack.object_node[object_offset - 1];

@ -85,18 +85,22 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
assert(0); /* unknown mode */ assert(0); /* unknown mode */
} }
if (!is_leaf()) if (!is_leaf()) {
for (int i = 0; i < num_children(); i++) for (int i = 0; i < num_children(); i++) {
cnt += get_child(i)->getSubtreeSize(stat); cnt += get_child(i)->getSubtreeSize(stat);
}
}
return cnt; return cnt;
} }
void BVHNode::deleteSubtree() void BVHNode::deleteSubtree()
{ {
for (int i = 0; i < num_children(); i++) for (int i = 0; i < num_children(); i++) {
if (get_child(i)) if (get_child(i)) {
get_child(i)->deleteSubtree(); get_child(i)->deleteSubtree();
}
}
delete this; delete this;
} }
@ -192,21 +196,25 @@ void BVHNode::dump_graph(const char *filename)
void InnerNode::print(int depth) const void InnerNode::print(int depth) const
{ {
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++) {
printf(" "); printf(" ");
}
printf("inner node %p\n", (void *)this); printf("inner node %p\n", (void *)this);
if (children[0]) if (children[0]) {
children[0]->print(depth + 1); children[0]->print(depth + 1);
if (children[1]) }
if (children[1]) {
children[1]->print(depth + 1); children[1]->print(depth + 1);
}
} }
void LeafNode::print(int depth) const void LeafNode::print(int depth) const
{ {
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++) {
printf(" "); printf(" ");
}
printf("leaf node %d to %d\n", lo, hi); printf("leaf node %d to %d\n", lo, hi);
} }

@ -46,22 +46,30 @@ struct BVHReferenceCompare {
float ca = ra_bounds.min[dim] + ra_bounds.max[dim]; float ca = ra_bounds.min[dim] + ra_bounds.max[dim];
float cb = rb_bounds.min[dim] + rb_bounds.max[dim]; float cb = rb_bounds.min[dim] + rb_bounds.max[dim];
if (ca < cb) if (ca < cb) {
return -1; return -1;
else if (ca > cb) }
else if (ca > cb) {
return 1; return 1;
else if (ra.prim_object() < rb.prim_object()) }
else if (ra.prim_object() < rb.prim_object()) {
return -1; return -1;
else if (ra.prim_object() > rb.prim_object()) }
else if (ra.prim_object() > rb.prim_object()) {
return 1; return 1;
else if (ra.prim_index() < rb.prim_index()) }
else if (ra.prim_index() < rb.prim_index()) {
return -1; return -1;
else if (ra.prim_index() > rb.prim_index()) }
else if (ra.prim_index() > rb.prim_index()) {
return 1; return 1;
else if (ra.prim_type() < rb.prim_type()) }
else if (ra.prim_type() < rb.prim_type()) {
return -1; return -1;
else if (ra.prim_type() > rb.prim_type()) }
else if (ra.prim_type() > rb.prim_type()) {
return 1; return 1;
}
return 0; return 0;
} }

@ -355,11 +355,13 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
float v1p = v1[dim]; float v1p = v1[dim];
/* insert vertex to the boxes it belongs to. */ /* insert vertex to the boxes it belongs to. */
if (v0p <= pos) if (v0p <= pos) {
left_bounds.grow(v0); left_bounds.grow(v0);
}
if (v0p >= pos) if (v0p >= pos) {
right_bounds.grow(v0); right_bounds.grow(v0);
}
/* edge intersects the plane => insert intersection to both boxes. */ /* edge intersects the plane => insert intersection to both boxes. */
if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
@ -397,17 +399,21 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair,
float v1p = v1[dim]; float v1p = v1[dim];
/* insert vertex to the boxes it belongs to. */ /* insert vertex to the boxes it belongs to. */
if (v0p <= pos) if (v0p <= pos) {
left_bounds.grow(v0); left_bounds.grow(v0);
}
if (v0p >= pos) if (v0p >= pos) {
right_bounds.grow(v0); right_bounds.grow(v0);
}
if (v1p <= pos) if (v1p <= pos) {
left_bounds.grow(v1); left_bounds.grow(v1);
}
if (v1p >= pos) if (v1p >= pos) {
right_bounds.grow(v1); right_bounds.grow(v1);
}
/* edge intersects the plane => insert intersection to both boxes. */ /* edge intersects the plane => insert intersection to both boxes. */
if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {

@ -48,8 +48,9 @@ string device_cpu_capabilities()
capabilities += system_cpu_support_sse2() ? "SSE2 " : ""; capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
capabilities += system_cpu_support_sse41() ? "SSE41 " : ""; capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
capabilities += system_cpu_support_avx2() ? "AVX2" : ""; capabilities += system_cpu_support_avx2() ? "AVX2" : "";
if (capabilities[capabilities.size() - 1] == ' ') if (capabilities[capabilities.size() - 1] == ' ') {
capabilities.resize(capabilities.size() - 1); capabilities.resize(capabilities.size() - 1);
}
return capabilities; return capabilities;
} }

@ -24,8 +24,9 @@ bool device_cuda_init()
static bool initialized = false; static bool initialized = false;
static bool result = false; static bool result = false;
if (initialized) if (initialized) {
return result; return result;
}
initialized = true; initialized = true;
int cuew_result = cuewInit(CUEW_INIT_CUDA); int cuew_result = cuewInit(CUEW_INIT_CUDA);
@ -99,8 +100,9 @@ void device_cuda_info(vector<DeviceInfo> &devices)
#ifdef WITH_CUDA #ifdef WITH_CUDA
CUresult result = device_cuda_safe_init(); CUresult result = device_cuda_safe_init();
if (result != CUDA_SUCCESS) { if (result != CUDA_SUCCESS) {
if (result != CUDA_ERROR_NO_DEVICE) if (result != CUDA_ERROR_NO_DEVICE) {
fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result)); fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
}
return; return;
} }
@ -188,8 +190,9 @@ void device_cuda_info(vector<DeviceInfo> &devices)
VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\"."; VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
} }
if (!display_devices.empty()) if (!display_devices.empty()) {
devices.insert(devices.end(), display_devices.begin(), display_devices.end()); devices.insert(devices.end(), display_devices.begin(), display_devices.end());
}
#else /* WITH_CUDA */ #else /* WITH_CUDA */
(void)devices; (void)devices;
#endif /* WITH_CUDA */ #endif /* WITH_CUDA */

@ -408,19 +408,22 @@ bool CUDADevice::load_kernels(const uint kernel_features)
} }
/* check if cuda init succeeded */ /* check if cuda init succeeded */
if (cuContext == 0) if (cuContext == 0) {
return false; return false;
}
/* check if GPU is supported */ /* check if GPU is supported */
if (!support_device(kernel_features)) if (!support_device(kernel_features)) {
return false; return false;
}
/* get kernel */ /* get kernel */
const char *kernel_name = "kernel"; const char *kernel_name = "kernel";
string cflags = compile_kernel_get_common_cflags(kernel_features); string cflags = compile_kernel_get_common_cflags(kernel_features);
string cubin = compile_kernel(cflags, kernel_name); string cubin = compile_kernel(cflags, kernel_name);
if (cubin.empty()) if (cubin.empty()) {
return false; return false;
}
/* open module */ /* open module */
CUDAContextScope scope(this); CUDAContextScope scope(this);
@ -428,14 +431,17 @@ bool CUDADevice::load_kernels(const uint kernel_features)
string cubin_data; string cubin_data;
CUresult result; CUresult result;
if (path_read_text(cubin, cubin_data)) if (path_read_text(cubin, cubin_data)) {
result = cuModuleLoadData(&cuModule, cubin_data.c_str()); result = cuModuleLoadData(&cuModule, cubin_data.c_str());
else }
else {
result = CUDA_ERROR_FILE_NOT_FOUND; result = CUDA_ERROR_FILE_NOT_FOUND;
}
if (result != CUDA_SUCCESS) if (result != CUDA_SUCCESS) {
set_error(string_printf( set_error(string_printf(
"Failed to load CUDA kernel from '%s' (%s)", cubin.c_str(), cuewErrorString(result))); "Failed to load CUDA kernel from '%s' (%s)", cubin.c_str(), cuewErrorString(result)));
}
if (result == CUDA_SUCCESS) { if (result == CUDA_SUCCESS) {
kernels.load(this); kernels.load(this);

@ -79,8 +79,9 @@ Device *Device::create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
break; break;
#ifdef WITH_CUDA #ifdef WITH_CUDA
case DEVICE_CUDA: case DEVICE_CUDA:
if (device_cuda_init()) if (device_cuda_init()) {
device = device_cuda_create(info, stats, profiler); device = device_cuda_create(info, stats, profiler);
}
break; break;
#endif #endif
#ifdef WITH_OPTIX #ifdef WITH_OPTIX
@ -123,44 +124,60 @@ Device *Device::create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
DeviceType Device::type_from_string(const char *name) DeviceType Device::type_from_string(const char *name)
{ {
if (strcmp(name, "CPU") == 0) if (strcmp(name, "CPU") == 0) {
return DEVICE_CPU; return DEVICE_CPU;
else if (strcmp(name, "CUDA") == 0) }
else if (strcmp(name, "CUDA") == 0) {
return DEVICE_CUDA; return DEVICE_CUDA;
else if (strcmp(name, "OPTIX") == 0) }
else if (strcmp(name, "OPTIX") == 0) {
return DEVICE_OPTIX; return DEVICE_OPTIX;
else if (strcmp(name, "MULTI") == 0) }
else if (strcmp(name, "MULTI") == 0) {
return DEVICE_MULTI; return DEVICE_MULTI;
else if (strcmp(name, "HIP") == 0) }
else if (strcmp(name, "HIP") == 0) {
return DEVICE_HIP; return DEVICE_HIP;
else if (strcmp(name, "METAL") == 0) }
else if (strcmp(name, "METAL") == 0) {
return DEVICE_METAL; return DEVICE_METAL;
else if (strcmp(name, "ONEAPI") == 0) }
else if (strcmp(name, "ONEAPI") == 0) {
return DEVICE_ONEAPI; return DEVICE_ONEAPI;
else if (strcmp(name, "HIPRT") == 0) }
else if (strcmp(name, "HIPRT") == 0) {
return DEVICE_HIPRT; return DEVICE_HIPRT;
}
return DEVICE_NONE; return DEVICE_NONE;
} }
string Device::string_from_type(DeviceType type) string Device::string_from_type(DeviceType type)
{ {
if (type == DEVICE_CPU) if (type == DEVICE_CPU) {
return "CPU"; return "CPU";
else if (type == DEVICE_CUDA) }
else if (type == DEVICE_CUDA) {
return "CUDA"; return "CUDA";
else if (type == DEVICE_OPTIX) }
else if (type == DEVICE_OPTIX) {
return "OPTIX"; return "OPTIX";
else if (type == DEVICE_MULTI) }
else if (type == DEVICE_MULTI) {
return "MULTI"; return "MULTI";
else if (type == DEVICE_HIP) }
else if (type == DEVICE_HIP) {
return "HIP"; return "HIP";
else if (type == DEVICE_METAL) }
else if (type == DEVICE_METAL) {
return "METAL"; return "METAL";
else if (type == DEVICE_ONEAPI) }
else if (type == DEVICE_ONEAPI) {
return "ONEAPI"; return "ONEAPI";
else if (type == DEVICE_HIPRT) }
else if (type == DEVICE_HIPRT) {
return "HIPRT"; return "HIPRT";
}
return ""; return "";
} }

@ -153,8 +153,9 @@ class MultiDevice : public Device {
bool load_kernels(const uint kernel_features) override bool load_kernels(const uint kernel_features) override
{ {
foreach (SubDevice &sub, devices) foreach (SubDevice &sub, devices)
if (!sub.device->load_kernels(kernel_features)) if (!sub.device->load_kernels(kernel_features)) {
return false; return false;
}
return true; return true;
} }
@ -162,8 +163,9 @@ class MultiDevice : public Device {
bool load_osl_kernels() override bool load_osl_kernels() override
{ {
foreach (SubDevice &sub, devices) foreach (SubDevice &sub, devices)
if (!sub.device->load_osl_kernels()) if (!sub.device->load_osl_kernels()) {
return false; return false;
}
return true; return true;
} }
@ -204,26 +206,34 @@ class MultiDevice : public Device {
if (!bvh_multi->sub_bvhs[i]) { if (!bvh_multi->sub_bvhs[i]) {
BVHParams params = bvh->params; BVHParams params = bvh->params;
if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX) if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX) {
params.bvh_layout = BVH_LAYOUT_OPTIX; params.bvh_layout = BVH_LAYOUT_OPTIX;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL) {
params.bvh_layout = BVH_LAYOUT_METAL; params.bvh_layout = BVH_LAYOUT_METAL;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_HIPRT) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_HIPRT) {
params.bvh_layout = BVH_LAYOUT_HIPRT; params.bvh_layout = BVH_LAYOUT_HIPRT;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_EMBREEGPU) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_EMBREEGPU) {
params.bvh_layout = BVH_LAYOUT_EMBREEGPU; params.bvh_layout = BVH_LAYOUT_EMBREEGPU;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE) {
params.bvh_layout = sub.device->info.type == DEVICE_OPTIX ? BVH_LAYOUT_OPTIX : params.bvh_layout = sub.device->info.type == DEVICE_OPTIX ? BVH_LAYOUT_OPTIX :
BVH_LAYOUT_EMBREE; BVH_LAYOUT_EMBREE;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL_EMBREE) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL_EMBREE) {
params.bvh_layout = sub.device->info.type == DEVICE_METAL ? BVH_LAYOUT_METAL : params.bvh_layout = sub.device->info.type == DEVICE_METAL ? BVH_LAYOUT_METAL :
BVH_LAYOUT_EMBREE; BVH_LAYOUT_EMBREE;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_HIPRT_EMBREE) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_HIPRT_EMBREE) {
params.bvh_layout = sub.device->info.type == DEVICE_HIP ? BVH_LAYOUT_HIPRT : params.bvh_layout = sub.device->info.type == DEVICE_HIP ? BVH_LAYOUT_HIPRT :
BVH_LAYOUT_EMBREE; BVH_LAYOUT_EMBREE;
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_EMBREEGPU_EMBREE) }
else if (bvh->params.bvh_layout == BVH_LAYOUT_MULTI_EMBREEGPU_EMBREE) {
params.bvh_layout = sub.device->info.type == DEVICE_ONEAPI ? BVH_LAYOUT_EMBREEGPU : params.bvh_layout = sub.device->info.type == DEVICE_ONEAPI ? BVH_LAYOUT_EMBREEGPU :
BVH_LAYOUT_EMBREE; BVH_LAYOUT_EMBREE;
}
/* Skip building a bottom level acceleration structure for non-instanced geometry on Embree /* Skip building a bottom level acceleration structure for non-instanced geometry on Embree
* (since they are put into the top level directly, see bvh_embree.cpp) */ * (since they are put into the top level directly, see bvh_embree.cpp) */
if (!params.top_level && params.bvh_layout == BVH_LAYOUT_EMBREE && if (!params.top_level && params.bvh_layout == BVH_LAYOUT_EMBREE &&
@ -440,8 +450,9 @@ class MultiDevice : public Device {
int i = 0; int i = 0;
foreach (SubDevice &sub, devices) { foreach (SubDevice &sub, devices) {
if (sub.device == sub_device) if (sub.device == sub_device) {
return i; return i;
}
i++; i++;
} }

@ -46,10 +46,11 @@ DeviceQueue::~DeviceQueue()
<< "s: " << device_kernel_mask_as_string(mask); << "s: " << device_kernel_mask_as_string(mask);
} }
if (is_per_kernel_performance_) if (is_per_kernel_performance_) {
VLOG_DEVICE_STATS << "GPU queue total time: " << std::fixed << std::setprecision(5) VLOG_DEVICE_STATS << "GPU queue total time: " << std::fixed << std::setprecision(5)
<< total_time; << total_time;
} }
}
} }
void DeviceQueue::debug_init_execution() void DeviceQueue::debug_init_execution()

@ -566,9 +566,10 @@ bool Node::equals(const Node &other) const
assert(type == other.type); assert(type == other.type);
foreach (const SocketType &socket, type->inputs) { foreach (const SocketType &socket, type->inputs) {
if (!equals_value(other, socket)) if (!equals_value(other, socket)) {
return false; return false;
} }
}
return true; return true;
} }

@ -34,9 +34,10 @@ static void xml_read_float_array(T &value, xml_attribute attr)
for (size_t i = 0; i < value.size(); i++) { for (size_t i = 0; i < value.size(); i++) {
float *value_float = (float *)&value[i]; float *value_float = (float *)&value[i];
for (size_t j = 0; j < VECTOR_SIZE; j++) for (size_t j = 0; j < VECTOR_SIZE; j++) {
value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str()); value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
} }
}
} }
void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node) void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
@ -71,8 +72,9 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
array<bool> value; array<bool> value;
value.resize(tokens.size()); value.resize(tokens.size());
for (size_t i = 0; i < value.size(); i++) for (size_t i = 0; i < value.size(); i++) {
value[i] = xml_read_boolean(tokens[i].c_str()); value[i] = xml_read_boolean(tokens[i].c_str());
}
node->set(socket, value); node->set(socket, value);
break; break;
} }
@ -192,9 +194,10 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
map<ustring, Node *>::iterator it = reader.node_map.find(value); map<ustring, Node *>::iterator it = reader.node_map.find(value);
if (it != reader.node_map.end()) { if (it != reader.node_map.end()) {
Node *value_node = it->second; Node *value_node = it->second;
if (value_node->is_a(socket.node_type)) if (value_node->is_a(socket.node_type)) {
node->set(socket, it->second); node->set(socket, it->second);
} }
}
break; break;
} }
case SocketType::NODE_ARRAY: { case SocketType::NODE_ARRAY: {
@ -223,8 +226,9 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
} }
} }
if (!node->name.empty()) if (!node->name.empty()) {
reader.node_map[node->name] = node; reader.node_map[node->name] = node;
}
} }
xml_node xml_write_node(Node *node, xml_node xml_root) xml_node xml_write_node(Node *node, xml_node xml_root)
@ -256,9 +260,10 @@ xml_node xml_write_node(Node *node, xml_node xml_root)
const array<bool> &value = node->get_bool_array(socket); const array<bool> &value = node->get_bool_array(socket);
for (size_t i = 0; i < value.size(); i++) { for (size_t i = 0; i < value.size(); i++) {
ss << xml_write_boolean(value[i]); ss << xml_write_boolean(value[i]);
if (i != value.size() - 1) if (i != value.size() - 1) {
ss << " "; ss << " ";
} }
}
attr = ss.str().c_str(); attr = ss.str().c_str();
break; break;
} }

@ -162,10 +162,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
Transform tfm; Transform tfm;
if (time == sd->time) if (time == sd->time) {
tfm = object_get_transform(kg, sd); tfm = object_get_transform(kg, sd);
else }
else {
tfm = object_fetch_transform_motion_test(kg, object, time, NULL); tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
}
#else #else
const Transform tfm = object_get_transform(kg, sd); const Transform tfm = object_get_transform(kg, sd);
#endif #endif
@ -200,10 +202,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
Transform itfm; Transform itfm;
if (time == sd->time) if (time == sd->time) {
itfm = object_get_inverse_transform(kg, sd); itfm = object_get_inverse_transform(kg, sd);
else }
else {
object_fetch_transform_motion_test(kg, object, time, &itfm); object_fetch_transform_motion_test(kg, object, time, &itfm);
}
#else #else
const Transform itfm = object_get_inverse_transform(kg, sd); const Transform itfm = object_get_inverse_transform(kg, sd);
#endif #endif
@ -740,10 +744,12 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives,
fval[7] = P[2].y; fval[7] = P[2].y;
fval[8] = P[2].z; fval[8] = P[2].z;
if (type.arraylen > 3) if (type.arraylen > 3) {
memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3)); memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3));
if (derivatives) }
if (derivatives) {
memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen); memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen);
}
return true; return true;
} }
@ -1097,8 +1103,9 @@ bool OSLRenderServices::get_background_attribute(const KernelGlobalsCPU *kg,
return set_attribute_float3(ndc, type, derivatives, val); return set_attribute_float3(ndc, type, derivatives, val);
} }
else else {
return false; return false;
}
} }
bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
@ -1108,8 +1115,9 @@ bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
OSLUStringHash name, OSLUStringHash name,
void *val) void *val)
{ {
if (sg == NULL || sg->renderstate == NULL) if (sg == NULL || sg->renderstate == NULL) {
return false; return false;
}
ShaderData *sd = (ShaderData *)(sg->renderstate); ShaderData *sd = (ShaderData *)(sg->renderstate);
return get_attribute(sd, derivatives, object_name, type, name, val); return get_attribute(sd, derivatives, object_name, type, name, val);
@ -1129,8 +1137,9 @@ bool OSLRenderServices::get_attribute(ShaderData *sd,
if (object_name != u_empty) { if (object_name != u_empty) {
OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name); OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
if (it == kg->osl->object_name_map.end()) if (it == kg->osl->object_name_map.end()) {
return false; return false;
}
object = it->second; object = it->second;
} }
@ -1349,12 +1358,15 @@ bool OSLRenderServices::texture(OSLUStringHash filename,
} }
result[0] = rgba[0]; result[0] = rgba[0];
if (nchannels > 1) if (nchannels > 1) {
result[1] = rgba[1]; result[1] = rgba[1];
if (nchannels > 2) }
if (nchannels > 2) {
result[2] = rgba[2]; result[2] = rgba[2];
if (nchannels > 3) }
if (nchannels > 3) {
result[3] = rgba[3]; result[3] = rgba[3];
}
status = true; status = true;
break; break;
} }
@ -1421,10 +1433,11 @@ bool OSLRenderServices::texture(OSLUStringHash filename,
result[1] = 0.0f; result[1] = 0.0f;
result[2] = 1.0f; result[2] = 1.0f;
if (nchannels == 4) if (nchannels == 4) {
result[3] = 1.0f; result[3] = 1.0f;
} }
} }
}
return status; return status;
} }
@ -1459,12 +1472,15 @@ bool OSLRenderServices::texture3d(OSLUStringHash filename,
float4 rgba = kernel_tex_image_interp_3d(kernel_globals, slot, P_float3, INTERPOLATION_NONE); float4 rgba = kernel_tex_image_interp_3d(kernel_globals, slot, P_float3, INTERPOLATION_NONE);
result[0] = rgba[0]; result[0] = rgba[0];
if (nchannels > 1) if (nchannels > 1) {
result[1] = rgba[1]; result[1] = rgba[1];
if (nchannels > 2) }
if (nchannels > 2) {
result[2] = rgba[2]; result[2] = rgba[2];
if (nchannels > 3) }
if (nchannels > 3) {
result[3] = rgba[3]; result[3] = rgba[3];
}
status = true; status = true;
break; break;
} }
@ -1531,10 +1547,11 @@ bool OSLRenderServices::texture3d(OSLUStringHash filename,
result[1] = 0.0f; result[1] = 0.0f;
result[2] = 1.0f; result[2] = 1.0f;
if (nchannels == 4) if (nchannels == 4) {
result[3] = 1.0f; result[3] = 1.0f;
} }
} }
}
return status; return status;
} }
@ -1587,10 +1604,11 @@ bool OSLRenderServices::environment(OSLUStringHash filename,
result[1] = 0.0f; result[1] = 0.0f;
result[2] = 1.0f; result[2] = 1.0f;
if (nchannels == 4) if (nchannels == 4) {
result[3] = 1.0f; result[3] = 1.0f;
} }
} }
}
else if (handle && handle->processor) { else if (handle && handle->processor) {
ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels); ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
} }

@ -70,8 +70,9 @@ void Attribute::add(const float &f)
char *data = (char *)&f; char *data = (char *)&f;
size_t size = sizeof(f); size_t size = sizeof(f);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -83,8 +84,9 @@ void Attribute::add(const uchar4 &f)
char *data = (char *)&f; char *data = (char *)&f;
size_t size = sizeof(f); size_t size = sizeof(f);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -96,8 +98,9 @@ void Attribute::add(const float2 &f)
char *data = (char *)&f; char *data = (char *)&f;
size_t size = sizeof(f); size_t size = sizeof(f);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -109,8 +112,9 @@ void Attribute::add(const float3 &f)
char *data = (char *)&f; char *data = (char *)&f;
size_t size = sizeof(f); size_t size = sizeof(f);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -122,8 +126,9 @@ void Attribute::add(const Transform &f)
char *data = (char *)&f; char *data = (char *)&f;
size_t size = sizeof(f); size_t size = sizeof(f);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -132,8 +137,9 @@ void Attribute::add(const char *data)
{ {
size_t size = data_sizeof(); size_t size = data_sizeof();
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++) {
buffer.push_back(data[i]); buffer.push_back(data[i]);
}
modified = true; modified = true;
} }
@ -158,24 +164,32 @@ void Attribute::set_data_from(Attribute &&other)
size_t Attribute::data_sizeof() const size_t Attribute::data_sizeof() const
{ {
if (element == ATTR_ELEMENT_VOXEL) if (element == ATTR_ELEMENT_VOXEL) {
return sizeof(ImageHandle); return sizeof(ImageHandle);
else if (element == ATTR_ELEMENT_CORNER_BYTE) }
else if (element == ATTR_ELEMENT_CORNER_BYTE) {
return sizeof(uchar4); return sizeof(uchar4);
else if (type == TypeDesc::TypeFloat) }
else if (type == TypeDesc::TypeFloat) {
return sizeof(float); return sizeof(float);
else if (type == TypeFloat2) }
else if (type == TypeFloat2) {
return sizeof(float2); return sizeof(float2);
else if (type == TypeDesc::TypeMatrix) }
else if (type == TypeDesc::TypeMatrix) {
return sizeof(Transform); return sizeof(Transform);
// The float3 type is not interchangeable with float4 // The float3 type is not interchangeable with float4
// as it is now a packed type. // as it is now a packed type.
else if (type == TypeDesc::TypeFloat4) }
else if (type == TypeDesc::TypeFloat4) {
return sizeof(float4); return sizeof(float4);
else if (type == TypeRGBA) }
else if (type == TypeRGBA) {
return sizeof(float4); return sizeof(float4);
else }
else {
return sizeof(float3); return sizeof(float3);
}
} }
size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const
@ -275,8 +289,9 @@ size_t Attribute::buffer_size(Geometry *geom, AttributePrimitive prim) const
bool Attribute::same_storage(TypeDesc a, TypeDesc b) bool Attribute::same_storage(TypeDesc a, TypeDesc b)
{ {
if (a == b) if (a == b) {
return true; return true;
}
if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector || if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
a == TypeDesc::TypeNormal) a == TypeDesc::TypeNormal)
@ -471,8 +486,9 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
if (attr) { if (attr) {
/* return if same already exists */ /* return if same already exists */
if (attr->type == type && attr->element == element) if (attr->type == type && attr->element == element) {
return attr; return attr;
}
/* overwrite attribute with same name but different type/element */ /* overwrite attribute with same name but different type/element */
remove(name); remove(name);
@ -487,8 +503,9 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
Attribute *AttributeSet::find(ustring name) const Attribute *AttributeSet::find(ustring name) const
{ {
foreach (const Attribute &attr, attributes) foreach (const Attribute &attr, attributes)
if (attr.name == name) if (attr.name == name) {
return (Attribute *)&attr; return (Attribute *)&attr;
}
return NULL; return NULL;
} }
@ -513,8 +530,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
{ {
Attribute *attr = NULL; Attribute *attr = NULL;
if (name == ustring()) if (name == ustring()) {
name = Attribute::standard_name(std); name = Attribute::standard_name(std);
}
if (geometry->geometry_type == Geometry::MESH) { if (geometry->geometry_type == Geometry::MESH) {
switch (std) { switch (std) {
@ -666,8 +684,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
Attribute *AttributeSet::find(AttributeStandard std) const Attribute *AttributeSet::find(AttributeStandard std) const
{ {
foreach (const Attribute &attr, attributes) foreach (const Attribute &attr, attributes)
if (attr.std == std) if (attr.std == std) {
return (Attribute *)&attr; return (Attribute *)&attr;
}
return NULL; return NULL;
} }
@ -710,10 +729,12 @@ void AttributeSet::remove(AttributeStandard std)
Attribute *AttributeSet::find(AttributeRequest &req) Attribute *AttributeSet::find(AttributeRequest &req)
{ {
if (req.std == ATTR_STD_NONE) if (req.std == ATTR_STD_NONE) {
return find(req.name); return find(req.name);
else }
else {
return find(req.std); return find(req.std);
}
} }
void AttributeSet::remove(Attribute *attribute) void AttributeSet::remove(Attribute *attribute)
@ -852,16 +873,18 @@ AttributeRequestSet::~AttributeRequestSet() {}
bool AttributeRequestSet::modified(const AttributeRequestSet &other) bool AttributeRequestSet::modified(const AttributeRequestSet &other)
{ {
if (requests.size() != other.requests.size()) if (requests.size() != other.requests.size()) {
return true; return true;
}
for (size_t i = 0; i < requests.size(); i++) { for (size_t i = 0; i < requests.size(); i++) {
bool found = false; bool found = false;
for (size_t j = 0; j < requests.size() && !found; j++) for (size_t j = 0; j < requests.size() && !found; j++) {
if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) { if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
found = true; found = true;
} }
}
if (!found) { if (!found) {
return true; return true;
@ -885,8 +908,9 @@ void AttributeRequestSet::add(ustring name)
void AttributeRequestSet::add(AttributeStandard std) void AttributeRequestSet::add(AttributeStandard std)
{ {
foreach (AttributeRequest &req, requests) foreach (AttributeRequest &req, requests)
if (req.std == std) if (req.std == std) {
return; return;
}
requests.push_back(AttributeRequest(std)); requests.push_back(AttributeRequest(std));
} }
@ -894,11 +918,13 @@ void AttributeRequestSet::add(AttributeStandard std)
void AttributeRequestSet::add(AttributeRequestSet &reqs) void AttributeRequestSet::add(AttributeRequestSet &reqs)
{ {
foreach (AttributeRequest &req, reqs.requests) { foreach (AttributeRequest &req, reqs.requests) {
if (req.std == ATTR_STD_NONE) if (req.std == ATTR_STD_NONE) {
add(req.name); add(req.name);
else }
else {
add(req.std); add(req.std);
} }
}
} }
void AttributeRequestSet::add_standard(ustring name) void AttributeRequestSet::add_standard(ustring name)
@ -920,8 +946,9 @@ void AttributeRequestSet::add_standard(ustring name)
bool AttributeRequestSet::find(ustring name) bool AttributeRequestSet::find(ustring name)
{ {
foreach (AttributeRequest &req, requests) foreach (AttributeRequest &req, requests)
if (req.name == name) if (req.name == name) {
return true; return true;
}
return false; return false;
} }
@ -929,8 +956,9 @@ bool AttributeRequestSet::find(ustring name)
bool AttributeRequestSet::find(AttributeStandard std) bool AttributeRequestSet::find(AttributeStandard std)
{ {
foreach (AttributeRequest &req, requests) foreach (AttributeRequest &req, requests)
if (req.std == std) if (req.std == std) {
return true; return true;
}
return false; return false;
} }

@ -51,8 +51,9 @@ Background::~Background()
void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene) void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{ {
if (!is_modified()) if (!is_modified()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -80,10 +81,12 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
kbackground->transparent_roughness_squared_threshold = -1.0f; kbackground->transparent_roughness_squared_threshold = -1.0f;
} }
if (bg_shader->has_volume) if (bg_shader->has_volume) {
kbackground->volume_shader = kbackground->surface_shader; kbackground->volume_shader = kbackground->surface_shader;
else }
else {
kbackground->volume_shader = SHADER_NONE; kbackground->volume_shader = SHADER_NONE;
}
kbackground->volume_step_size = volume_step_size * scene->integrator->get_volume_step_rate(); kbackground->volume_step_size = volume_step_size * scene->integrator->get_volume_step_rate();
@ -93,17 +96,22 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
} }
/* Background present, check visibilities */ /* Background present, check visibilities */
else { else {
if (!(visibility & PATH_RAY_DIFFUSE)) if (!(visibility & PATH_RAY_DIFFUSE)) {
kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE; kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
if (!(visibility & PATH_RAY_GLOSSY)) }
if (!(visibility & PATH_RAY_GLOSSY)) {
kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY; kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
if (!(visibility & PATH_RAY_TRANSMIT)) }
if (!(visibility & PATH_RAY_TRANSMIT)) {
kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT; kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
if (!(visibility & PATH_RAY_VOLUME_SCATTER)) }
if (!(visibility & PATH_RAY_VOLUME_SCATTER)) {
kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER; kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
if (!(visibility & PATH_RAY_CAMERA)) }
if (!(visibility & PATH_RAY_CAMERA)) {
kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA; kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
} }
}
/* Light group. */ /* Light group. */
auto it = scene->lightgroups.find(lightgroup); auto it = scene->lightgroups.find(lightgroup);

@ -51,8 +51,9 @@ void BakeManager::device_update(Device * /*device*/,
Scene *scene, Scene *scene,
Progress & /* progress */) Progress & /* progress */)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
KernelBake *kbake = &dscene->data.bake; KernelBake *kbake = &dscene->data.bake;
memset(kbake, 0, sizeof(*kbake)); memset(kbake, 0, sizeof(*kbake));

@ -227,8 +227,9 @@ void Camera::update(Scene *scene)
need_device_update = true; need_device_update = true;
} }
if (!is_modified()) if (!is_modified()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -254,12 +255,15 @@ void Camera::update(Scene *scene)
/* Screen to camera. */ /* Screen to camera. */
ProjectionTransform cameratoscreen; ProjectionTransform cameratoscreen;
if (camera_type == CAMERA_PERSPECTIVE) if (camera_type == CAMERA_PERSPECTIVE) {
cameratoscreen = projection_perspective(fov, nearclip, farclip); cameratoscreen = projection_perspective(fov, nearclip, farclip);
else if (camera_type == CAMERA_ORTHOGRAPHIC) }
else if (camera_type == CAMERA_ORTHOGRAPHIC) {
cameratoscreen = projection_orthographic(nearclip, farclip); cameratoscreen = projection_orthographic(nearclip, farclip);
else }
else {
cameratoscreen = projection_identity(); cameratoscreen = projection_identity();
}
ProjectionTransform screentocamera = projection_inverse(cameratoscreen); ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
@ -474,8 +478,9 @@ void Camera::device_update(Device * /* device */, DeviceScene *dscene, Scene *sc
{ {
update(scene); update(scene);
if (!need_device_update) if (!need_device_update) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {

@ -136,8 +136,9 @@ void Film::add_default(Scene *scene)
void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{ {
if (!is_modified()) if (!is_modified()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {

@ -76,8 +76,9 @@ Geometry::~Geometry()
void Geometry::clear(bool preserve_shaders) void Geometry::clear(bool preserve_shaders)
{ {
if (!preserve_shaders) if (!preserve_shaders) {
used_shaders.clear(); used_shaders.clear();
}
transform_applied = false; transform_applied = false;
transform_negative_scaled = false; transform_negative_scaled = false;
@ -707,8 +708,9 @@ void GeometryManager::device_update(Device *device,
Scene *scene, Scene *scene,
Progress &progress) Progress &progress)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
VLOG_INFO << "Total " << scene->geometry.size() << " meshes."; VLOG_INFO << "Total " << scene->geometry.size() << " meshes.";
@ -787,11 +789,13 @@ void GeometryManager::device_update(Device *device,
Mesh *mesh = static_cast<Mesh *>(geom); Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->need_tesselation()) { if (mesh->need_tesselation()) {
string msg = "Tessellating "; string msg = "Tessellating ";
if (mesh->name == "") if (mesh->name == "") {
msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed); msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
else }
else {
msg += string_printf( msg += string_printf(
"%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed); "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
}
progress.set_status("Updating Mesh", msg); progress.set_status("Updating Mesh", msg);

@ -35,31 +35,36 @@ CCL_NAMESPACE_BEGIN
bool Geometry::need_attribute(Scene *scene, AttributeStandard std) bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
{ {
if (std == ATTR_STD_NONE) if (std == ATTR_STD_NONE) {
return false; return false;
}
if (scene->need_global_attribute(std)) if (scene->need_global_attribute(std)) {
return true; return true;
}
foreach (Node *node, used_shaders) { foreach (Node *node, used_shaders) {
Shader *shader = static_cast<Shader *>(node); Shader *shader = static_cast<Shader *>(node);
if (shader->attributes.find(std)) if (shader->attributes.find(std)) {
return true; return true;
} }
}
return false; return false;
} }
bool Geometry::need_attribute(Scene * /*scene*/, ustring name) bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
{ {
if (name == ustring()) if (name == ustring()) {
return false; return false;
}
foreach (Node *node, used_shaders) { foreach (Node *node, used_shaders) {
Shader *shader = static_cast<Shader *>(node); Shader *shader = static_cast<Shader *>(node);
if (shader->attributes.find(name)) if (shader->attributes.find(name)) {
return true; return true;
} }
}
return false; return false;
} }
@ -98,18 +103,24 @@ static void emit_attribute_map_entry(AttributeMap *attr_map,
attr_map[index].element = desc.element; attr_map[index].element = desc.element;
attr_map[index].offset = as_uint(desc.offset); attr_map[index].offset = as_uint(desc.offset);
if (type == TypeDesc::TypeFloat) if (type == TypeDesc::TypeFloat) {
attr_map[index].type = NODE_ATTR_FLOAT; attr_map[index].type = NODE_ATTR_FLOAT;
else if (type == TypeDesc::TypeMatrix) }
else if (type == TypeDesc::TypeMatrix) {
attr_map[index].type = NODE_ATTR_MATRIX; attr_map[index].type = NODE_ATTR_MATRIX;
else if (type == TypeFloat2) }
else if (type == TypeFloat2) {
attr_map[index].type = NODE_ATTR_FLOAT2; attr_map[index].type = NODE_ATTR_FLOAT2;
else if (type == TypeFloat4) }
else if (type == TypeFloat4) {
attr_map[index].type = NODE_ATTR_FLOAT4; attr_map[index].type = NODE_ATTR_FLOAT4;
else if (type == TypeRGBA) }
else if (type == TypeRGBA) {
attr_map[index].type = NODE_ATTR_RGBA; attr_map[index].type = NODE_ATTR_RGBA;
else }
else {
attr_map[index].type = NODE_ATTR_FLOAT3; attr_map[index].type = NODE_ATTR_FLOAT3;
}
attr_map[index].flags = desc.flags; attr_map[index].flags = desc.flags;
} }
@ -189,8 +200,9 @@ void GeometryManager::update_svm_attributes(Device *,
} }
} }
if (attr_map_size == 0) if (attr_map_size == 0) {
return; return;
}
if (!dscene->attributes_map.need_realloc()) { if (!dscene->attributes_map.need_realloc()) {
return; return;
@ -209,10 +221,12 @@ void GeometryManager::update_svm_attributes(Device *,
foreach (AttributeRequest &req, attributes.requests) { foreach (AttributeRequest &req, attributes.requests) {
uint64_t id; uint64_t id;
if (req.std == ATTR_STD_NONE) if (req.std == ATTR_STD_NONE) {
id = scene->shader_manager->get_attribute_id(req.name); id = scene->shader_manager->get_attribute_id(req.name);
else }
else {
id = scene->shader_manager->get_attribute_id(req.std); id = scene->shader_manager->get_attribute_id(req.std);
}
emit_attribute_mapping(attr_map, index, id, req, geom); emit_attribute_mapping(attr_map, index, id, req, geom);
index += ATTR_PRIM_TYPES; index += ATTR_PRIM_TYPES;
@ -240,10 +254,12 @@ void GeometryManager::update_svm_attributes(Device *,
foreach (AttributeRequest &req, attributes.requests) { foreach (AttributeRequest &req, attributes.requests) {
uint64_t id; uint64_t id;
if (req.std == ATTR_STD_NONE) if (req.std == ATTR_STD_NONE) {
id = scene->shader_manager->get_attribute_id(req.name); id = scene->shader_manager->get_attribute_id(req.name);
else }
else {
id = scene->shader_manager->get_attribute_id(req.std); id = scene->shader_manager->get_attribute_id(req.std);
}
emit_attribute_mapping(attr_map, index, id, req, object->geometry); emit_attribute_mapping(attr_map, index, id, req, object->geometry);
index += ATTR_PRIM_TYPES; index += ATTR_PRIM_TYPES;
@ -378,39 +394,50 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
/* Indices for subdivided attributes are retrieved /* Indices for subdivided attributes are retrieved
* from patch table so no need for correction here. */ * from patch table so no need for correction here. */
} }
else if (element == ATTR_ELEMENT_VERTEX) else if (element == ATTR_ELEMENT_VERTEX) {
offset -= mesh->vert_offset; offset -= mesh->vert_offset;
else if (element == ATTR_ELEMENT_VERTEX_MOTION) }
else if (element == ATTR_ELEMENT_VERTEX_MOTION) {
offset -= mesh->vert_offset; offset -= mesh->vert_offset;
}
else if (element == ATTR_ELEMENT_FACE) { else if (element == ATTR_ELEMENT_FACE) {
if (prim == ATTR_PRIM_GEOMETRY) if (prim == ATTR_PRIM_GEOMETRY) {
offset -= mesh->prim_offset; offset -= mesh->prim_offset;
else }
else {
offset -= mesh->face_offset; offset -= mesh->face_offset;
} }
}
else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) { else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
if (prim == ATTR_PRIM_GEOMETRY) if (prim == ATTR_PRIM_GEOMETRY) {
offset -= 3 * mesh->prim_offset; offset -= 3 * mesh->prim_offset;
else }
else {
offset -= mesh->corner_offset; offset -= mesh->corner_offset;
} }
} }
}
else if (geom->is_hair()) { else if (geom->is_hair()) {
Hair *hair = static_cast<Hair *>(geom); Hair *hair = static_cast<Hair *>(geom);
if (element == ATTR_ELEMENT_CURVE) if (element == ATTR_ELEMENT_CURVE) {
offset -= hair->prim_offset; offset -= hair->prim_offset;
else if (element == ATTR_ELEMENT_CURVE_KEY) }
offset -= hair->curve_key_offset; else if (element == ATTR_ELEMENT_CURVE_KEY) {
else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
offset -= hair->curve_key_offset; offset -= hair->curve_key_offset;
} }
else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
offset -= hair->curve_key_offset;
}
}
else if (geom->is_pointcloud()) { else if (geom->is_pointcloud()) {
if (element == ATTR_ELEMENT_VERTEX) if (element == ATTR_ELEMENT_VERTEX) {
offset -= geom->prim_offset; offset -= geom->prim_offset;
else if (element == ATTR_ELEMENT_VERTEX_MOTION) }
else if (element == ATTR_ELEMENT_VERTEX_MOTION) {
offset -= geom->prim_offset; offset -= geom->prim_offset;
} }
} }
}
else { else {
/* attribute not found */ /* attribute not found */
desc.element = ATTR_ELEMENT_NONE; desc.element = ATTR_ELEMENT_NONE;
@ -652,10 +679,11 @@ void GeometryManager::device_update_attributes(Device *device,
req.subd_desc); req.subd_desc);
} }
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
for (size_t i = 0; i < scene->objects.size(); i++) { for (size_t i = 0; i < scene->objects.size(); i++) {
Object *object = scene->objects[i]; Object *object = scene->objects[i];
@ -689,19 +717,22 @@ void GeometryManager::device_update_attributes(Device *device,
req.subd_type = req.type; req.subd_type = req.type;
req.subd_desc = req.desc; req.subd_desc = req.desc;
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
/* create attribute lookup maps */ /* create attribute lookup maps */
if (scene->shader_manager->use_osl()) if (scene->shader_manager->use_osl()) {
update_osl_globals(device, scene); update_osl_globals(device, scene);
}
update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes); update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* copy to device */ /* copy to device */
progress.set_status("Updating Mesh", "Copying Attributes to device"); progress.set_status("Updating Mesh", "Copying Attributes to device");
@ -712,8 +743,9 @@ void GeometryManager::device_update_attributes(Device *device,
dscene->attributes_float4.copy_to_device_if_modified(); dscene->attributes_float4.copy_to_device_if_modified();
dscene->attributes_uchar4.copy_to_device_if_modified(); dscene->attributes_uchar4.copy_to_device_if_modified();
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* After mesh attributes and patch tables have been copied to device memory, /* After mesh attributes and patch tables have been copied to device memory,
* we need to update offsets in the objects. */ * we need to update offsets in the objects. */

@ -40,8 +40,9 @@ void Geometry::compute_bvh(Device *device,
size_t n, size_t n,
size_t total) size_t total)
{ {
if (progress->get_cancel()) if (progress->get_cancel()) {
return; return;
}
compute_bounds(); compute_bounds();
@ -49,10 +50,12 @@ void Geometry::compute_bvh(Device *device,
params->bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features)); params->bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
if (need_build_bvh(bvh_layout)) { if (need_build_bvh(bvh_layout)) {
string msg = "Updating Geometry BVH "; string msg = "Updating Geometry BVH ";
if (name.empty()) if (name.empty()) {
msg += string_printf("%u/%u", (uint)(n + 1), (uint)total); msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
else }
else {
msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total); msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
}
Object object; Object object;

@ -125,10 +125,11 @@ void GeometryManager::device_update_mesh(Device *,
&tri_patch_uv[mesh->vert_offset]); &tri_patch_uv[mesh->vert_offset]);
} }
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
/* vertex coordinates */ /* vertex coordinates */
progress.set_status("Updating Mesh", "Copying Mesh to device"); progress.set_status("Updating Mesh", "Copying Mesh to device");
@ -169,10 +170,11 @@ void GeometryManager::device_update_mesh(Device *,
&curve_keys[hair->curve_key_offset], &curve_keys[hair->curve_key_offset],
&curves[hair->prim_offset], &curves[hair->prim_offset],
&curve_segments[hair->curve_segment_offset]); &curve_segments[hair->curve_segment_offset]);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
dscene->curve_keys.copy_to_device_if_modified(); dscene->curve_keys.copy_to_device_if_modified();
dscene->curves.copy_to_device_if_modified(); dscene->curves.copy_to_device_if_modified();
@ -190,10 +192,11 @@ void GeometryManager::device_update_mesh(Device *,
PointCloud *pointcloud = static_cast<PointCloud *>(geom); PointCloud *pointcloud = static_cast<PointCloud *>(geom);
pointcloud->pack( pointcloud->pack(
scene, &points[pointcloud->prim_offset], &points_shader[pointcloud->prim_offset]); scene, &points[pointcloud->prim_offset], &points_shader[pointcloud->prim_offset]);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
dscene->points.copy_to_device(); dscene->points.copy_to_device();
dscene->points_shader.copy_to_device(); dscene->points_shader.copy_to_device();
@ -214,10 +217,11 @@ void GeometryManager::device_update_mesh(Device *,
mesh->patch_table_offset); mesh->patch_table_offset);
} }
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
dscene->patches.copy_to_device(); dscene->patches.copy_to_device();
} }

@ -398,8 +398,9 @@ void Hair::compute_bounds()
size_t curve_keys_size = curve_keys.size(); size_t curve_keys_size = curve_keys.size();
if (curve_keys_size > 0) { if (curve_keys_size > 0) {
for (size_t i = 0; i < curve_keys_size; i++) for (size_t i = 0; i < curve_keys_size; i++) {
bnds.grow(curve_keys[i], curve_radius[i]); bnds.grow(curve_keys[i], curve_radius[i]);
}
Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (use_motion_blur && curve_attr) { if (use_motion_blur && curve_attr) {
@ -408,16 +409,18 @@ void Hair::compute_bounds()
// interchangeable with float3 // interchangeable with float3
float4 *key_steps = curve_attr->data_float4(); float4 *key_steps = curve_attr->data_float4();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow(float4_to_float3(key_steps[i])); bnds.grow(float4_to_float3(key_steps[i]));
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
bnds = BoundBox::empty; bnds = BoundBox::empty;
/* skip nan or inf coordinates */ /* skip nan or inf coordinates */
for (size_t i = 0; i < curve_keys_size; i++) for (size_t i = 0; i < curve_keys_size; i++) {
bnds.grow_safe(curve_keys[i], curve_radius[i]); bnds.grow_safe(curve_keys[i], curve_radius[i]);
}
if (use_motion_blur && curve_attr) { if (use_motion_blur && curve_attr) {
size_t steps_size = curve_keys.size() * (motion_steps - 1); size_t steps_size = curve_keys.size() * (motion_steps - 1);
@ -425,11 +428,12 @@ void Hair::compute_bounds()
// interchangeable with float4 // interchangeable with float4
float4 *key_steps = curve_attr->data_float4(); float4 *key_steps = curve_attr->data_float4();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow_safe(float4_to_float3(key_steps[i])); bnds.grow_safe(float4_to_float3(key_steps[i]));
} }
} }
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
/* empty mesh */ /* empty mesh */
@ -492,9 +496,10 @@ void Hair::pack_curves(Scene *scene,
float3 *keys_ptr = curve_keys.data(); float3 *keys_ptr = curve_keys.data();
float *radius_ptr = curve_radius.data(); float *radius_ptr = curve_radius.data();
for (size_t i = 0; i < curve_keys_size; i++) for (size_t i = 0; i < curve_keys_size; i++) {
curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]); curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
} }
}
/* pack curve segments */ /* pack curve segments */
const PrimitiveType type = primitive_type(); const PrimitiveType type = primitive_type();

@ -330,8 +330,9 @@ ImageManager::ImageManager(const DeviceInfo &info)
ImageManager::~ImageManager() ImageManager::~ImageManager()
{ {
for (size_t slot = 0; slot < images.size(); slot++) for (size_t slot = 0; slot < images.size(); slot++) {
assert(!images[slot]); assert(!images[slot]);
}
} }
void ImageManager::set_osl_texture_system(void *texture_system) void ImageManager::set_osl_texture_system(void *texture_system)
@ -346,10 +347,11 @@ bool ImageManager::set_animation_frame_update(int frame)
animation_frame = frame; animation_frame = frame;
for (size_t slot = 0; slot < images.size(); slot++) { for (size_t slot = 0; slot < images.size(); slot++) {
if (images[slot] && images[slot]->params.animated) if (images[slot] && images[slot]->params.animated) {
return true; return true;
} }
} }
}
return false; return false;
} }
@ -468,9 +470,10 @@ size_t ImageManager::add_image_slot(ImageLoader *loader,
/* Find free slot. */ /* Find free slot. */
for (slot = 0; slot < images.size(); slot++) { for (slot = 0; slot < images.size(); slot++) {
if (!images[slot]) if (!images[slot]) {
break; break;
} }
}
if (slot == images.size()) { if (slot == images.size()) {
images.resize(images.size() + 1); images.resize(images.size() + 1);
@ -514,8 +517,9 @@ void ImageManager::remove_image_user(size_t slot)
/* don't remove immediately, rather do it all together later on. one of /* don't remove immediately, rather do it all together later on. one of
* the reasons for this is that on shader changes we add and remove nodes * the reasons for this is that on shader changes we add and remove nodes
* that use them, but we do not want to reload the image all the time. */ * that use them, but we do not want to reload the image all the time. */
if (image->users == 0) if (image->users == 0) {
need_update_ = true; need_update_ = true;
}
} }
static bool image_associate_alpha(ImageManager::Image *img) static bool image_associate_alpha(ImageManager::Image *img)

@ -158,8 +158,9 @@ Integrator::~Integrator() {}
void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene) void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{ {
if (!is_modified()) if (!is_modified()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {

@ -293,8 +293,9 @@ void LightManager::device_update_distribution(Device *,
size_t num_triangles = 0; size_t num_triangles = 0;
foreach (Object *object, scene->objects) { foreach (Object *object, scene->objects) {
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
if (!object->usable_as_light()) { if (!object->usable_as_light()) {
continue; continue;
@ -338,8 +339,9 @@ void LightManager::device_update_distribution(Device *,
int j = 0; int j = 0;
foreach (Object *object, scene->objects) { foreach (Object *object, scene->objects) {
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
if (!object->usable_as_light()) { if (!object->usable_as_light()) {
j++; j++;
@ -414,8 +416,9 @@ void LightManager::device_update_distribution(Device *,
if (num_lights > 0) { if (num_lights > 0) {
float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f; float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
foreach (Light *light, scene->lights) { foreach (Light *light, scene->lights) {
if (!light->is_enabled) if (!light->is_enabled) {
continue; continue;
}
distribution[offset].totarea = totarea; distribution[offset].totarea = totarea;
distribution[offset].prim = ~light_index; distribution[offset].prim = ~light_index;
@ -435,13 +438,15 @@ void LightManager::device_update_distribution(Device *,
distribution[num_distribution].mesh_light.shader_flag = 0; distribution[num_distribution].mesh_light.shader_flag = 0;
if (totarea > 0.0f) { if (totarea > 0.0f) {
for (size_t i = 0; i < num_distribution; i++) for (size_t i = 0; i < num_distribution; i++) {
distribution[i].totarea /= totarea; distribution[i].totarea /= totarea;
}
distribution[num_distribution].totarea = 1.0f; distribution[num_distribution].totarea = 1.0f;
} }
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* Update integrator state. */ /* Update integrator state. */
kintegrator->use_direct_light = (totarea > 0.0f); kintegrator->use_direct_light = (totarea > 0.0f);
@ -1048,8 +1053,9 @@ void LightManager::device_update_background(Device *device,
vector<float3> pixels; vector<float3> pixels;
shade_background_pixels(device, dscene, res.x, res.y, pixels, progress); shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* build row distributions and column distribution for the infinite area environment light */ /* build row distributions and column distribution for the infinite area environment light */
int cdf_width = res.x + 1; int cdf_width = res.x + 1;
@ -1090,9 +1096,11 @@ void LightManager::device_update_background(Device *device,
background_light->set_average_radiance(map_average_radiance); background_light->set_average_radiance(map_average_radiance);
} }
if (cdf_total > 0.0f) if (cdf_total > 0.0f) {
for (int i = 1; i < res.y; i++) for (int i = 1; i < res.y; i++) {
marg_cdf[i].y /= cdf_total; marg_cdf[i].y /= cdf_total;
}
}
marg_cdf[res.y].y = 1.0f; marg_cdf[res.y].y = 1.0f;
@ -1199,8 +1207,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
int shader_id = scene->shader_manager->get_shader_id(shader); int shader_id = scene->shader_manager->get_shader_id(shader);
float random = (float)light->random_id * (1.0f / (float)0xFFFFFFFF); float random = (float)light->random_id * (1.0f / (float)0xFFFFFFFF);
if (!light->cast_shadow) if (!light->cast_shadow) {
shader_id &= ~SHADER_CAST_SHADOW; shader_id &= ~SHADER_CAST_SHADOW;
}
if (!light->use_camera) { if (!light->use_camera) {
shader_id |= SHADER_EXCLUDE_CAMERA; shader_id |= SHADER_EXCLUDE_CAMERA;
@ -1237,8 +1246,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
/* Convert radiant flux to radiance or radiant intensity. */ /* Convert radiant flux to radiance or radiant intensity. */
float eval_fac = invarea * M_1_PI_F; float eval_fac = invarea * M_1_PI_F;
if (light->use_mis && radius > 0.0f) if (light->use_mis && radius > 0.0f) {
shader_id |= SHADER_USE_MIS; shader_id |= SHADER_USE_MIS;
}
klights[light_index].co = light->get_co(); klights[light_index].co = light->get_co();
klights[light_index].spot.radius = radius; klights[light_index].spot.radius = radius;
@ -1318,8 +1328,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
float3 dir = safe_normalize(light->get_dir()); float3 dir = safe_normalize(light->get_dir());
if (light->use_mis && area != 0.0f) if (light->use_mis && area != 0.0f) {
shader_id |= SHADER_USE_MIS; shader_id |= SHADER_USE_MIS;
}
klights[light_index].co = light->get_co(); klights[light_index].co = light->get_co();
klights[light_index].area.axis_u = axis_u; klights[light_index].area.axis_u = axis_u;
@ -1384,8 +1395,9 @@ void LightManager::device_update(Device *device,
Scene *scene, Scene *scene,
Progress &progress) Progress &progress)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -1401,26 +1413,31 @@ void LightManager::device_update(Device *device,
device_free(device, dscene, need_update_background); device_free(device, dscene, need_update_background);
device_update_lights(device, dscene, scene); device_update_lights(device, dscene, scene);
if (progress.get_cancel()) if (progress.get_cancel()) {
return;
if (need_update_background) {
device_update_background(device, dscene, scene, progress);
if (progress.get_cancel())
return; return;
} }
device_update_distribution(device, dscene, scene, progress); if (need_update_background) {
if (progress.get_cancel()) device_update_background(device, dscene, scene, progress);
if (progress.get_cancel()) {
return; return;
}
}
device_update_distribution(device, dscene, scene, progress);
if (progress.get_cancel()) {
return;
}
device_update_tree(device, dscene, scene, progress); device_update_tree(device, dscene, scene, progress);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
device_update_ies(dscene); device_update_ies(dscene);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
update_flags = UPDATE_NONE; update_flags = UPDATE_NONE;
need_update_background = false; need_update_background = false;

@ -429,9 +429,10 @@ void Mesh::copy_center_to_motion_step(const int motion_step)
size_t numverts = verts.size(); size_t numverts = verts.size();
memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts); memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
if (attr_mN) if (attr_mN) {
memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts); memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
} }
}
} }
void Mesh::get_uv_tiles(ustring map, unordered_set<int> &tiles) void Mesh::get_uv_tiles(ustring map, unordered_set<int> &tiles)
@ -461,34 +462,38 @@ void Mesh::compute_bounds()
size_t verts_size = verts.size(); size_t verts_size = verts.size();
if (verts_size > 0) { if (verts_size > 0) {
for (size_t i = 0; i < verts_size; i++) for (size_t i = 0; i < verts_size; i++) {
bnds.grow(verts[i]); bnds.grow(verts[i]);
}
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (use_motion_blur && attr) { if (use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1); size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3(); float3 *vert_steps = attr->data_float3();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow(vert_steps[i]); bnds.grow(vert_steps[i]);
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
bnds = BoundBox::empty; bnds = BoundBox::empty;
/* skip nan or inf coordinates */ /* skip nan or inf coordinates */
for (size_t i = 0; i < verts_size; i++) for (size_t i = 0; i < verts_size; i++) {
bnds.grow_safe(verts[i]); bnds.grow_safe(verts[i]);
}
if (use_motion_blur && attr) { if (use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1); size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3(); float3 *vert_steps = attr->data_float3();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow_safe(vert_steps[i]); bnds.grow_safe(vert_steps[i]);
} }
} }
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
/* empty mesh */ /* empty mesh */
@ -503,8 +508,9 @@ void Mesh::apply_transform(const Transform &tfm, const bool apply_to_motion)
transform_normal = transform_transposed_inverse(tfm); transform_normal = transform_transposed_inverse(tfm);
/* apply to mesh vertices */ /* apply to mesh vertices */
for (size_t i = 0; i < verts.size(); i++) for (size_t i = 0; i < verts.size(); i++) {
verts[i] = transform_point(&tfm, verts[i]); verts[i] = transform_point(&tfm, verts[i]);
}
tag_verts_modified(); tag_verts_modified();
@ -515,9 +521,10 @@ void Mesh::apply_transform(const Transform &tfm, const bool apply_to_motion)
size_t steps_size = verts.size() * (motion_steps - 1); size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3(); float3 *vert_steps = attr->data_float3();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
vert_steps[i] = transform_point(&tfm, vert_steps[i]); vert_steps[i] = transform_point(&tfm, vert_steps[i]);
} }
}
Attribute *attr_N = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); Attribute *attr_N = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
@ -526,17 +533,19 @@ void Mesh::apply_transform(const Transform &tfm, const bool apply_to_motion)
size_t steps_size = verts.size() * (motion_steps - 1); size_t steps_size = verts.size() * (motion_steps - 1);
float3 *normal_steps = attr_N->data_float3(); float3 *normal_steps = attr_N->data_float3();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i])); normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
} }
} }
}
} }
void Mesh::add_face_normals() void Mesh::add_face_normals()
{ {
/* don't compute if already there */ /* don't compute if already there */
if (attributes.find(ATTR_STD_FACE_NORMAL)) if (attributes.find(ATTR_STD_FACE_NORMAL)) {
return; return;
}
/* get attributes */ /* get attributes */
Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL); Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
@ -557,9 +566,10 @@ void Mesh::add_face_normals()
if (transform_applied) { if (transform_applied) {
Transform ntfm = transform_inverse(transform_normal); Transform ntfm = transform_inverse(transform_normal);
for (size_t i = 0; i < triangles_size; i++) for (size_t i = 0; i < triangles_size; i++) {
fN[i] = normalize(transform_direction(&ntfm, fN[i])); fN[i] = normalize(transform_direction(&ntfm, fN[i]));
} }
}
} }
void Mesh::add_vertex_normals() void Mesh::add_vertex_normals()

@ -27,8 +27,9 @@ static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
float3 norm = cross(v1 - v0, v2 - v0); float3 norm = cross(v1 - v0, v2 - v0);
float normlen = len(norm); float normlen = len(norm);
if (normlen == 0.0f) if (normlen == 0.0f) {
return make_float3(1.0f, 0.0f, 0.0f); return make_float3(1.0f, 0.0f, 0.0f);
}
return norm / normlen; return norm / normlen;
} }
@ -62,8 +63,9 @@ static int fill_shader_input(const Scene *scene,
} }
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
if (done[t.v[j]]) if (done[t.v[j]]) {
continue; continue;
}
done[t.v[j]] = true; done[t.v[j]] = true;
@ -312,8 +314,9 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
} }
vN[vert] = normalize(vN[vert]); vN[vert] = normalize(vN[vert]);
if (flip) if (flip) {
vN[vert] = -vN[vert]; vN[vert] = -vN[vert];
}
done[vert] = true; done[vert] = true;
} }
@ -382,8 +385,9 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
} }
mN[vert] = normalize(mN[vert]); mN[vert] = normalize(mN[vert]);
if (flip) if (flip) {
mN[vert] = -mN[vert]; mN[vert] = -mN[vert];
}
done[vert] = true; done[vert] = true;
} }

@ -188,15 +188,17 @@ void Object::compute_bounds(bool motion_blur)
void Object::apply_transform(bool apply_to_motion) void Object::apply_transform(bool apply_to_motion)
{ {
if (!geometry || tfm == transform_identity()) if (!geometry || tfm == transform_identity()) {
return; return;
}
geometry->apply_transform(tfm, apply_to_motion); geometry->apply_transform(tfm, apply_to_motion);
/* we keep normals pointing in same direction on negative scale, notify /* we keep normals pointing in same direction on negative scale, notify
* geometry about this in it (re)calculates normals */ * geometry about this in it (re)calculates normals */
if (transform_negative_scale(tfm)) if (transform_negative_scale(tfm)) {
geometry->transform_negative_scaled = true; geometry->transform_negative_scaled = true;
}
if (bounds.valid()) { if (bounds.valid()) {
geometry->compute_bounds(); geometry->compute_bounds();
@ -235,10 +237,11 @@ void Object::tag_update(Scene *scene)
foreach (Node *node, geometry->get_used_shaders()) { foreach (Node *node, geometry->get_used_shaders()) {
Shader *shader = static_cast<Shader *>(node); Shader *shader = static_cast<Shader *>(node);
if (shader->emission_sampling != EMISSION_SAMPLING_NONE) if (shader->emission_sampling != EMISSION_SAMPLING_NONE) {
scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED); scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED);
} }
} }
}
scene->camera->need_flags_update = true; scene->camera->need_flags_update = true;
scene->object_manager->tag_update(scene, flag); scene->object_manager->tag_update(scene, flag);
@ -753,8 +756,9 @@ void ObjectManager::device_update(Device *device,
Scene *scene, Scene *scene,
Progress &progress) Progress &progress)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
if (update_flags & (OBJECT_ADDED | OBJECT_REMOVED)) { if (update_flags & (OBJECT_ADDED | OBJECT_REMOVED)) {
dscene->objects.tag_realloc(); dscene->objects.tag_realloc();
@ -776,8 +780,9 @@ void ObjectManager::device_update(Device *device,
device_free(device, dscene, false); device_free(device, dscene, false);
if (scene->objects.size() == 0) if (scene->objects.size() == 0) {
return; return;
}
{ {
/* Assign object IDs. */ /* Assign object IDs. */
@ -816,8 +821,9 @@ void ObjectManager::device_update(Device *device,
device_update_transforms(dscene, scene, progress); device_update_transforms(dscene, scene, progress);
} }
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
/* prepare for static BVH building */ /* prepare for static BVH building */
/* todo: do before to support getting object level coords? */ /* todo: do before to support getting object level coords? */
@ -841,8 +847,9 @@ void ObjectManager::device_update(Device *device,
void ObjectManager::device_update_flags( void ObjectManager::device_update_flags(
Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid) Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid)
{ {
if (!need_update() && !need_flags_update) if (!need_update() && !need_flags_update) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -853,8 +860,9 @@ void ObjectManager::device_update_flags(
update_flags = UPDATE_NONE; update_flags = UPDATE_NONE;
need_flags_update = false; need_flags_update = false;
if (scene->objects.size() == 0) if (scene->objects.size() == 0) {
return; return;
}
/* Object info flag. */ /* Object info flag. */
uint *object_flag = dscene->object_flag.data(); uint *object_flag = dscene->object_flag.data();
@ -997,14 +1005,17 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
foreach (Object *object, scene->objects) { foreach (Object *object, scene->objects) {
map<Geometry *, int>::iterator it = geometry_users.find(object->geometry); map<Geometry *, int>::iterator it = geometry_users.find(object->geometry);
if (it == geometry_users.end()) if (it == geometry_users.end()) {
geometry_users[object->geometry] = 1; geometry_users[object->geometry] = 1;
else }
else {
it->second++; it->second++;
} }
}
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
uint *object_flag = dscene->object_flag.data(); uint *object_flag = dscene->object_flag.data();
@ -1036,9 +1047,10 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
object->apply_transform(apply_to_motion); object->apply_transform(apply_to_motion);
geom->transform_applied = true; geom->transform_applied = true;
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
}
object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED; object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
} }

@ -51,8 +51,9 @@ void ParticleSystemManager::device_update_particles(Device *,
* adds one dummy particle at the beginning to avoid invalid lookups, * adds one dummy particle at the beginning to avoid invalid lookups,
* in case a shader uses particle info without actual particle data. */ * in case a shader uses particle info without actual particle data. */
int num_particles = 1; int num_particles = 1;
for (size_t j = 0; j < scene->particle_systems.size(); j++) for (size_t j = 0; j < scene->particle_systems.size(); j++) {
num_particles += scene->particle_systems[j]->particles.size(); num_particles += scene->particle_systems[j]->particles.size();
}
KernelParticle *kparticles = dscene->particles.alloc(num_particles); KernelParticle *kparticles = dscene->particles.alloc(num_particles);
@ -78,10 +79,11 @@ void ParticleSystemManager::device_update_particles(Device *,
i++; i++;
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
} }
} }
}
dscene->particles.copy_to_device(); dscene->particles.copy_to_device();
} }
@ -91,8 +93,9 @@ void ParticleSystemManager::device_update(Device *device,
Scene *scene, Scene *scene,
Progress &progress) Progress &progress)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -107,8 +110,9 @@ void ParticleSystemManager::device_update(Device *device,
progress.set_status("Updating Particle Systems", "Copying Particles to device"); progress.set_status("Updating Particle Systems", "Copying Particles to device");
device_update_particles(device, dscene, scene, progress); device_update_particles(device, dscene, scene, progress);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
need_update_ = false; need_update_ = false;
} }

@ -188,26 +188,29 @@ void PointCloud::compute_bounds()
size_t steps_size = points.size() * (motion_steps - 1); size_t steps_size = points.size() * (motion_steps - 1);
float4 *point_steps = attr->data_float4(); float4 *point_steps = attr->data_float4();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow(float4_to_float3(point_steps[i]), point_steps[i].w); bnds.grow(float4_to_float3(point_steps[i]), point_steps[i].w);
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
bnds = BoundBox::empty; bnds = BoundBox::empty;
/* skip nan or inf coordinates */ /* skip nan or inf coordinates */
for (size_t i = 0; i < numpoints; i++) for (size_t i = 0; i < numpoints; i++) {
bnds.grow_safe(points[i], radius[i]); bnds.grow_safe(points[i], radius[i]);
}
if (use_motion_blur && attr) { if (use_motion_blur && attr) {
size_t steps_size = points.size() * (motion_steps - 1); size_t steps_size = points.size() * (motion_steps - 1);
float4 *point_steps = attr->data_float4(); float4 *point_steps = attr->data_float4();
for (size_t i = 0; i < steps_size; i++) for (size_t i = 0; i < steps_size; i++) {
bnds.grow_safe(float4_to_float3(point_steps[i]), point_steps[i].w); bnds.grow_safe(float4_to_float3(point_steps[i]), point_steps[i].w);
} }
} }
} }
}
if (!bnds.valid()) { if (!bnds.valid()) {
/* empty mesh */ /* empty mesh */

@ -149,10 +149,12 @@ void Scene::free_memory(bool final)
bake_manager->device_free(device, &dscene); bake_manager->device_free(device, &dscene);
if (final) if (final) {
image_manager->device_free(device); image_manager->device_free(device);
else }
else {
image_manager->device_free_builtin(device); image_manager->device_free_builtin(device);
}
lookup_tables->device_free(device, &dscene); lookup_tables->device_free(device, &dscene);
} }
@ -173,8 +175,9 @@ void Scene::free_memory(bool final)
void Scene::device_update(Device *device_, Progress &progress) void Scene::device_update(Device *device_, Progress &progress)
{ {
if (!device) if (!device) {
device = device_; device = device_;
}
bool print_stats = need_data_update(); bool print_stats = need_data_update();
@ -213,108 +216,126 @@ void Scene::device_update(Device *device_, Progress &progress)
progress.set_status("Updating Shaders"); progress.set_status("Updating Shaders");
shader_manager->device_update(device, &dscene, this, progress); shader_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
procedural_manager->update(this, progress); procedural_manager->update(this, progress);
if (progress.get_cancel()) if (progress.get_cancel()) {
return; return;
}
progress.set_status("Updating Background"); progress.set_status("Updating Background");
background->device_update(device, &dscene, this); background->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Camera"); progress.set_status("Updating Camera");
camera->device_update(device, &dscene, this); camera->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
geometry_manager->device_update_preprocess(device, this, progress); geometry_manager->device_update_preprocess(device, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Objects"); progress.set_status("Updating Objects");
object_manager->device_update(device, &dscene, this, progress); object_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Particle Systems"); progress.set_status("Updating Particle Systems");
particle_system_manager->device_update(device, &dscene, this, progress); particle_system_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Meshes"); progress.set_status("Updating Meshes");
geometry_manager->device_update(device, &dscene, this, progress); geometry_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Objects Flags"); progress.set_status("Updating Objects Flags");
object_manager->device_update_flags(device, &dscene, this, progress); object_manager->device_update_flags(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Primitive Offsets"); progress.set_status("Updating Primitive Offsets");
object_manager->device_update_prim_offsets(device, &dscene, this); object_manager->device_update_prim_offsets(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Images"); progress.set_status("Updating Images");
image_manager->device_update(device, this, progress); image_manager->device_update(device, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Camera Volume"); progress.set_status("Updating Camera Volume");
camera->device_update_volume(device, &dscene, this); camera->device_update_volume(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Lookup Tables"); progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene, this); lookup_tables->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Lights"); progress.set_status("Updating Lights");
light_manager->device_update(device, &dscene, this, progress); light_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Integrator"); progress.set_status("Updating Integrator");
integrator->device_update(device, &dscene, this); integrator->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Film"); progress.set_status("Updating Film");
film->device_update(device, &dscene, this); film->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Lookup Tables"); progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene, this); lookup_tables->device_update(device, &dscene, this);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
progress.set_status("Updating Baking"); progress.set_status("Updating Baking");
bake_manager->device_update(device, &dscene, this, progress); bake_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error()) if (progress.get_cancel() || device->have_error()) {
return; return;
}
if (device->have_error() == false) { if (device->have_error() == false) {
dscene.data.volume_stack_size = get_volume_stack_size(); dscene.data.volume_stack_size = get_volume_stack_size();
@ -339,30 +360,38 @@ void Scene::device_update(Device *device_, Progress &progress)
Scene::MotionType Scene::need_motion() const Scene::MotionType Scene::need_motion() const
{ {
if (integrator->get_motion_blur()) if (integrator->get_motion_blur()) {
return MOTION_BLUR; return MOTION_BLUR;
else if (Pass::contains(passes, PASS_MOTION)) }
else if (Pass::contains(passes, PASS_MOTION)) {
return MOTION_PASS; return MOTION_PASS;
else }
else {
return MOTION_NONE; return MOTION_NONE;
}
} }
float Scene::motion_shutter_time() float Scene::motion_shutter_time()
{ {
if (need_motion() == Scene::MOTION_PASS) if (need_motion() == Scene::MOTION_PASS) {
return 2.0f; return 2.0f;
else }
else {
return camera->get_shuttertime(); return camera->get_shuttertime();
}
} }
bool Scene::need_global_attribute(AttributeStandard std) bool Scene::need_global_attribute(AttributeStandard std)
{ {
if (std == ATTR_STD_UV) if (std == ATTR_STD_UV) {
return Pass::contains(passes, PASS_UV); return Pass::contains(passes, PASS_UV);
else if (std == ATTR_STD_MOTION_VERTEX_POSITION) }
else if (std == ATTR_STD_MOTION_VERTEX_POSITION) {
return need_motion() != MOTION_NONE; return need_motion() != MOTION_NONE;
else if (std == ATTR_STD_MOTION_VERTEX_NORMAL) }
else if (std == ATTR_STD_MOTION_VERTEX_NORMAL) {
return need_motion() == MOTION_BLUR; return need_motion() == MOTION_BLUR;
}
else if (std == ATTR_STD_VOLUME_VELOCITY || std == ATTR_STD_VOLUME_VELOCITY_X || else if (std == ATTR_STD_VOLUME_VELOCITY || std == ATTR_STD_VOLUME_VELOCITY_X ||
std == ATTR_STD_VOLUME_VELOCITY_Y || std == ATTR_STD_VOLUME_VELOCITY_Z) std == ATTR_STD_VOLUME_VELOCITY_Y || std == ATTR_STD_VOLUME_VELOCITY_Z)
{ {
@ -374,9 +403,11 @@ bool Scene::need_global_attribute(AttributeStandard std)
void Scene::need_global_attributes(AttributeRequestSet &attributes) void Scene::need_global_attributes(AttributeRequestSet &attributes)
{ {
for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
if (need_global_attribute((AttributeStandard)std)) if (need_global_attribute((AttributeStandard)std)) {
attributes.add((AttributeStandard)std); attributes.add((AttributeStandard)std);
}
}
} }
bool Scene::need_update() bool Scene::need_update()
@ -597,8 +628,9 @@ bool Scene::load_kernels(Progress &progress)
log_kernel_features(kernel_features); log_kernel_features(kernel_features);
if (!device->load_kernels(kernel_features)) { if (!device->load_kernels(kernel_features)) {
string message = device->error_message(); string message = device->error_message();
if (message.empty()) if (message.empty()) {
message = "Failed loading render kernel, see console for errors"; message = "Failed loading render kernel, see console for errors";
}
progress.set_error(message); progress.set_error(message);
progress.set_status(message); progress.set_status(message);

@ -323,8 +323,9 @@ void Shader::tag_update(Scene *scene)
/* if the shader previously was emissive, update light distribution, /* if the shader previously was emissive, update light distribution,
* if the new shader is emissive, a light manager update tag will be * if the new shader is emissive, a light manager update tag will be
* done in the shader manager device update. */ * done in the shader manager device update. */
if (emission_sampling != EMISSION_SAMPLING_NONE) if (emission_sampling != EMISSION_SAMPLING_NONE) {
scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED); scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
}
/* Special handle of background MIS light for now: for some reason it /* Special handle of background MIS light for now: for some reason it
* has use_mis set to false. We are quite close to release now, so * has use_mis set to false. We are quite close to release now, so
@ -450,8 +451,9 @@ uint64_t ShaderManager::get_attribute_id(ustring name)
/* get a unique id for each name, for SVM attribute lookup */ /* get a unique id for each name, for SVM attribute lookup */
AttributeIDMap::iterator it = unique_attribute_id.find(name); AttributeIDMap::iterator it = unique_attribute_id.find(name);
if (it != unique_attribute_id.end()) if (it != unique_attribute_id.end()) {
return it->second; return it->second;
}
uint64_t id = ATTR_STD_NUM + unique_attribute_id.size(); uint64_t id = ATTR_STD_NUM + unique_attribute_id.size();
unique_attribute_id[name] = id; unique_attribute_id[name] = id;
@ -469,8 +471,9 @@ int ShaderManager::get_shader_id(Shader *shader, bool smooth)
int id = shader->id; int id = shader->id;
/* smooth flag */ /* smooth flag */
if (smooth) if (smooth) {
id |= SHADER_SMOOTH_NORMAL; id |= SHADER_SMOOTH_NORMAL;
}
/* default flags */ /* default flags */
id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT; id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT;
@ -509,8 +512,9 @@ void ShaderManager::device_update_common(Device * /*device*/,
{ {
dscene->shaders.free(); dscene->shaders.free();
if (scene->shaders.size() == 0) if (scene->shaders.size() == 0) {
return; return;
}
KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size()); KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
bool has_volumes = false; bool has_volumes = false;
@ -529,12 +533,15 @@ void ShaderManager::device_update_common(Device * /*device*/,
flag |= SD_MIS_FRONT | SD_MIS_BACK; flag |= SD_MIS_FRONT | SD_MIS_BACK;
} }
if (!is_zero(shader->emission_estimate)) if (!is_zero(shader->emission_estimate)) {
flag |= SD_HAS_EMISSION; flag |= SD_HAS_EMISSION;
if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) }
if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) {
flag |= SD_HAS_TRANSPARENT_SHADOW; flag |= SD_HAS_TRANSPARENT_SHADOW;
if (shader->has_surface_raytrace) }
if (shader->has_surface_raytrace) {
flag |= SD_HAS_RAYTRACE; flag |= SD_HAS_RAYTRACE;
}
if (shader->has_volume) { if (shader->has_volume) {
flag |= SD_HAS_VOLUME; flag |= SD_HAS_VOLUME;
has_volumes = true; has_volumes = true;
@ -545,30 +552,40 @@ void ShaderManager::device_update_common(Device * /*device*/,
flag |= SD_HAS_TRANSPARENT_SHADOW; flag |= SD_HAS_TRANSPARENT_SHADOW;
} }
/* in this case we can assume transparent surface */ /* in this case we can assume transparent surface */
if (shader->has_volume_connected && !shader->has_surface) if (shader->has_volume_connected && !shader->has_surface) {
flag |= SD_HAS_ONLY_VOLUME; flag |= SD_HAS_ONLY_VOLUME;
}
if (shader->has_volume) { if (shader->has_volume) {
if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) {
flag |= SD_HETEROGENEOUS_VOLUME; flag |= SD_HETEROGENEOUS_VOLUME;
} }
if (shader->has_volume_attribute_dependency) }
if (shader->has_volume_attribute_dependency) {
flag |= SD_NEED_VOLUME_ATTRIBUTES; flag |= SD_NEED_VOLUME_ATTRIBUTES;
if (shader->has_bssrdf_bump) }
if (shader->has_bssrdf_bump) {
flag |= SD_HAS_BSSRDF_BUMP; flag |= SD_HAS_BSSRDF_BUMP;
if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) }
if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) {
flag |= SD_VOLUME_EQUIANGULAR; flag |= SD_VOLUME_EQUIANGULAR;
if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) }
if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) {
flag |= SD_VOLUME_MIS; flag |= SD_VOLUME_MIS;
if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) }
if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) {
flag |= SD_VOLUME_CUBIC; flag |= SD_VOLUME_CUBIC;
if (shader->has_bump) }
if (shader->has_bump) {
flag |= SD_HAS_BUMP; flag |= SD_HAS_BUMP;
if (shader->get_displacement_method() != DISPLACE_BUMP) }
if (shader->get_displacement_method() != DISPLACE_BUMP) {
flag |= SD_HAS_DISPLACEMENT; flag |= SD_HAS_DISPLACEMENT;
}
/* constant emission check */ /* constant emission check */
if (shader->emission_is_constant) if (shader->emission_is_constant) {
flag |= SD_HAS_CONSTANT_EMISSION; flag |= SD_HAS_CONSTANT_EMISSION;
}
uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0); uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);

@ -99,9 +99,10 @@ void ShaderNode::create_inputs_outputs(const NodeType *type)
ShaderInput *ShaderNode::input(const char *name) ShaderInput *ShaderNode::input(const char *name)
{ {
foreach (ShaderInput *socket, inputs) { foreach (ShaderInput *socket, inputs) {
if (socket->name() == name) if (socket->name() == name) {
return socket; return socket;
} }
}
return NULL; return NULL;
} }
@ -109,8 +110,9 @@ ShaderInput *ShaderNode::input(const char *name)
ShaderOutput *ShaderNode::output(const char *name) ShaderOutput *ShaderNode::output(const char *name)
{ {
foreach (ShaderOutput *socket, outputs) foreach (ShaderOutput *socket, outputs)
if (socket->name() == name) if (socket->name() == name) {
return socket; return socket;
}
return NULL; return NULL;
} }
@ -118,9 +120,10 @@ ShaderOutput *ShaderNode::output(const char *name)
ShaderInput *ShaderNode::input(ustring name) ShaderInput *ShaderNode::input(ustring name)
{ {
foreach (ShaderInput *socket, inputs) { foreach (ShaderInput *socket, inputs) {
if (socket->name() == name) if (socket->name() == name) {
return socket; return socket;
} }
}
return NULL; return NULL;
} }
@ -128,8 +131,9 @@ ShaderInput *ShaderNode::input(ustring name)
ShaderOutput *ShaderNode::output(ustring name) ShaderOutput *ShaderNode::output(ustring name)
{ {
foreach (ShaderOutput *socket, outputs) foreach (ShaderOutput *socket, outputs)
if (socket->name() == name) if (socket->name() == name) {
return socket; return socket;
}
return NULL; return NULL;
} }
@ -146,17 +150,20 @@ void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
foreach (ShaderInput *input, inputs) { foreach (ShaderInput *input, inputs) {
if (!input->link) { if (!input->link) {
if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) { if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if (shader->has_surface_link()) if (shader->has_surface_link()) {
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
if (shader->has_volume) }
if (shader->has_volume) {
attributes->add(ATTR_STD_GENERATED_TRANSFORM); attributes->add(ATTR_STD_GENERATED_TRANSFORM);
} }
}
else if (input->flags() & SocketType::LINK_TEXTURE_UV) { else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
if (shader->has_surface_link()) if (shader->has_surface_link()) {
attributes->add(ATTR_STD_UV); attributes->add(ATTR_STD_UV);
} }
} }
} }
}
} }
bool ShaderNode::equals(const ShaderNode &other) bool ShaderNode::equals(const ShaderNode &other)
@ -322,9 +329,10 @@ void ShaderGraph::relink(ShaderOutput *from, ShaderOutput *to)
foreach (ShaderInput *sock, outputs) { foreach (ShaderInput *sock, outputs) {
disconnect(sock); disconnect(sock);
if (to) if (to) {
connect(to, sock); connect(to, sock);
} }
}
} }
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
@ -336,15 +344,17 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
/* Bypass node by moving all links from "from" to "to" */ /* Bypass node by moving all links from "from" to "to" */
foreach (ShaderInput *sock, node->inputs) { foreach (ShaderInput *sock, node->inputs) {
if (sock->link) if (sock->link) {
disconnect(sock); disconnect(sock);
} }
}
foreach (ShaderInput *sock, outputs) { foreach (ShaderInput *sock, outputs) {
disconnect(sock); disconnect(sock);
if (to) if (to) {
connect(to, sock); connect(to, sock);
} }
}
} }
void ShaderGraph::simplify(Scene *scene) void ShaderGraph::simplify(Scene *scene)
@ -369,18 +379,21 @@ void ShaderGraph::finalize(Scene *scene, bool do_bump, bool bump_in_object_space
if (!finalized) { if (!finalized) {
simplify(scene); simplify(scene);
if (do_bump) if (do_bump) {
bump_from_displacement(bump_in_object_space); bump_from_displacement(bump_in_object_space);
}
ShaderInput *surface_in = output()->input("Surface"); ShaderInput *surface_in = output()->input("Surface");
ShaderInput *volume_in = output()->input("Volume"); ShaderInput *volume_in = output()->input("Volume");
/* todo: make this work when surface and volume closures are tangled up */ /* todo: make this work when surface and volume closures are tangled up */
if (surface_in->link) if (surface_in->link) {
transform_multi_closure(surface_in->link->parent, NULL, false); transform_multi_closure(surface_in->link->parent, NULL, false);
if (volume_in->link) }
if (volume_in->link) {
transform_multi_closure(volume_in->link->parent, NULL, true); transform_multi_closure(volume_in->link->parent, NULL, true);
}
finalized = true; finalized = true;
} }
@ -479,15 +492,18 @@ void ShaderGraph::remove_proxy_nodes()
vector<ShaderInput *> links = tonode->outputs[0]->links; vector<ShaderInput *> links = tonode->outputs[0]->links;
foreach (ShaderInput *autoin, links) { foreach (ShaderInput *autoin, links) {
if (autoin->flags() & SocketType::DEFAULT_LINK_MASK) if (autoin->flags() & SocketType::DEFAULT_LINK_MASK) {
disconnect(autoin); disconnect(autoin);
else }
else {
all_links_removed = false; all_links_removed = false;
} }
}
if (all_links_removed) if (all_links_removed) {
removed[tonode->id] = true; removed[tonode->id] = true;
} }
}
disconnect(to); disconnect(to);
@ -506,11 +522,13 @@ void ShaderGraph::remove_proxy_nodes()
list<ShaderNode *> newnodes; list<ShaderNode *> newnodes;
foreach (ShaderNode *node, nodes) { foreach (ShaderNode *node, nodes) {
if (!removed[node->id]) if (!removed[node->id]) {
newnodes.push_back(node); newnodes.push_back(node);
else }
else {
delete_node(node); delete_node(node);
} }
}
nodes = newnodes; nodes = newnodes;
} }
@ -805,11 +823,13 @@ void ShaderGraph::clean(Scene *scene)
list<ShaderNode *> newnodes; list<ShaderNode *> newnodes;
foreach (ShaderNode *node, nodes) { foreach (ShaderNode *node, nodes) {
if (visited[node->id]) if (visited[node->id]) {
newnodes.push_back(node); newnodes.push_back(node);
else }
else {
delete_node(node); delete_node(node);
} }
}
nodes = newnodes; nodes = newnodes;
} }
@ -834,44 +854,51 @@ void ShaderGraph::default_inputs(bool do_osl)
foreach (ShaderInput *input, node->inputs) { foreach (ShaderInput *input, node->inputs) {
if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) { if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) { if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if (!texco) if (!texco) {
texco = create_node<TextureCoordinateNode>(); texco = create_node<TextureCoordinateNode>();
}
connect(texco->output("Generated"), input); connect(texco->output("Generated"), input);
} }
if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) { if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
if (!texco) if (!texco) {
texco = create_node<TextureCoordinateNode>(); texco = create_node<TextureCoordinateNode>();
}
connect(texco->output("Normal"), input); connect(texco->output("Normal"), input);
} }
else if (input->flags() & SocketType::LINK_TEXTURE_UV) { else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
if (!texco) if (!texco) {
texco = create_node<TextureCoordinateNode>(); texco = create_node<TextureCoordinateNode>();
}
connect(texco->output("UV"), input); connect(texco->output("UV"), input);
} }
else if (input->flags() & SocketType::LINK_INCOMING) { else if (input->flags() & SocketType::LINK_INCOMING) {
if (!geom) if (!geom) {
geom = create_node<GeometryNode>(); geom = create_node<GeometryNode>();
}
connect(geom->output("Incoming"), input); connect(geom->output("Incoming"), input);
} }
else if (input->flags() & SocketType::LINK_NORMAL) { else if (input->flags() & SocketType::LINK_NORMAL) {
if (!geom) if (!geom) {
geom = create_node<GeometryNode>(); geom = create_node<GeometryNode>();
}
connect(geom->output("Normal"), input); connect(geom->output("Normal"), input);
} }
else if (input->flags() & SocketType::LINK_POSITION) { else if (input->flags() & SocketType::LINK_POSITION) {
if (!geom) if (!geom) {
geom = create_node<GeometryNode>(); geom = create_node<GeometryNode>();
}
connect(geom->output("Position"), input); connect(geom->output("Position"), input);
} }
else if (input->flags() & SocketType::LINK_TANGENT) { else if (input->flags() & SocketType::LINK_TANGENT) {
if (!geom) if (!geom) {
geom = create_node<GeometryNode>(); geom = create_node<GeometryNode>();
}
connect(geom->output("Tangent"), input); connect(geom->output("Tangent"), input);
} }
@ -879,10 +906,12 @@ void ShaderGraph::default_inputs(bool do_osl)
} }
} }
if (geom) if (geom) {
add(geom); add(geom);
if (texco) }
if (texco) {
add(texco); add(texco);
}
} }
void ShaderGraph::refine_bump_nodes() void ShaderGraph::refine_bump_nodes()
@ -957,8 +986,9 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
ShaderInput *displacement_in = output()->input("Displacement"); ShaderInput *displacement_in = output()->input("Displacement");
if (!displacement_in->link) if (!displacement_in->link) {
return; return;
}
/* find dependencies for the given input */ /* find dependencies for the given input */
ShaderNodeSet nodes_displace; ShaderNodeSet nodes_displace;
@ -1056,13 +1086,16 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
ShaderInput *fac_in = mix_node->input("Fac"); ShaderInput *fac_in = mix_node->input("Fac");
ShaderInput *weight_in = mix_node->input("Weight"); ShaderInput *weight_in = mix_node->input("Weight");
if (fin->link) if (fin->link) {
connect(fin->link, fac_in); connect(fin->link, fac_in);
else }
else {
mix_node->set_fac(node->get_float(fin->socket_type)); mix_node->set_fac(node->get_float(fin->socket_type));
}
if (weight_out) if (weight_out) {
connect(weight_out, weight_in); connect(weight_out, weight_in);
}
weight1_out = mix_node->output("Weight1"); weight1_out = mix_node->output("Weight1");
weight2_out = mix_node->output("Weight2"); weight2_out = mix_node->output("Weight2");
@ -1073,17 +1106,20 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
weight2_out = weight_out; weight2_out = weight_out;
} }
if (cl1in->link) if (cl1in->link) {
transform_multi_closure(cl1in->link->parent, weight1_out, volume); transform_multi_closure(cl1in->link->parent, weight1_out, volume);
if (cl2in->link) }
if (cl2in->link) {
transform_multi_closure(cl2in->link->parent, weight2_out, volume); transform_multi_closure(cl2in->link->parent, weight2_out, volume);
} }
}
else { else {
ShaderInput *weight_in = node->input((volume) ? "VolumeMixWeight" : "SurfaceMixWeight"); ShaderInput *weight_in = node->input((volume) ? "VolumeMixWeight" : "SurfaceMixWeight");
/* not a closure node? */ /* not a closure node? */
if (!weight_in) if (!weight_in) {
return; return;
}
/* already has a weight connected to it? add weights */ /* already has a weight connected to it? add weights */
float weight_value = node->get_float(weight_in->socket_type); float weight_value = node->get_float(weight_in->socket_type);
@ -1091,27 +1127,34 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
MathNode *math_node = create_node<MathNode>(); MathNode *math_node = create_node<MathNode>();
add(math_node); add(math_node);
if (weight_in->link) if (weight_in->link) {
connect(weight_in->link, math_node->input("Value1")); connect(weight_in->link, math_node->input("Value1"));
else }
else {
math_node->set_value1(weight_value); math_node->set_value1(weight_value);
}
if (weight_out) if (weight_out) {
connect(weight_out, math_node->input("Value2")); connect(weight_out, math_node->input("Value2"));
else }
else {
math_node->set_value2(1.0f); math_node->set_value2(1.0f);
}
weight_out = math_node->output("Value"); weight_out = math_node->output("Value");
if (weight_in->link) if (weight_in->link) {
disconnect(weight_in); disconnect(weight_in);
} }
}
/* connected to closure mix weight */ /* connected to closure mix weight */
if (weight_out) if (weight_out) {
connect(weight_out, weight_in); connect(weight_out, weight_in);
else }
else {
node->set(weight_in->socket_type, weight_value + 1.0f); node->set(weight_in->socket_type, weight_value + 1.0f);
} }
}
} }
int ShaderGraph::get_num_closures() int ShaderGraph::get_num_closures()

@ -71,24 +71,30 @@ Transform TextureMapping::compute_transform()
{ {
Transform mmat = transform_scale(zero_float3()); Transform mmat = transform_scale(zero_float3());
if (x_mapping != NONE) if (x_mapping != NONE) {
mmat[0][x_mapping - 1] = 1.0f; mmat[0][x_mapping - 1] = 1.0f;
if (y_mapping != NONE) }
if (y_mapping != NONE) {
mmat[1][y_mapping - 1] = 1.0f; mmat[1][y_mapping - 1] = 1.0f;
if (z_mapping != NONE) }
if (z_mapping != NONE) {
mmat[2][z_mapping - 1] = 1.0f; mmat[2][z_mapping - 1] = 1.0f;
}
float3 scale_clamped = scale; float3 scale_clamped = scale;
if (type == TEXTURE || type == NORMAL) { if (type == TEXTURE || type == NORMAL) {
/* keep matrix invertible */ /* keep matrix invertible */
if (fabsf(scale.x) < 1e-5f) if (fabsf(scale.x) < 1e-5f) {
scale_clamped.x = signf(scale.x) * 1e-5f; scale_clamped.x = signf(scale.x) * 1e-5f;
if (fabsf(scale.y) < 1e-5f) }
if (fabsf(scale.y) < 1e-5f) {
scale_clamped.y = signf(scale.y) * 1e-5f; scale_clamped.y = signf(scale.y) * 1e-5f;
if (fabsf(scale.z) < 1e-5f) }
if (fabsf(scale.z) < 1e-5f) {
scale_clamped.z = signf(scale.z) * 1e-5f; scale_clamped.z = signf(scale.z) * 1e-5f;
} }
}
Transform smat = transform_scale(scale_clamped); Transform smat = transform_scale(scale_clamped);
Transform rmat = transform_euler(rotation); Transform rmat = transform_euler(rotation);
@ -126,17 +132,22 @@ Transform TextureMapping::compute_transform()
bool TextureMapping::skip() bool TextureMapping::skip()
{ {
if (translation != zero_float3()) if (translation != zero_float3()) {
return false; return false;
if (rotation != zero_float3()) }
if (rotation != zero_float3()) {
return false; return false;
if (scale != one_float3()) }
if (scale != one_float3()) {
return false; return false;
}
if (x_mapping != X || y_mapping != Y || z_mapping != Z) if (x_mapping != X || y_mapping != Y || z_mapping != Z) {
return false; return false;
if (use_minmax) }
if (use_minmax) {
return false; return false;
}
return true; return true;
} }
@ -906,10 +917,12 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
ShaderOutput *color_out = output("Color"); ShaderOutput *color_out = output("Color");
SunSky sunsky; SunSky sunsky;
if (sky_type == NODE_SKY_PREETHAM) if (sky_type == NODE_SKY_PREETHAM) {
sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
else if (sky_type == NODE_SKY_HOSEK) }
else if (sky_type == NODE_SKY_HOSEK) {
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
}
else if (sky_type == NODE_SKY_NISHITA) { else if (sky_type == NODE_SKY_NISHITA) {
/* Clamp altitude to reasonable values. /* Clamp altitude to reasonable values.
* Below 1m causes numerical issues and above 60km is space. */ * Below 1m causes numerical issues and above 60km is space. */
@ -937,8 +950,9 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
handle = image_manager->add_image(loader, impar); handle = image_manager->add_image(loader, impar);
} }
} }
else else {
assert(false); assert(false);
}
int vector_offset = tex_mapping.compile_begin(compiler, vector_in); int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
@ -1002,10 +1016,12 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
tex_mapping.compile(compiler); tex_mapping.compile(compiler);
SunSky sunsky; SunSky sunsky;
if (sky_type == NODE_SKY_PREETHAM) if (sky_type == NODE_SKY_PREETHAM) {
sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
else if (sky_type == NODE_SKY_HOSEK) }
else if (sky_type == NODE_SKY_HOSEK) {
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
}
else if (sky_type == NODE_SKY_NISHITA) { else if (sky_type == NODE_SKY_NISHITA) {
/* Clamp altitude to reasonable values. /* Clamp altitude to reasonable values.
* Below 1m causes numerical issues and above 60km is space. */ * Below 1m causes numerical issues and above 60km is space. */
@ -1033,8 +1049,9 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
handle = image_manager->add_image(loader, impar); handle = image_manager->add_image(loader, impar);
} }
} }
else else {
assert(false); assert(false);
}
compiler.parameter(this, "sky_type"); compiler.parameter(this, "sky_type");
compiler.parameter("theta", sunsky.theta); compiler.parameter("theta", sunsky.theta);
@ -1874,8 +1891,9 @@ ShaderNode *PointDensityTextureNode::clone(ShaderGraph *graph) const
void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (shader->has_volume) if (shader->has_volume) {
attributes->add(ATTR_STD_GENERATED_TRANSFORM); attributes->add(ATTR_STD_GENERATED_TRANSFORM);
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -2153,10 +2171,12 @@ ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool auto
from = from_; from = from_;
to = to_; to = to_;
if (from == to) if (from == to) {
special_type = SHADER_SPECIAL_TYPE_PROXY; special_type = SHADER_SPECIAL_TYPE_PROXY;
else if (autoconvert) }
else if (autoconvert) {
special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
}
} }
/* Union usage requires a manual copy constructor. */ /* Union usage requires a manual copy constructor. */
@ -2225,45 +2245,53 @@ void ConvertNode::compile(SVMCompiler &compiler)
ShaderOutput *out = outputs[0]; ShaderOutput *out = outputs[0];
if (from == SocketType::FLOAT) { if (from == SocketType::FLOAT) {
if (to == SocketType::INT) if (to == SocketType::INT) {
/* float to int */ /* float to int */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
else }
else {
/* float to float3 */ /* float to float3 */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
} }
}
else if (from == SocketType::INT) { else if (from == SocketType::INT) {
if (to == SocketType::FLOAT) if (to == SocketType::FLOAT) {
/* int to float */ /* int to float */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
else }
else {
/* int to vector/point/normal */ /* int to vector/point/normal */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
} }
}
else if (to == SocketType::FLOAT) { else if (to == SocketType::FLOAT) {
if (from == SocketType::COLOR) if (from == SocketType::COLOR) {
/* color to float */ /* color to float */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
else }
else {
/* vector/point/normal to float */ /* vector/point/normal to float */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
} }
}
else if (to == SocketType::INT) { else if (to == SocketType::INT) {
if (from == SocketType::COLOR) if (from == SocketType::COLOR) {
/* color to int */ /* color to int */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
else }
else {
/* vector/point/normal to int */ /* vector/point/normal to int */
compiler.add_node( compiler.add_node(
NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out)); NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
} }
}
else { else {
/* float3 to float3 */ /* float3 to float3 */
if (in->link) { if (in->link) {
@ -2283,20 +2311,27 @@ void ConvertNode::compile(OSLCompiler &compiler)
/* proxy nodes should have been removed at this point */ /* proxy nodes should have been removed at this point */
assert(special_type != SHADER_SPECIAL_TYPE_PROXY); assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
if (from == SocketType::FLOAT) if (from == SocketType::FLOAT) {
compiler.add(this, "node_convert_from_float"); compiler.add(this, "node_convert_from_float");
else if (from == SocketType::INT) }
else if (from == SocketType::INT) {
compiler.add(this, "node_convert_from_int"); compiler.add(this, "node_convert_from_int");
else if (from == SocketType::COLOR) }
else if (from == SocketType::COLOR) {
compiler.add(this, "node_convert_from_color"); compiler.add(this, "node_convert_from_color");
else if (from == SocketType::VECTOR) }
else if (from == SocketType::VECTOR) {
compiler.add(this, "node_convert_from_vector"); compiler.add(this, "node_convert_from_vector");
else if (from == SocketType::POINT) }
else if (from == SocketType::POINT) {
compiler.add(this, "node_convert_from_point"); compiler.add(this, "node_convert_from_point");
else if (from == SocketType::NORMAL) }
else if (from == SocketType::NORMAL) {
compiler.add(this, "node_convert_from_normal"); compiler.add(this, "node_convert_from_normal");
else }
else {
assert(0); assert(0);
}
} }
/* Base type for all closure-type nodes */ /* Base type for all closure-type nodes */
@ -2328,10 +2363,12 @@ void BsdfNode::compile(SVMCompiler &compiler,
ShaderInput *normal_in = input("Normal"); ShaderInput *normal_in = input("Normal");
ShaderInput *tangent_in = input("Tangent"); ShaderInput *tangent_in = input("Tangent");
if (color_in->link) if (color_in->link) {
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else }
else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
}
int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID; int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) : int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) :
@ -2405,9 +2442,10 @@ void GlossyBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
ShaderInput *tangent_in = input("Tangent"); ShaderInput *tangent_in = input("Tangent");
if (!tangent_in->link && !is_isotropic()) if (!tangent_in->link && !is_isotropic()) {
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -2740,9 +2778,10 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
ShaderInput *tangent_in = input("Tangent"); ShaderInput *tangent_in = input("Tangent");
if (!tangent_in->link) if (!tangent_in->link) {
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -2981,8 +3020,9 @@ void EmissionNode::compile(SVMCompiler &compiler)
compiler.add_node( compiler.add_node(
NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in)); NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
} }
else else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
}
compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset()); compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
} }
@ -3028,8 +3068,9 @@ void BackgroundNode::compile(SVMCompiler &compiler)
compiler.add_node( compiler.add_node(
NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in)); NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
} }
else else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
}
compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset()); compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
} }
@ -3145,10 +3186,12 @@ void VolumeNode::compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput
{ {
ShaderInput *color_in = input("Color"); ShaderInput *color_in = input("Color");
if (color_in->link) if (color_in->link) {
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else }
else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
}
compiler.add_node( compiler.add_node(
NODE_CLOSURE_VOLUME, NODE_CLOSURE_VOLUME,
@ -3297,10 +3340,12 @@ void PrincipledVolumeNode::compile(SVMCompiler &compiler)
ShaderInput *blackbody_tint_in = input("Blackbody Tint"); ShaderInput *blackbody_tint_in = input("Blackbody Tint");
ShaderInput *temperature_in = input("Temperature"); ShaderInput *temperature_in = input("Temperature");
if (color_in->link) if (color_in->link) {
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else }
else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
}
compiler.add_node(NODE_PRINCIPLED_VOLUME, compiler.add_node(NODE_PRINCIPLED_VOLUME,
compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in), compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in),
@ -3677,12 +3722,15 @@ void GeometryNode::compile(SVMCompiler &compiler)
void GeometryNode::compile(OSLCompiler &compiler) void GeometryNode::compile(OSLCompiler &compiler)
{ {
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
compiler.parameter("bump_offset", "dx"); compiler.parameter("bump_offset", "dx");
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
compiler.parameter("bump_offset", "dy"); compiler.parameter("bump_offset", "dy");
else }
else {
compiler.parameter("bump_offset", "center"); compiler.parameter("bump_offset", "center");
}
compiler.add(this, "node_geometry"); compiler.add(this, "node_geometry");
} }
@ -3714,12 +3762,14 @@ void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attr
{ {
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
if (!from_dupli) { if (!from_dupli) {
if (!output("Generated")->links.empty()) if (!output("Generated")->links.empty()) {
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
if (!output("UV")->links.empty()) }
if (!output("UV")->links.empty()) {
attributes->add(ATTR_STD_UV); attributes->add(ATTR_STD_UV);
} }
} }
}
if (shader->has_volume) { if (shader->has_volume) {
if (!from_dupli) { if (!from_dupli) {
@ -3819,17 +3869,22 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
void TextureCoordinateNode::compile(OSLCompiler &compiler) void TextureCoordinateNode::compile(OSLCompiler &compiler)
{ {
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
compiler.parameter("bump_offset", "dx"); compiler.parameter("bump_offset", "dx");
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
compiler.parameter("bump_offset", "dy"); compiler.parameter("bump_offset", "dy");
else }
else {
compiler.parameter("bump_offset", "center"); compiler.parameter("bump_offset", "center");
}
if (compiler.background) if (compiler.background) {
compiler.parameter("is_background", true); compiler.parameter("is_background", true);
if (compiler.output_type() == SHADER_TYPE_VOLUME) }
if (compiler.output_type() == SHADER_TYPE_VOLUME) {
compiler.parameter("is_volume", true); compiler.parameter("is_volume", true);
}
compiler.parameter(this, "use_transform"); compiler.parameter(this, "use_transform");
Transform ob_itfm = transform_inverse(ob_tfm); Transform ob_itfm = transform_inverse(ob_tfm);
compiler.parameter("object_itfm", ob_itfm); compiler.parameter("object_itfm", ob_itfm);
@ -3860,13 +3915,15 @@ void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if (shader->has_surface) { if (shader->has_surface) {
if (!from_dupli) { if (!from_dupli) {
if (!output("UV")->links.empty()) { if (!output("UV")->links.empty()) {
if (attribute != "") if (attribute != "") {
attributes->add(attribute); attributes->add(attribute);
else }
else {
attributes->add(ATTR_STD_UV); attributes->add(ATTR_STD_UV);
} }
} }
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -3892,10 +3949,12 @@ void UVMapNode::compile(SVMCompiler &compiler)
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out)); compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
} }
else { else {
if (attribute != "") if (attribute != "") {
attr = compiler.attribute(attribute); attr = compiler.attribute(attribute);
else }
else {
attr = compiler.attribute(ATTR_STD_UV); attr = compiler.attribute(ATTR_STD_UV);
}
compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3); compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
} }
@ -3904,12 +3963,15 @@ void UVMapNode::compile(SVMCompiler &compiler)
void UVMapNode::compile(OSLCompiler &compiler) void UVMapNode::compile(OSLCompiler &compiler)
{ {
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
compiler.parameter("bump_offset", "dx"); compiler.parameter("bump_offset", "dx");
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
compiler.parameter("bump_offset", "dy"); compiler.parameter("bump_offset", "dy");
else }
else {
compiler.parameter("bump_offset", "center"); compiler.parameter("bump_offset", "center");
}
compiler.parameter(this, "from_dupli"); compiler.parameter(this, "from_dupli");
compiler.parameter(this, "attribute"); compiler.parameter(this, "attribute");
@ -4159,26 +4221,34 @@ ParticleInfoNode::ParticleInfoNode() : ShaderNode(get_node_type()) {}
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes) void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (!output("Index")->links.empty()) if (!output("Index")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Random")->links.empty()) }
if (!output("Random")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Age")->links.empty()) }
if (!output("Age")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Lifetime")->links.empty()) }
if (!output("Lifetime")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Location")->links.empty()) }
if (!output("Location")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
}
#if 0 /* not yet supported */ #if 0 /* not yet supported */
if (!output("Rotation")->links.empty()) if (!output("Rotation")->links.empty())
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
#endif #endif
if (!output("Size")->links.empty()) if (!output("Size")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Velocity")->links.empty()) }
if (!output("Velocity")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
if (!output("Angular Velocity")->links.empty()) }
if (!output("Angular Velocity")->links.empty()) {
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -4265,15 +4335,18 @@ void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
ShaderOutput *intercept_out = output("Intercept"); ShaderOutput *intercept_out = output("Intercept");
if (!intercept_out->links.empty()) if (!intercept_out->links.empty()) {
attributes->add(ATTR_STD_CURVE_INTERCEPT); attributes->add(ATTR_STD_CURVE_INTERCEPT);
}
if (!output("Length")->links.empty()) if (!output("Length")->links.empty()) {
attributes->add(ATTR_STD_CURVE_LENGTH); attributes->add(ATTR_STD_CURVE_LENGTH);
}
if (!output("Random")->links.empty()) if (!output("Random")->links.empty()) {
attributes->add(ATTR_STD_CURVE_RANDOM); attributes->add(ATTR_STD_CURVE_RANDOM);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -4339,9 +4412,10 @@ PointInfoNode::PointInfoNode() : ShaderNode(get_node_type()) {}
void PointInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes) void PointInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
if (!output("Random")->links.empty()) if (!output("Random")->links.empty()) {
attributes->add(ATTR_STD_POINT_RANDOM); attributes->add(ATTR_STD_POINT_RANDOM);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -4466,11 +4540,13 @@ VertexColorNode::VertexColorNode() : ShaderNode(get_node_type()) {}
void VertexColorNode::attributes(Shader *shader, AttributeRequestSet *attributes) void VertexColorNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) { if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) {
if (layer_name != "") if (layer_name != "") {
attributes->add_standard(layer_name); attributes->add_standard(layer_name);
else }
else {
attributes->add(ATTR_STD_VERTEX_COLOR); attributes->add(ATTR_STD_VERTEX_COLOR);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -4489,10 +4565,12 @@ void VertexColorNode::compile(SVMCompiler &compiler)
ShaderNodeType node; ShaderNodeType node;
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
node = NODE_VERTEX_COLOR_BUMP_DX; node = NODE_VERTEX_COLOR_BUMP_DX;
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
node = NODE_VERTEX_COLOR_BUMP_DY; node = NODE_VERTEX_COLOR_BUMP_DY;
}
else { else {
node = NODE_VERTEX_COLOR; node = NODE_VERTEX_COLOR;
} }
@ -5682,10 +5760,12 @@ void AttributeNode::compile(SVMCompiler &compiler)
ShaderNodeType attr_node = NODE_ATTR; ShaderNodeType attr_node = NODE_ATTR;
int attr = compiler.attribute_standard(attribute); int attr = compiler.attribute_standard(attribute);
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
attr_node = NODE_ATTR_BUMP_DX; attr_node = NODE_ATTR_BUMP_DX;
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
attr_node = NODE_ATTR_BUMP_DY; attr_node = NODE_ATTR_BUMP_DY;
}
if (!color_out->links.empty() || !vector_out->links.empty()) { if (!color_out->links.empty() || !vector_out->links.empty()) {
if (!color_out->links.empty()) { if (!color_out->links.empty()) {
@ -5710,17 +5790,22 @@ void AttributeNode::compile(SVMCompiler &compiler)
void AttributeNode::compile(OSLCompiler &compiler) void AttributeNode::compile(OSLCompiler &compiler)
{ {
if (bump == SHADER_BUMP_DX) if (bump == SHADER_BUMP_DX) {
compiler.parameter("bump_offset", "dx"); compiler.parameter("bump_offset", "dx");
else if (bump == SHADER_BUMP_DY) }
else if (bump == SHADER_BUMP_DY) {
compiler.parameter("bump_offset", "dy"); compiler.parameter("bump_offset", "dy");
else }
else {
compiler.parameter("bump_offset", "center"); compiler.parameter("bump_offset", "center");
}
if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE) if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE) {
compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str()); compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
else }
else {
compiler.parameter("name", attribute.c_str()); compiler.parameter("name", attribute.c_str());
}
compiler.add(this, "node_attribute"); compiler.add(this, "node_attribute");
} }
@ -5985,12 +6070,15 @@ void OutputNode::compile(SVMCompiler &compiler)
void OutputNode::compile(OSLCompiler &compiler) void OutputNode::compile(OSLCompiler &compiler)
{ {
if (compiler.output_type() == SHADER_TYPE_SURFACE) if (compiler.output_type() == SHADER_TYPE_SURFACE) {
compiler.add(this, "node_output_surface"); compiler.add(this, "node_output_surface");
else if (compiler.output_type() == SHADER_TYPE_VOLUME) }
else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
compiler.add(this, "node_output_volume"); compiler.add(this, "node_output_volume");
else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) }
else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
compiler.add(this, "node_output_displacement"); compiler.add(this, "node_output_displacement");
}
} }
/* Map Range Node */ /* Map Range Node */
@ -6703,8 +6791,9 @@ void CurvesNode::compile(SVMCompiler &compiler,
ShaderInput *value_in, ShaderInput *value_in,
ShaderOutput *value_out) ShaderOutput *value_out)
{ {
if (curves.size() == 0) if (curves.size() == 0) {
return; return;
}
ShaderInput *fac_in = input("Fac"); ShaderInput *fac_in = input("Fac");
@ -6717,14 +6806,16 @@ void CurvesNode::compile(SVMCompiler &compiler,
__float_as_int(max_x)); __float_as_int(max_x));
compiler.add_node(curves.size()); compiler.add_node(curves.size());
for (int i = 0; i < curves.size(); i++) for (int i = 0; i < curves.size(); i++) {
compiler.add_node(float3_to_float4(curves[i])); compiler.add_node(float3_to_float4(curves[i]));
}
} }
void CurvesNode::compile(OSLCompiler &compiler, const char *name) void CurvesNode::compile(OSLCompiler &compiler, const char *name)
{ {
if (curves.size() == 0) if (curves.size() == 0) {
return; return;
}
compiler.parameter_color_array("ramp", curves); compiler.parameter_color_array("ramp", curves);
compiler.parameter(this, "min_x"); compiler.parameter(this, "min_x");
@ -6861,8 +6952,9 @@ void FloatCurveNode::constant_fold(const ConstantFolder &folder)
void FloatCurveNode::compile(SVMCompiler &compiler) void FloatCurveNode::compile(SVMCompiler &compiler)
{ {
if (curve.size() == 0) if (curve.size() == 0) {
return; return;
}
ShaderInput *value_in = input("Value"); ShaderInput *value_in = input("Value");
ShaderInput *fac_in = input("Factor"); ShaderInput *fac_in = input("Factor");
@ -6877,14 +6969,16 @@ void FloatCurveNode::compile(SVMCompiler &compiler)
__float_as_int(max_x)); __float_as_int(max_x));
compiler.add_node(curve.size()); compiler.add_node(curve.size());
for (int i = 0; i < curve.size(); i++) for (int i = 0; i < curve.size(); i++) {
compiler.add_node(make_float4(curve[i])); compiler.add_node(make_float4(curve[i]));
}
} }
void FloatCurveNode::compile(OSLCompiler &compiler) void FloatCurveNode::compile(OSLCompiler &compiler)
{ {
if (curve.size() == 0) if (curve.size() == 0) {
return; return;
}
compiler.parameter_array("ramp", curve.data(), curve.size()); compiler.parameter_array("ramp", curve.data(), curve.size());
compiler.parameter(this, "min_x"); compiler.parameter(this, "min_x");
@ -6915,8 +7009,9 @@ RGBRampNode::RGBRampNode() : ShaderNode(get_node_type()) {}
void RGBRampNode::constant_fold(const ConstantFolder &folder) void RGBRampNode::constant_fold(const ConstantFolder &folder)
{ {
if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
return; return;
}
if (folder.all_inputs_constant()) { if (folder.all_inputs_constant()) {
float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1); float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
@ -6940,8 +7035,9 @@ void RGBRampNode::constant_fold(const ConstantFolder &folder)
void RGBRampNode::compile(SVMCompiler &compiler) void RGBRampNode::compile(SVMCompiler &compiler)
{ {
if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
return; return;
}
ShaderInput *fac_in = input("Fac"); ShaderInput *fac_in = input("Fac");
ShaderOutput *color_out = output("Color"); ShaderOutput *color_out = output("Color");
@ -6954,14 +7050,16 @@ void RGBRampNode::compile(SVMCompiler &compiler)
interpolate); interpolate);
compiler.add_node(ramp.size()); compiler.add_node(ramp.size());
for (int i = 0; i < ramp.size(); i++) for (int i = 0; i < ramp.size(); i++) {
compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i])); compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
}
} }
void RGBRampNode::compile(OSLCompiler &compiler) void RGBRampNode::compile(OSLCompiler &compiler)
{ {
if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
return; return;
}
compiler.parameter_color_array("ramp_color", ramp); compiler.parameter_color_array("ramp_color", ramp);
compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size()); compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
@ -7071,10 +7169,12 @@ void OSLNode::compile(SVMCompiler &)
void OSLNode::compile(OSLCompiler &compiler) void OSLNode::compile(OSLCompiler &compiler)
{ {
if (!filepath.empty()) if (!filepath.empty()) {
compiler.add(this, filepath.c_str(), true); compiler.add(this, filepath.c_str(), true);
else }
else {
compiler.add(this, bytecode_hash.c_str(), false); compiler.add(this, bytecode_hash.c_str(), false);
}
} }
/* Normal Map */ /* Normal Map */
@ -7195,14 +7295,17 @@ void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if (shader->has_surface_link()) { if (shader->has_surface_link()) {
if (direction_type == NODE_TANGENT_UVMAP) { if (direction_type == NODE_TANGENT_UVMAP) {
if (attribute.empty()) if (attribute.empty()) {
attributes->add(ATTR_STD_UV_TANGENT); attributes->add(ATTR_STD_UV_TANGENT);
else }
else {
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
} }
else }
else {
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
} }
}
ShaderNode::attributes(shader, attributes); ShaderNode::attributes(shader, attributes);
} }
@ -7213,13 +7316,16 @@ void TangentNode::compile(SVMCompiler &compiler)
int attr; int attr;
if (direction_type == NODE_TANGENT_UVMAP) { if (direction_type == NODE_TANGENT_UVMAP) {
if (attribute.empty()) if (attribute.empty()) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT); attr = compiler.attribute(ATTR_STD_UV_TANGENT);
else }
else {
attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
} }
else }
else {
attr = compiler.attribute(ATTR_STD_GENERATED); attr = compiler.attribute(ATTR_STD_GENERATED);
}
compiler.add_node( compiler.add_node(
NODE_TANGENT, NODE_TANGENT,
@ -7230,11 +7336,13 @@ void TangentNode::compile(SVMCompiler &compiler)
void TangentNode::compile(OSLCompiler &compiler) void TangentNode::compile(OSLCompiler &compiler)
{ {
if (direction_type == NODE_TANGENT_UVMAP) { if (direction_type == NODE_TANGENT_UVMAP) {
if (attribute.empty()) if (attribute.empty()) {
compiler.parameter("attr_name", ustring("geom:tangent")); compiler.parameter("attr_name", ustring("geom:tangent"));
else }
else {
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
} }
}
compiler.parameter(this, "direction_type"); compiler.parameter(this, "direction_type");
compiler.parameter(this, "axis"); compiler.parameter(this, "axis");

@ -54,8 +54,9 @@ void SVMShaderManager::device_update_specific(Device *device,
Scene *scene, Scene *scene,
Progress &progress) Progress &progress)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -200,17 +201,20 @@ int SVMCompiler::stack_find_offset(int size)
/* find free space in stack & mark as used */ /* find free space in stack & mark as used */
for (int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) { for (int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
if (active_stack.users[i]) if (active_stack.users[i]) {
num_unused = 0; num_unused = 0;
else }
else {
num_unused++; num_unused++;
}
if (num_unused == size) { if (num_unused == size) {
offset = i + 1 - size; offset = i + 1 - size;
max_stack_use = max(i + 1, max_stack_use); max_stack_use = max(i + 1, max_stack_use);
while (i >= offset) while (i >= offset) {
active_stack.users[i--] = 1; active_stack.users[i--] = 1;
}
return offset; return offset;
} }
@ -235,8 +239,9 @@ void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
{ {
int size = stack_size(type); int size = stack_size(type);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
active_stack.users[offset + i]--; active_stack.users[offset + i]--;
}
} }
int SVMCompiler::stack_assign(ShaderInput *input) int SVMCompiler::stack_assign(ShaderInput *input)
@ -269,10 +274,11 @@ int SVMCompiler::stack_assign(ShaderInput *input)
add_node(NODE_VALUE_V, input->stack_offset); add_node(NODE_VALUE_V, input->stack_offset);
add_node(NODE_VALUE_V, node->get_float3(input->socket_type)); add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
} }
else /* should not get called for closure */ else { /* should not get called for closure */
assert(0); assert(0);
} }
} }
}
return input->stack_offset; return input->stack_offset;
} }
@ -280,24 +286,27 @@ int SVMCompiler::stack_assign(ShaderInput *input)
int SVMCompiler::stack_assign(ShaderOutput *output) int SVMCompiler::stack_assign(ShaderOutput *output)
{ {
/* if no stack offset assigned yet, find one */ /* if no stack offset assigned yet, find one */
if (output->stack_offset == SVM_STACK_INVALID) if (output->stack_offset == SVM_STACK_INVALID) {
output->stack_offset = stack_find_offset(output->type()); output->stack_offset = stack_find_offset(output->type());
}
return output->stack_offset; return output->stack_offset;
} }
int SVMCompiler::stack_assign_if_linked(ShaderInput *input) int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
{ {
if (input->link || input->constant_folded_in) if (input->link || input->constant_folded_in) {
return stack_assign(input); return stack_assign(input);
}
return SVM_STACK_INVALID; return SVM_STACK_INVALID;
} }
int SVMCompiler::stack_assign_if_linked(ShaderOutput *output) int SVMCompiler::stack_assign_if_linked(ShaderOutput *output)
{ {
if (!output->links.empty()) if (!output->links.empty()) {
return stack_assign(output); return stack_assign(output);
}
return SVM_STACK_INVALID; return SVM_STACK_INVALID;
} }
@ -312,9 +321,10 @@ void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
int size = stack_size(output->type()); int size = stack_size(output->type());
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
active_stack.users[output->stack_offset + i]++; active_stack.users[output->stack_offset + i]++;
} }
}
} }
void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done) void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
@ -334,8 +344,9 @@ void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
/* optimization we should add: verify if in->parent is actually used */ /* optimization we should add: verify if in->parent is actually used */
foreach (ShaderInput *in, output->links) foreach (ShaderInput *in, output->links)
if (in->parent != node && done.find(in->parent) == done.end()) if (in->parent != node && done.find(in->parent) == done.end()) {
all_done = false; all_done = false;
}
if (all_done) { if (all_done) {
stack_clear_offset(output->type(), output->stack_offset); stack_clear_offset(output->type(), output->stack_offset);
@ -431,17 +442,21 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
stack_clear_temporary(node); stack_clear_temporary(node);
if (current_type == SHADER_TYPE_SURFACE) { if (current_type == SHADER_TYPE_SURFACE) {
if (node->has_spatial_varying()) if (node->has_spatial_varying()) {
current_shader->has_surface_spatial_varying = true; current_shader->has_surface_spatial_varying = true;
if (node->get_feature() & KERNEL_FEATURE_NODE_RAYTRACE) }
if (node->get_feature() & KERNEL_FEATURE_NODE_RAYTRACE) {
current_shader->has_surface_raytrace = true; current_shader->has_surface_raytrace = true;
} }
}
else if (current_type == SHADER_TYPE_VOLUME) { else if (current_type == SHADER_TYPE_VOLUME) {
if (node->has_spatial_varying()) if (node->has_spatial_varying()) {
current_shader->has_volume_spatial_varying = true; current_shader->has_volume_spatial_varying = true;
if (node->has_attribute_dependency()) }
if (node->has_attribute_dependency()) {
current_shader->has_volume_attribute_dependency = true; current_shader->has_volume_attribute_dependency = true;
} }
}
} }
void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state) void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state)
@ -498,10 +513,12 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state)
"SurfaceMixWeight"; "SurfaceMixWeight";
ShaderInput *weight_in = node->input(weight_name); ShaderInput *weight_in = node->input(weight_name);
if (weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f)) if (weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f)) {
mix_weight_offset = stack_assign(weight_in); mix_weight_offset = stack_assign(weight_in);
else }
else {
mix_weight_offset = SVM_STACK_INVALID; mix_weight_offset = SVM_STACK_INVALID;
}
/* compile closure itself */ /* compile closure itself */
generate_node(node, state->nodes_done); generate_node(node, state->nodes_done);
@ -509,13 +526,15 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state)
mix_weight_offset = SVM_STACK_INVALID; mix_weight_offset = SVM_STACK_INVALID;
if (current_type == SHADER_TYPE_SURFACE) { if (current_type == SHADER_TYPE_SURFACE) {
if (node->has_surface_transparent()) if (node->has_surface_transparent()) {
current_shader->has_surface_transparent = true; current_shader->has_surface_transparent = true;
}
if (node->has_surface_bssrdf()) { if (node->has_surface_bssrdf()) {
current_shader->has_surface_bssrdf = true; current_shader->has_surface_bssrdf = true;
if (node->has_bssrdf_bump()) if (node->has_bssrdf_bump()) {
current_shader->has_bssrdf_bump = true; current_shader->has_bssrdf_bump = true;
} }
}
if (node->has_bump()) { if (node->has_bump()) {
current_shader->has_bump = true; current_shader->has_bump = true;
} }
@ -532,10 +551,11 @@ void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
} }
else { else {
foreach (ShaderInput *in, node->inputs) { foreach (ShaderInput *in, node->inputs) {
if (in->type() == SocketType::CLOSURE && in->link) if (in->type() == SocketType::CLOSURE && in->link) {
generated_shared_closure_nodes(root_node, in->link->parent, state, shared); generated_shared_closure_nodes(root_node, in->link->parent, state, shared);
} }
} }
}
} }
void SVMCompiler::find_aov_nodes_and_dependencies(ShaderNodeSet &aov_nodes, void SVMCompiler::find_aov_nodes_and_dependencies(ShaderNodeSet &aov_nodes,
@ -562,8 +582,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
CompilerState *state) CompilerState *state)
{ {
/* only generate once */ /* only generate once */
if (state->closure_done.find(node) != state->closure_done.end()) if (state->closure_done.find(node) != state->closure_done.end()) {
return; return;
}
state->closure_done.insert(node); state->closure_done.insert(node);
@ -574,8 +595,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
ShaderInput *facin = node->input("Fac"); ShaderInput *facin = node->input("Fac");
/* skip empty mix/add closure nodes */ /* skip empty mix/add closure nodes */
if (!cl1in->link && !cl2in->link) if (!cl1in->link && !cl2in->link) {
return; return;
}
if (facin && facin->link) { if (facin && facin->link) {
/* mix closure: generate instructions to compute mix weight */ /* mix closure: generate instructions to compute mix weight */
@ -691,12 +713,14 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
/* execute closures and their dependencies, no runtime checks /* execute closures and their dependencies, no runtime checks
* to skip closures here because was already optimized due to * to skip closures here because was already optimized due to
* fixed weight or add closure that always needs both */ * fixed weight or add closure that always needs both */
if (cl1in->link) if (cl1in->link) {
generate_multi_closure(root_node, cl1in->link->parent, state); generate_multi_closure(root_node, cl1in->link->parent, state);
if (cl2in->link) }
if (cl2in->link) {
generate_multi_closure(root_node, cl2in->link->parent, state); generate_multi_closure(root_node, cl2in->link->parent, state);
} }
} }
}
else { else {
generate_closure_node(node, state); generate_closure_node(node, state);
} }

@ -26,8 +26,9 @@ LookupTables::~LookupTables()
void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene) void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene)
{ {
if (!need_update()) if (!need_update()) {
return; return;
}
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@ -37,8 +38,9 @@ void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene)
VLOG_INFO << "Total " << lookup_tables.size() << " lookup tables."; VLOG_INFO << "Total " << lookup_tables.size() << " lookup tables.";
if (lookup_tables.size() > 0) if (lookup_tables.size() > 0) {
dscene->lookup_table.copy_to_device(); dscene->lookup_table.copy_to_device();
}
need_update_ = false; need_update_ = false;
} }
@ -76,9 +78,10 @@ size_t LookupTables::add_table(DeviceScene *dscene, vector<float> &data)
lookup_tables.insert(table, new_table); lookup_tables.insert(table, new_table);
break; break;
} }
else else {
new_table.offset = table->offset + table->size; new_table.offset = table->offset + table->size;
} }
}
if (table == lookup_tables.end()) { if (table == lookup_tables.end()) {
/* add at the end */ /* add at the end */

@ -290,8 +290,9 @@ bool RenderBuffers::copy_from_device()
{ {
DCHECK(params.pass_stride != -1); DCHECK(params.pass_stride != -1);
if (!buffer.device_pointer) if (!buffer.device_pointer) {
return false; return false;
}
buffer.copy_from_device(0, params.width * params.pass_stride, params.height); buffer.copy_from_device(0, params.width * params.pass_stride, params.height);

@ -273,10 +273,12 @@ void Session::thread_render()
profiler.stop(); profiler.stop();
/* progress update */ /* progress update */
if (progress.get_cancel()) if (progress.get_cancel()) {
progress.set_status(progress.get_cancel_message()); progress.set_status(progress.get_cancel_message());
else }
else {
progress.set_update(); progress.set_update();
}
} }
bool Session::is_session_thread_rendering() bool Session::is_session_thread_rendering()

@ -77,8 +77,9 @@ void EdgeDice::stitch_triangles(Subpatch &sub, int edge)
int outer_T = sub.edges[edge].T; int outer_T = sub.edges[edge].T;
int inner_T = ((edge % 2) == 0) ? Mv - 2 : Mu - 2; int inner_T = ((edge % 2) == 0) ? Mv - 2 : Mu - 2;
if (inner_T < 0 || outer_T < 0) if (inner_T < 0 || outer_T < 0) {
return; // XXX avoid crashes for Mu or Mv == 1, missing polygons return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
}
/* stitch together two arrays of verts with triangles. at each step, /* stitch together two arrays of verts with triangles. at each step,
* we compare using the next verts on both sides, to find the split * we compare using the next verts on both sides, to find the split
@ -104,11 +105,13 @@ void EdgeDice::stitch_triangles(Subpatch &sub, int edge)
mesh_P[sub.get_vert_along_grid_edge(edge, i + 1)]); mesh_P[sub.get_vert_along_grid_edge(edge, i + 1)]);
/* use smallest diagonal */ /* use smallest diagonal */
if (len1 < len2) if (len1 < len2) {
v2 = sub.get_vert_along_edge(edge, ++j); v2 = sub.get_vert_along_edge(edge, ++j);
else }
else {
v2 = sub.get_vert_along_grid_edge(edge, ++i); v2 = sub.get_vert_along_grid_edge(edge, ++i);
} }
}
add_triangle(sub.patch, v1, v0, v2); add_triangle(sub.patch, v1, v0, v2);
} }
@ -132,8 +135,9 @@ float3 QuadDice::eval_projected(Subpatch &sub, float u, float v)
float3 P; float3 P;
sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
if (params.camera) if (params.camera) {
P = transform_perspective(&params.camera->worldtoraster, P); P = transform_perspective(&params.camera->worldtoraster, P);
}
return P; return P;
} }
@ -186,9 +190,11 @@ float QuadDice::scale_factor(Subpatch &sub, int Mu, int Mv)
/* estimate area as 4x largest of 4 quads */ /* estimate area as 4x largest of 4 quads */
float3 P[3][3]; float3 P[3][3];
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++) {
P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f); P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f);
}
}
float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]); float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]); float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);

@ -25,8 +25,9 @@ static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4]
d1 += t * (d2 - d1); d1 += t * (d2 - d1);
*P = d0 + t * (d1 - d0); *P = d0 + t * (d1 - d0);
if (dt) if (dt) {
*dt = d1 - d0; *dt = d1 - d0;
}
} }
static void decasteljau_bicubic( static void decasteljau_bicubic(
@ -42,8 +43,9 @@ static void decasteljau_bicubic(
/* interpolate over v */ /* interpolate over v */
decasteljau_cubic(P, dv, v, ucp); decasteljau_cubic(P, dv, v, ucp);
if (du) if (du) {
decasteljau_cubic(du, NULL, v, utn); decasteljau_cubic(du, NULL, v, utn);
}
} }
/* Linear Quad Patch */ /* Linear Quad Patch */
@ -70,8 +72,9 @@ BoundBox LinearQuadPatch::bound()
{ {
BoundBox bbox = BoundBox::empty; BoundBox bbox = BoundBox::empty;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++) {
bbox.grow(hull[i]); bbox.grow(hull[i]);
}
return bbox; return bbox;
} }
@ -100,8 +103,9 @@ BoundBox BicubicPatch::bound()
{ {
BoundBox bbox = BoundBox::empty; BoundBox bbox = BoundBox::empty;
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++) {
bbox.grow(hull[i]); bbox.grow(hull[i]);
}
return bbox; return bbox;
} }

@ -30,8 +30,9 @@ float3 DiagSplit::to_world(Patch *patch, float2 uv)
float3 P; float3 P;
patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
if (params.camera) if (params.camera) {
P = transform_point(&params.objecttoworld, P); P = transform_point(&params.objecttoworld, P);
}
return P; return P;
} }

@ -56,29 +56,35 @@ DebugFlags::Metal::Metal()
void DebugFlags::CUDA::reset() void DebugFlags::CUDA::reset()
{ {
if (getenv("CYCLES_CUDA_ADAPTIVE_COMPILE") != NULL) if (getenv("CYCLES_CUDA_ADAPTIVE_COMPILE") != NULL) {
adaptive_compile = true; adaptive_compile = true;
}
} }
void DebugFlags::HIP::reset() void DebugFlags::HIP::reset()
{ {
if (getenv("CYCLES_HIP_ADAPTIVE_COMPILE") != NULL) if (getenv("CYCLES_HIP_ADAPTIVE_COMPILE") != NULL) {
adaptive_compile = true; adaptive_compile = true;
}
} }
void DebugFlags::Metal::reset() void DebugFlags::Metal::reset()
{ {
if (getenv("CYCLES_METAL_ADAPTIVE_COMPILE") != NULL) if (getenv("CYCLES_METAL_ADAPTIVE_COMPILE") != NULL) {
adaptive_compile = true; adaptive_compile = true;
}
if (auto str = getenv("CYCLES_METAL_LOCAL_ATOMIC_SORT")) if (auto str = getenv("CYCLES_METAL_LOCAL_ATOMIC_SORT")) {
use_local_atomic_sort = (atoi(str) != 0); use_local_atomic_sort = (atoi(str) != 0);
}
if (auto str = getenv("CYCLES_METAL_NANOVDB")) if (auto str = getenv("CYCLES_METAL_NANOVDB")) {
use_nanovdb = (atoi(str) != 0); use_nanovdb = (atoi(str) != 0);
}
if (auto str = getenv("CYCLES_METAL_ASYNC_PSO_CREATION")) if (auto str = getenv("CYCLES_METAL_ASYNC_PSO_CREATION")) {
use_async_pso_creation = (atoi(str) != 0); use_async_pso_creation = (atoi(str) != 0);
}
} }
DebugFlags::OptiX::OptiX() DebugFlags::OptiX::OptiX()

@ -120,10 +120,11 @@ void MD5Hash::process(const uint8_t *data /*[64]*/)
int i; int i;
X = xbuf; /* (dynamic only) */ X = xbuf; /* (dynamic only) */
for (i = 0; i < 16; ++i, xp += 4) for (i = 0; i < 16; ++i, xp += 4) {
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
} }
} }
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
@ -258,34 +259,39 @@ void MD5Hash::append(const uint8_t *data, int nbytes)
int offset = (count[0] >> 3) & 63; int offset = (count[0] >> 3) & 63;
uint32_t nbits = (uint32_t)(nbytes << 3); uint32_t nbits = (uint32_t)(nbytes << 3);
if (nbytes <= 0) if (nbytes <= 0) {
return; return;
}
/* Update the message length. */ /* Update the message length. */
count[1] += nbytes >> 29; count[1] += nbytes >> 29;
count[0] += nbits; count[0] += nbits;
if (count[0] < nbits) if (count[0] < nbits) {
count[1]++; count[1]++;
}
/* Process an initial partial block. */ /* Process an initial partial block. */
if (offset) { if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(buf + offset, p, copy); memcpy(buf + offset, p, copy);
if (offset + copy < 64) if (offset + copy < 64) {
return; return;
}
p += copy; p += copy;
left -= copy; left -= copy;
process(buf); process(buf);
} }
/* Process full blocks. */ /* Process full blocks. */
for (; left >= 64; p += 64, left -= 64) for (; left >= 64; p += 64, left -= 64) {
process(p); process(p);
}
/* Process a final partial block. */ /* Process a final partial block. */
if (left) if (left) {
memcpy(buf, p, left); memcpy(buf, p, left);
}
} }
void MD5Hash::append(const string &str) void MD5Hash::append(const string &str)
@ -331,16 +337,18 @@ void MD5Hash::finish(uint8_t digest[16])
int i; int i;
/* Save the length before padding. */ /* Save the length before padding. */
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i) {
data[i] = (uint8_t)(count[i >> 2] >> ((i & 3) << 3)); data[i] = (uint8_t)(count[i >> 2] >> ((i & 3) << 3));
}
/* Pad to 56 bytes mod 64. */ /* Pad to 56 bytes mod 64. */
append(pad, ((55 - (count[0] >> 3)) & 63) + 1); append(pad, ((55 - (count[0] >> 3)) & 63) + 1);
/* Append the length. */ /* Append the length. */
append(data, 8); append(data, 8);
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i) {
digest[i] = (uint8_t)(abcd[i >> 2] >> ((i & 3) << 3)); digest[i] = (uint8_t)(abcd[i >> 2] >> ((i & 3) << 3));
}
} }
string MD5Hash::get_hex() string MD5Hash::get_hex()

@ -337,19 +337,22 @@ void path_init(const string &path, const string &user_path)
string path_get(const string &sub) string path_get(const string &sub)
{ {
char *special = path_specials(sub); char *special = path_specials(sub);
if (special != NULL) if (special != NULL) {
return special; return special;
}
if (cached_path == "") if (cached_path == "") {
cached_path = path_dirname(Sysutil::this_program_path()); cached_path = path_dirname(Sysutil::this_program_path());
}
return path_join(cached_path, sub); return path_join(cached_path, sub);
} }
string path_user_get(const string &sub) string path_user_get(const string &sub)
{ {
if (cached_user_path == "") if (cached_user_path == "") {
cached_user_path = path_dirname(Sysutil::this_program_path()); cached_user_path = path_dirname(Sysutil::this_program_path());
}
return path_join(cached_user_path, sub); return path_join(cached_user_path, sub);
} }
@ -653,11 +656,13 @@ bool path_write_binary(const string &path, const vector<uint8_t> &binary)
/* write binary file from memory */ /* write binary file from memory */
FILE *f = path_fopen(path, "wb"); FILE *f = path_fopen(path, "wb");
if (!f) if (!f) {
return false; return false;
}
if (binary.size() > 0) if (binary.size() > 0) {
fwrite(&binary[0], sizeof(uint8_t), binary.size(), f); fwrite(&binary[0], sizeof(uint8_t), binary.size(), f);
}
fclose(f); fclose(f);
@ -703,8 +708,9 @@ bool path_read_text(const string &path, string &text)
{ {
vector<uint8_t> binary; vector<uint8_t> binary;
if (!path_exists(path) || !path_read_binary(path, binary)) if (!path_exists(path) || !path_read_binary(path, binary)) {
return false; return false;
}
const char *str = (const char *)&binary[0]; const char *str = (const char *)&binary[0];
size_t size = binary.size(); size_t size = binary.size();

@ -55,9 +55,11 @@ string string_printf(const char *format, ...)
bool string_iequals(const string &a, const string &b) bool string_iequals(const string &a, const string &b)
{ {
if (a.size() == b.size()) { if (a.size() == b.size()) {
for (size_t i = 0; i < a.size(); i++) for (size_t i = 0; i < a.size(); i++) {
if (toupper(a[i]) != toupper(b[i])) if (toupper(a[i]) != toupper(b[i])) {
return false; return false;
}
}
return true; return true;
} }
@ -167,10 +169,12 @@ string string_remove_trademark(const string &s)
string string_from_bool(bool var) string string_from_bool(bool var)
{ {
if (var) if (var) {
return "True"; return "True";
else }
else {
return "False"; return "False";
}
} }
string to_string(const char *str) string to_string(const char *str)
@ -240,10 +244,12 @@ string string_human_readable_size(size_t size)
suffix++; suffix++;
} }
if (*suffix != 'B') if (*suffix != 'B') {
return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix); return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
else }
else {
return string_printf("%zu", size); return string_printf("%zu", size);
}
} }
string string_human_readable_number(size_t num) string string_human_readable_number(size_t num)
@ -260,8 +266,9 @@ string string_human_readable_number(size_t num)
int i = -1; int i = -1;
while (num) { while (num) {
if (++i && i % 3 == 0) if (++i && i % 3 == 0) {
*(--p) = ','; *(--p) = ',';
}
*(--p) = '0' + (num % 10); *(--p) = '0' + (num % 10);

@ -129,10 +129,12 @@ void DedicatedTaskPool::push(TaskRunFunction &&task, bool front)
/* add task to queue */ /* add task to queue */
queue_mutex.lock(); queue_mutex.lock();
if (front) if (front) {
queue.emplace_front(std::move(task)); queue.emplace_front(std::move(task));
else }
else {
queue.emplace_back(std::move(task)); queue.emplace_back(std::move(task));
}
queue_cond.notify_one(); queue_cond.notify_one();
queue_mutex.unlock(); queue_mutex.unlock();
@ -142,8 +144,9 @@ void DedicatedTaskPool::wait()
{ {
thread_scoped_lock num_lock(num_mutex); thread_scoped_lock num_lock(num_mutex);
while (num) while (num) {
num_cond.wait(num_lock); num_cond.wait(num_lock);
}
} }
void DedicatedTaskPool::cancel() void DedicatedTaskPool::cancel()
@ -167,8 +170,9 @@ void DedicatedTaskPool::num_decrease(int done)
num -= done; num -= done;
assert(num >= 0); assert(num >= 0);
if (num == 0) if (num == 0) {
num_cond.notify_all(); num_cond.notify_all();
}
} }
void DedicatedTaskPool::num_increase() void DedicatedTaskPool::num_increase()
@ -182,8 +186,9 @@ bool DedicatedTaskPool::thread_wait_pop(TaskRunFunction &task)
{ {
thread_scoped_lock queue_lock(queue_mutex); thread_scoped_lock queue_lock(queue_mutex);
while (queue.empty() && !do_exit) while (queue.empty() && !do_exit) {
queue_cond.wait(queue_lock); queue_cond.wait(queue_lock);
}
if (queue.empty()) { if (queue.empty()) {
assert(do_exit); assert(do_exit);

@ -56,8 +56,9 @@ void time_sleep(double t)
/* get microseconds */ /* get microseconds */
int us = (int)(t * 1e6); int us = (int)(t * 1e6);
if (us > 0) if (us > 0) {
usleep(us); usleep(us);
}
} }
#endif #endif

@ -24,14 +24,16 @@ static bool projection_matrix4_inverse(float R[][4], float M[][4])
int pivot = i; int pivot = i;
float pivotsize = M[i][i]; float pivotsize = M[i][i];
if (pivotsize < 0) if (pivotsize < 0) {
pivotsize = -pivotsize; pivotsize = -pivotsize;
}
for (int j = i + 1; j < 4; j++) { for (int j = i + 1; j < 4; j++) {
float tmp = M[j][i]; float tmp = M[j][i];
if (tmp < 0) if (tmp < 0) {
tmp = -tmp; tmp = -tmp;
}
if (tmp > pivotsize) { if (tmp > pivotsize) {
pivot = j; pivot = j;
@ -39,8 +41,9 @@ static bool projection_matrix4_inverse(float R[][4], float M[][4])
} }
} }
if (UNLIKELY(pivotsize == 0.0f)) if (UNLIKELY(pivotsize == 0.0f)) {
return false; return false;
}
if (pivot != i) { if (pivot != i) {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
@ -70,8 +73,9 @@ static bool projection_matrix4_inverse(float R[][4], float M[][4])
for (int i = 3; i >= 0; --i) { for (int i = 3; i >= 0; --i) {
float f; float f;
if (UNLIKELY((f = M[i][i]) == 0.0f)) if (UNLIKELY((f = M[i][i]) == 0.0f)) {
return false; return false;
}
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
M[i][j] /= f; M[i][j] /= f;
@ -134,10 +138,12 @@ float4 transform_to_quat(const Transform &tfm)
else { else {
int i = 0; int i = 0;
if (tfm[1][1] > tfm[i][i]) if (tfm[1][1] > tfm[i][i]) {
i = 1; i = 1;
if (tfm[2][2] > tfm[i][i]) }
if (tfm[2][2] > tfm[i][i]) {
i = 2; i = 2;
}
int j = (i + 1) % 3; int j = (i + 1) % 3;
int k = (j + 1) % 3; int k = (j + 1) % 3;
@ -146,8 +152,9 @@ float4 transform_to_quat(const Transform &tfm)
double q[3]; double q[3];
q[i] = s * 0.5; q[i] = s * 0.5;
if (s != 0.0) if (s != 0.0) {
s = 0.5 / s; s = 0.5 / s;
}
double w = (double)(tfm[k][j] - tfm[j][k]) * s; double w = (double)(tfm[k][j] - tfm[j][k]) * s;
q[j] = (double)(tfm[j][i] + tfm[i][j]) * s; q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
@ -253,10 +260,11 @@ void transform_motion_decompose(DecomposedTransform *decomp, const Transform *mo
if (i > 0) { if (i > 0) {
/* Ensure rotation around shortest angle, negated quaternions are the same /* Ensure rotation around shortest angle, negated quaternions are the same
* but this means we don't have to do the check in quat_interpolate */ * but this means we don't have to do the check in quat_interpolate */
if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f) if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f) {
decomp[i].x = -decomp[i].x; decomp[i].x = -decomp[i].x;
} }
} }
}
/* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
* rotation interpolation when the scale goes to 0 for a time step. * rotation interpolation when the scale goes to 0 for a time step.

@ -113,9 +113,10 @@ static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[
/* Get triangle edge vectors */ /* Get triangle edge vectors */
int64_t tri_edges[3][3]; int64_t tri_edges[3][3];
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++) {
tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j]; tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j];
} }
}
/* Triangle normal */ /* Triangle normal */
crossProduct(axes[3], tri_edges[0], tri_edges[1]); crossProduct(axes[3], tri_edges[0], tri_edges[1]);
@ -171,8 +172,9 @@ CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3],
cube_proj.origin = dotProduct(axes[axis], cube[0]); cube_proj.origin = dotProduct(axes[axis], cube[0]);
/* 3 direction vectors */ /* 3 direction vectors */
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++) {
cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]); cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]);
}
/* Offsets of 2 ends of cube projection */ /* Offsets of 2 ends of cube projection */
int64_t max = 0; int64_t max = 0;
@ -201,13 +203,15 @@ CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3],
inherit->tri_proj[axis][0] = vts[0]; inherit->tri_proj[axis][0] = vts[0];
inherit->tri_proj[axis][1] = vts[0]; inherit->tri_proj[axis][1] = vts[0];
for (i = 1; i < 3; i++) { for (i = 1; i < 3; i++) {
if (vts[i] < inherit->tri_proj[axis][0]) if (vts[i] < inherit->tri_proj[axis][0]) {
inherit->tri_proj[axis][0] = vts[i]; inherit->tri_proj[axis][0] = vts[i];
}
if (vts[i] > inherit->tri_proj[axis][1]) if (vts[i] > inherit->tri_proj[axis][1]) {
inherit->tri_proj[axis][1] = vts[i]; inherit->tri_proj[axis][1] = vts[i];
} }
} }
}
} }
/** /**
@ -223,8 +227,9 @@ CubeTriangleIsect::CubeTriangleIsect(CubeTriangleIsect *parent)
for (int i = 0; i < NUM_AXES; i++) { for (int i = 0; i < NUM_AXES; i++) {
cubeProj[i].origin = parent->cubeProj[i].origin; cubeProj[i].origin = parent->cubeProj[i].origin;
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++) {
cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1; cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1;
}
cubeProj[i].min = parent->cubeProj[i].min >> 1; cubeProj[i].min = parent->cubeProj[i].min >> 1;
cubeProj[i].max = parent->cubeProj[i].max >> 1; cubeProj[i].max = parent->cubeProj[i].max >> 1;
@ -337,14 +342,16 @@ float CubeTriangleIsect::getIntersectionPrimary(int edgeInd) const
int64_t d = proj1 - proj0; int64_t d = proj1 - proj0;
double alpha; double alpha;
if (d == 0) if (d == 0) {
alpha = 0.5; alpha = 0.5;
}
else { else {
alpha = (double)((proj2 - proj0)) / (double)d; alpha = (double)((proj2 - proj0)) / (double)d;
if (alpha < 0 || alpha > 1) if (alpha < 0 || alpha > 1) {
alpha = 0.5; alpha = 0.5;
} }
}
return (float)alpha; return (float)alpha;
} }

@ -54,9 +54,10 @@ class DualConInputReader : public ModelReader {
/* initialize maxsize */ /* initialize maxsize */
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
float d = max[i] - min[i]; float d = max[i] - min[i];
if (d > maxsize) if (d > maxsize) {
maxsize = d; maxsize = d;
} }
}
/* redo the bounds */ /* redo the bounds */
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -64,15 +65,17 @@ class DualConInputReader : public ModelReader {
max[i] = (max[i] + min[i]) / 2 + maxsize / 2; max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) {
min[i] -= maxsize * (1 / scale - 1) / 2; min[i] -= maxsize * (1 / scale - 1) / 2;
}
maxsize *= 1 / scale; maxsize *= 1 / scale;
} }
Triangle *getNextTriangle() Triangle *getNextTriangle()
{ {
if (curtri == input_mesh->tottri) if (curtri == input_mesh->tottri) {
return NULL; return NULL;
}
Triangle *t = new Triangle(); Triangle *t = new Triangle();
@ -97,8 +100,9 @@ class DualConInputReader : public ModelReader {
int getNextTriangle(int t[3]) int getNextTriangle(int t[3])
{ {
if (curtri == input_mesh->tottri) if (curtri == input_mesh->tottri) {
return 0; return 0;
}
unsigned int *tr = GET_TRI(input_mesh, curtri); unsigned int *tr = GET_TRI(input_mesh, curtri);
t[0] = tr[0]; t[0] = tr[0];

@ -325,17 +325,19 @@ void Octree::addTriangle(Triangle *trian, int triind)
/* Project the triangle's coordinates into the grid */ /* Project the triangle's coordinates into the grid */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++) {
trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range; trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range;
} }
}
/* Generate projections */ /* Generate projections */
int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}}; int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}};
int64_t trig[3][3]; int64_t trig[3][3];
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++) {
trig[i][j] = (int64_t)(trian->vt[i][j]); trig[i][j] = (int64_t)(trian->vt[i][j]);
} }
}
/* Add triangle to the octree */ /* Add triangle to the octree */
int64_t errorvec = (int64_t)(0); int64_t errorvec = (int64_t)(0);
@ -379,23 +381,28 @@ InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int
/* Pruning using intersection test */ /* Pruning using intersection test */
if (subp->isIntersecting()) { if (subp->isIntersecting()) {
if (!node->has_child(i)) { if (!node->has_child(i)) {
if (height == 1) if (height == 1) {
node = addLeafChild(node, i, count, createLeaf(0)); node = addLeafChild(node, i, count, createLeaf(0));
else }
else {
node = addInternalChild(node, i, count, createInternal(0)); node = addInternalChild(node, i, count, createInternal(0));
} }
}
Node *chd = node->get_child(count); Node *chd = node->get_child(count);
if (node->is_child_leaf(i)) if (node->is_child_leaf(i)) {
node->set_child(count, (Node *)updateCell(&chd->leaf, subp)); node->set_child(count, (Node *)updateCell(&chd->leaf, subp));
else }
else {
node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1)); node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1));
} }
} }
}
if (node->has_child(i)) if (node->has_child(i)) {
count++; count++;
} }
}
delete subp; delete subp;
@ -445,10 +452,12 @@ void Octree::preparePrimalEdgesMask(InternalNode *node)
int count = 0; int count = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (node->has_child(i)) { if (node->has_child(i)) {
if (node->is_child_leaf(i)) if (node->is_child_leaf(i)) {
createPrimalEdgesMask(&node->get_child(count)->leaf); createPrimalEdgesMask(&node->get_child(count)->leaf);
else }
else {
preparePrimalEdgesMask(&node->get_child(count)->internal); preparePrimalEdgesMask(&node->get_child(count)->internal);
}
count++; count++;
} }
@ -2016,8 +2025,9 @@ int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int th
// cells // cells
LeafNode *cs[2]; LeafNode *cs[2];
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++) {
cs[j] = locateLeaf(cst[j]); cs[j] = locateLeaf(cst[j]);
}
// Middle sign // Middle sign
int s = getSign(cs[0], 0); int s = getSign(cs[0], 0);
@ -2195,8 +2205,9 @@ static void solve_least_squares(const float halfA[],
b2 = b2 + A * -mp; b2 = b2 + A * -mp;
result = pinv * b2 + mp; result = pinv * b2 + mp;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) {
rvalue[i] = result(i); rvalue[i] = result(i);
}
} }
static void mass_point(float mp[3], const float pts[12][3], const int parity[12]) static void mass_point(float mp[3], const float pts[12][3], const int parity[12])

@ -149,10 +149,11 @@ static void linear_solver_variables_to_vector(LinearSolver *solver)
for (int i = 0; i < solver->num_variables; i++) { for (int i = 0; i < solver->num_variables; i++) {
LinearSolver::Variable *v = &solver->variable[i]; LinearSolver::Variable *v = &solver->variable[i];
if (!v->locked) { if (!v->locked) {
for (int j = 0; j < num_rhs; j++) for (int j = 0; j < num_rhs; j++) {
solver->x[j][v->index] = v->value[j]; solver->x[j][v->index] = v->value[j];
} }
} }
}
} }
static void linear_solver_vector_to_variables(LinearSolver *solver) static void linear_solver_vector_to_variables(LinearSolver *solver)
@ -162,10 +163,11 @@ static void linear_solver_vector_to_variables(LinearSolver *solver)
for (int i = 0; i < solver->num_variables; i++) { for (int i = 0; i < solver->num_variables; i++) {
LinearSolver::Variable *v = &solver->variable[i]; LinearSolver::Variable *v = &solver->variable[i];
if (!v->locked) { if (!v->locked) {
for (int j = 0; j < num_rhs; j++) for (int j = 0; j < num_rhs; j++) {
v->value[j] = solver->x[j][v->index]; v->value[j] = solver->x[j][v->index];
} }
} }
}
} }
/* Matrix */ /* Matrix */
@ -177,11 +179,13 @@ static void linear_solver_ensure_matrix_construct(LinearSolver *solver)
int n = 0; int n = 0;
for (int i = 0; i < solver->num_variables; i++) { for (int i = 0; i < solver->num_variables; i++) {
if (solver->variable[i].locked) if (solver->variable[i].locked) {
solver->variable[i].index = ~0; solver->variable[i].index = ~0;
else }
else {
solver->variable[i].index = n++; solver->variable[i].index = n++;
} }
}
int m = (solver->num_rows == 0) ? n : solver->num_rows; int m = (solver->num_rows == 0) ? n : solver->num_rows;
@ -210,16 +214,19 @@ static void linear_solver_ensure_matrix_construct(LinearSolver *solver)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value) void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
{ {
if (solver->state == LinearSolver::STATE_MATRIX_SOLVED) if (solver->state == LinearSolver::STATE_MATRIX_SOLVED) {
return; return;
}
linear_solver_ensure_matrix_construct(solver); linear_solver_ensure_matrix_construct(solver);
if (!solver->least_squares && solver->variable[row].locked) if (!solver->least_squares && solver->variable[row].locked) {
; ;
}
else if (solver->variable[col].locked) { else if (solver->variable[col].locked) {
if (!solver->least_squares) if (!solver->least_squares) {
row = solver->variable[row].index; row = solver->variable[row].index;
}
LinearSolver::Coeff coeff; LinearSolver::Coeff coeff;
coeff.index = row; coeff.index = row;
@ -227,8 +234,9 @@ void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double
solver->variable[col].a.push_back(coeff); solver->variable[col].a.push_back(coeff);
} }
else { else {
if (!solver->least_squares) if (!solver->least_squares) {
row = solver->variable[row].index; row = solver->variable[row].index;
}
col = solver->variable[col].index; col = solver->variable[col].index;
/* direct insert into matrix is too slow, so use triplets */ /* direct insert into matrix is too slow, so use triplets */
@ -257,8 +265,9 @@ void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int in
bool EIG_linear_solver_solve(LinearSolver *solver) bool EIG_linear_solver_solve(LinearSolver *solver)
{ {
/* nothing to solve, perhaps all variables were locked */ /* nothing to solve, perhaps all variables were locked */
if (solver->m == 0 || solver->n == 0) if (solver->m == 0 || solver->n == 0) {
return true; return true;
}
bool result = true; bool result = true;
@ -271,8 +280,9 @@ bool EIG_linear_solver_solve(LinearSolver *solver)
solver->Mtriplets.clear(); solver->Mtriplets.clear();
/* create least squares matrix */ /* create least squares matrix */
if (solver->least_squares) if (solver->least_squares) {
solver->MtM = solver->M.transpose() * solver->M; solver->MtM = solver->M.transpose() * solver->M;
}
/* convert M to compressed column format */ /* convert M to compressed column format */
EigenSparseMatrix &M = (solver->least_squares) ? solver->MtM : solver->M; EigenSparseMatrix &M = (solver->least_squares) ? solver->MtM : solver->M;
@ -300,10 +310,11 @@ bool EIG_linear_solver_solve(LinearSolver *solver)
if (variable->locked) { if (variable->locked) {
std::vector<LinearSolver::Coeff> &a = variable->a; std::vector<LinearSolver::Coeff> &a = variable->a;
for (int j = 0; j < a.size(); j++) for (int j = 0; j < a.size(); j++) {
b[a[j].index] -= a[j].value * variable->value[rhs]; b[a[j].index] -= a[j].value * variable->value[rhs];
} }
} }
}
/* solve */ /* solve */
if (solver->least_squares) { if (solver->least_squares) {
@ -315,17 +326,20 @@ bool EIG_linear_solver_solve(LinearSolver *solver)
solver->x[rhs] = solver->sparseLU->solve(b); solver->x[rhs] = solver->sparseLU->solve(b);
} }
if (solver->sparseLU->info() != Eigen::Success) if (solver->sparseLU->info() != Eigen::Success) {
result = false; result = false;
} }
}
if (result) if (result) {
linear_solver_vector_to_variables(solver); linear_solver_vector_to_variables(solver);
} }
}
/* clear for next solve */ /* clear for next solve */
for (int rhs = 0; rhs < solver->num_rhs; rhs++) for (int rhs = 0; rhs < solver->num_rhs; rhs++) {
solver->b[rhs].setZero(solver->m); solver->b[rhs].setZero(solver->m);
}
return result; return result;
} }
@ -336,9 +350,11 @@ void EIG_linear_solver_print_matrix(LinearSolver *solver)
{ {
std::cout << "A:" << solver->M << std::endl; std::cout << "A:" << solver->M << std::endl;
for (int rhs = 0; rhs < solver->num_rhs; rhs++) for (int rhs = 0; rhs < solver->num_rhs; rhs++) {
std::cout << "b " << rhs << ":" << solver->b[rhs] << std::endl; std::cout << "b " << rhs << ":" << solver->b[rhs] << std::endl;
}
if (solver->MtM.rows() && solver->MtM.cols()) if (solver->MtM.rows() && solver->MtM.cols()) {
std::cout << "AtA:" << solver->MtM << std::endl; std::cout << "AtA:" << solver->MtM << std::endl;
}
} }

@ -64,8 +64,9 @@ bool test_codec_video_by_codecid(AVCodecID codec_id, AVPixelFormat pixelformat)
{ {
bool result = false; bool result = false;
const AVCodec *codec = avcodec_find_encoder(codec_id); const AVCodec *codec = avcodec_find_encoder(codec_id);
if (codec) if (codec) {
result = test_vcodec(codec, pixelformat); result = test_vcodec(codec, pixelformat);
}
return result; return result;
} }
@ -73,8 +74,9 @@ bool test_codec_video_by_name(const char *codecname, AVPixelFormat pixelformat)
{ {
bool result = false; bool result = false;
const AVCodec *codec = avcodec_find_encoder_by_name(codecname); const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
if (codec) if (codec) {
result = test_vcodec(codec, pixelformat); result = test_vcodec(codec, pixelformat);
}
return result; return result;
} }
@ -82,8 +84,9 @@ bool test_codec_audio_by_codecid(AVCodecID codec_id, AVSampleFormat fmt)
{ {
bool result = false; bool result = false;
const AVCodec *codec = avcodec_find_encoder(codec_id); const AVCodec *codec = avcodec_find_encoder(codec_id);
if (codec) if (codec) {
result = test_acodec(codec, fmt); result = test_acodec(codec, fmt);
}
return result; return result;
} }
@ -91,8 +94,9 @@ bool test_codec_audio_by_name(const char *codecname, AVSampleFormat fmt)
{ {
bool result = false; bool result = false;
const AVCodec *codec = avcodec_find_encoder_by_name(codecname); const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
if (codec) if (codec) {
result = test_acodec(codec, fmt); result = test_acodec(codec, fmt);
}
return result; return result;
} }

@ -101,10 +101,12 @@ void IK_QJacobian::Invert()
m_svd_v = svd.matrixV(); m_svd_v = svd.matrixV();
} }
if (m_sdls) if (m_sdls) {
InvertSDLS(); InvertSDLS();
else }
else {
InvertDLS(); InvertDLS();
}
} }
bool IK_QJacobian::ComputeNullProjection() bool IK_QJacobian::ComputeNullProjection()
@ -113,39 +115,49 @@ bool IK_QJacobian::ComputeNullProjection()
// compute null space projection based on V // compute null space projection based on V
int i, j, rank = 0; int i, j, rank = 0;
for (i = 0; i < m_svd_w.size(); i++) for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] > epsilon) if (m_svd_w[i] > epsilon) {
rank++; rank++;
}
}
if (rank < m_task_size) if (rank < m_task_size) {
return false; return false;
}
MatrixXd basis(m_svd_v.rows(), rank); MatrixXd basis(m_svd_v.rows(), rank);
int b = 0; int b = 0;
for (i = 0; i < m_svd_w.size(); i++) for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] > epsilon) { if (m_svd_w[i] > epsilon) {
for (j = 0; j < m_svd_v.rows(); j++) for (j = 0; j < m_svd_v.rows(); j++) {
basis(j, b) = m_svd_v(j, i); basis(j, b) = m_svd_v(j, i);
}
b++; b++;
} }
}
m_nullspace = basis * basis.transpose(); m_nullspace = basis * basis.transpose();
for (i = 0; i < m_nullspace.rows(); i++) for (i = 0; i < m_nullspace.rows(); i++) {
for (j = 0; j < m_nullspace.cols(); j++) for (j = 0; j < m_nullspace.cols(); j++) {
if (i == j) if (i == j) {
m_nullspace(i, j) = 1.0 - m_nullspace(i, j); m_nullspace(i, j) = 1.0 - m_nullspace(i, j);
else }
else {
m_nullspace(i, j) = -m_nullspace(i, j); m_nullspace(i, j) = -m_nullspace(i, j);
}
}
}
return true; return true;
} }
void IK_QJacobian::SubTask(IK_QJacobian &jacobian) void IK_QJacobian::SubTask(IK_QJacobian &jacobian)
{ {
if (!ComputeNullProjection()) if (!ComputeNullProjection()) {
return; return;
}
// restrict lower priority jacobian // restrict lower priority jacobian
jacobian.Restrict(m_d_theta, m_nullspace); jacobian.Restrict(m_d_theta, m_nullspace);
@ -157,8 +169,9 @@ void IK_QJacobian::SubTask(IK_QJacobian &jacobian)
// SDLS, to avoid shaking when the primary task is near singularities, // SDLS, to avoid shaking when the primary task is near singularities,
// doesn't work well at all // doesn't work well at all
int i; int i;
for (i = 0; i < m_d_theta.size(); i++) for (i = 0; i < m_d_theta.size(); i++) {
m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i); m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
}
} }
void IK_QJacobian::Restrict(VectorXd &d_theta, MatrixXd &nullspace) void IK_QJacobian::Restrict(VectorXd &d_theta, MatrixXd &nullspace)
@ -209,8 +222,9 @@ void IK_QJacobian::InvertSDLS()
} }
for (i = 0; i < m_svd_w.size(); i++) { for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] <= epsilon) if (m_svd_w[i] <= epsilon) {
continue; continue;
}
double wInv = 1.0 / m_svd_w[i]; double wInv = 1.0 / m_svd_w[i];
double alpha = 0.0; double alpha = 0.0;
@ -246,16 +260,18 @@ void IK_QJacobian::InvertSDLS()
// find largest absolute dTheta // find largest absolute dTheta
// multiply with weight to prevent unnecessary damping // multiply with weight to prevent unnecessary damping
abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j]; abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
if (abs_dtheta > max_dtheta) if (abs_dtheta > max_dtheta) {
max_dtheta = abs_dtheta; max_dtheta = abs_dtheta;
} }
}
M *= wInv; M *= wInv;
// compute damping term and damp the dTheta's // compute damping term and damp the dTheta's
double gamma = max_angle_change; double gamma = max_angle_change;
if (N < M) if (N < M) {
gamma *= N / M; gamma *= N / M;
}
double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0; double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
@ -265,15 +281,17 @@ void IK_QJacobian::InvertSDLS()
// better to go a little to slow than to far // better to go a little to slow than to far
double dofdamp = damp / m_weight[j]; double dofdamp = damp / m_weight[j];
if (dofdamp > 1.0) if (dofdamp > 1.0) {
dofdamp = 1.0; dofdamp = 1.0;
}
m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j]; m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
} }
if (damp < m_min_damp) if (damp < m_min_damp) {
m_min_damp = damp; m_min_damp = damp;
} }
}
// weight + prevent from doing angle updates with angles > max_angle_change // weight + prevent from doing angle updates with angles > max_angle_change
double max_angle = 0.0, abs_angle; double max_angle = 0.0, abs_angle;
@ -283,16 +301,18 @@ void IK_QJacobian::InvertSDLS()
abs_angle = fabs(m_d_theta[j]); abs_angle = fabs(m_d_theta[j]);
if (abs_angle > max_angle) if (abs_angle > max_angle) {
max_angle = abs_angle; max_angle = abs_angle;
} }
}
if (max_angle > max_angle_change) { if (max_angle > max_angle_change) {
double damp = (max_angle_change) / (max_angle_change + max_angle); double damp = (max_angle_change) / (max_angle_change + max_angle);
for (j = 0; j < m_dof; j++) for (j = 0; j < m_dof; j++) {
m_d_theta[j] *= damp; m_d_theta[j] *= damp;
} }
}
} }
void IK_QJacobian::InvertDLS() void IK_QJacobian::InvertDLS()
@ -322,26 +342,31 @@ void IK_QJacobian::InvertDLS()
double w_min = std::numeric_limits<double>::max(); double w_min = std::numeric_limits<double>::max();
for (i = 0; i < m_svd_w.size(); i++) { for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
w_min = m_svd_w[i]; w_min = m_svd_w[i];
} }
}
// compute lambda damping term // compute lambda damping term
double d = x_length / max_angle_change; double d = x_length / max_angle_change;
double lambda; double lambda;
if (w_min <= d / 2) if (w_min <= d / 2) {
lambda = d / 2; lambda = d / 2;
else if (w_min < d) }
else if (w_min < d) {
lambda = sqrt(w_min * (d - w_min)); lambda = sqrt(w_min * (d - w_min));
else }
else {
lambda = 0.0; lambda = 0.0;
}
lambda *= lambda; lambda *= lambda;
if (lambda > 10) if (lambda > 10) {
lambda = 10; lambda = 10;
}
// immediately multiply with Beta, so we can do matrix*vector products // immediately multiply with Beta, so we can do matrix*vector products
// rather than matrix*matrix products // rather than matrix*matrix products
@ -358,13 +383,15 @@ void IK_QJacobian::InvertDLS()
// compute V*Winv*Ut*Beta // compute V*Winv*Ut*Beta
m_svd_u_beta[i] *= wInv; m_svd_u_beta[i] *= wInv;
for (j = 0; j < m_d_theta.size(); j++) for (j = 0; j < m_d_theta.size(); j++) {
m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i]; m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i];
} }
} }
}
for (j = 0; j < m_d_theta.size(); j++) for (j = 0; j < m_d_theta.size(); j++) {
m_d_theta[j] *= m_weight[j]; m_d_theta[j] *= m_weight[j];
}
} }
void IK_QJacobian::Lock(int dof_id, double delta) void IK_QJacobian::Lock(int dof_id, double delta)
@ -392,9 +419,10 @@ double IK_QJacobian::AngleUpdateNorm() const
for (i = 0; i < m_d_theta.size(); i++) { for (i = 0; i < m_d_theta.size(); i++) {
dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]); dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]);
if (dtheta_abs > mx) if (dtheta_abs > mx) {
mx = dtheta_abs; mx = dtheta_abs;
} }
}
return mx; return mx;
} }

@ -23,13 +23,16 @@ double IK_QJacobianSolver::ComputeScale()
std::vector<IK_QSegment *>::iterator seg; std::vector<IK_QSegment *>::iterator seg;
double length = 0.0f; double length = 0.0f;
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
length += (*seg)->MaxExtension(); length += (*seg)->MaxExtension();
}
if (length == 0.0) if (length == 0.0) {
return 1.0; return 1.0;
else }
else {
return 1.0 / length; return 1.0 / length;
}
} }
void IK_QJacobianSolver::Scale(double scale, std::list<IK_QTask *> &tasks) void IK_QJacobianSolver::Scale(double scale, std::list<IK_QTask *> &tasks)
@ -37,11 +40,13 @@ void IK_QJacobianSolver::Scale(double scale, std::list<IK_QTask *> &tasks)
std::list<IK_QTask *>::iterator task; std::list<IK_QTask *>::iterator task;
std::vector<IK_QSegment *>::iterator seg; std::vector<IK_QSegment *>::iterator seg;
for (task = tasks.begin(); task != tasks.end(); task++) for (task = tasks.begin(); task != tasks.end(); task++) {
(*task)->Scale(scale); (*task)->Scale(scale);
}
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
(*seg)->Scale(scale); (*seg)->Scale(scale);
}
m_rootmatrix.translation() *= scale; m_rootmatrix.translation() *= scale;
m_goal *= scale; m_goal *= scale;
@ -53,8 +58,9 @@ void IK_QJacobianSolver::AddSegmentList(IK_QSegment *seg)
m_segments.push_back(seg); m_segments.push_back(seg);
IK_QSegment *child; IK_QSegment *child;
for (child = seg->Child(); child; child = child->Sibling()) for (child = seg->Child(); child; child = child->Sibling()) {
AddSegmentList(child); AddSegmentList(child);
}
} }
bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks) bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
@ -71,8 +77,9 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
num_dof += (*seg)->NumberOfDoF(); num_dof += (*seg)->NumberOfDoF();
} }
if (num_dof == 0) if (num_dof == 0) {
return false; return false;
}
// compute task ids and assign weights to task // compute task ids and assign weights to task
int primary_size = 0; int primary_size = 0;
@ -96,39 +103,47 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
} }
} }
if (primary_size == 0 || FuzzyZero(primary_weight)) if (primary_size == 0 || FuzzyZero(primary_weight)) {
return false; return false;
}
m_secondary_enabled = (secondary > 0); m_secondary_enabled = (secondary > 0);
// rescale weights of tasks to sum up to 1 // rescale weights of tasks to sum up to 1
double primary_rescale = 1.0 / primary_weight; double primary_rescale = 1.0 / primary_weight;
double secondary_rescale; double secondary_rescale;
if (FuzzyZero(secondary_weight)) if (FuzzyZero(secondary_weight)) {
secondary_rescale = 0.0; secondary_rescale = 0.0;
else }
else {
secondary_rescale = 1.0 / secondary_weight; secondary_rescale = 1.0 / secondary_weight;
}
for (task = tasks.begin(); task != tasks.end(); task++) { for (task = tasks.begin(); task != tasks.end(); task++) {
IK_QTask *qtask = *task; IK_QTask *qtask = *task;
if (qtask->Primary()) if (qtask->Primary()) {
qtask->SetWeight(qtask->Weight() * primary_rescale); qtask->SetWeight(qtask->Weight() * primary_rescale);
else }
else {
qtask->SetWeight(qtask->Weight() * secondary_rescale); qtask->SetWeight(qtask->Weight() * secondary_rescale);
} }
}
// set matrix sizes // set matrix sizes
m_jacobian.ArmMatrices(num_dof, primary_size); m_jacobian.ArmMatrices(num_dof, primary_size);
if (secondary > 0) if (secondary > 0) {
m_jacobian_sub.ArmMatrices(num_dof, secondary_size); m_jacobian_sub.ArmMatrices(num_dof, secondary_size);
}
// set dof weights // set dof weights
int i; int i;
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
for (i = 0; i < (*seg)->NumberOfDoF(); i++) for (i = 0; i < (*seg)->NumberOfDoF(); i++) {
m_jacobian.SetDoFWeight((*seg)->DoFId() + i, (*seg)->Weight(i)); m_jacobian.SetDoFWeight((*seg)->DoFId() + i, (*seg)->Weight(i));
}
}
return true; return true;
} }
@ -150,16 +165,19 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
// solving gives predictable solutions by rotating towards the solution, // solving gives predictable solutions by rotating towards the solution,
// and calling it afterwards ensures the solution is exact. // and calling it afterwards ensures the solution is exact.
if (!m_poleconstraint) if (!m_poleconstraint) {
return; return;
}
// disable pole vector constraint in case of multiple position tasks // disable pole vector constraint in case of multiple position tasks
std::list<IK_QTask *>::iterator task; std::list<IK_QTask *>::iterator task;
int positiontasks = 0; int positiontasks = 0;
for (task = tasks.begin(); task != tasks.end(); task++) for (task = tasks.begin(); task != tasks.end(); task++) {
if ((*task)->PositionTask()) if ((*task)->PositionTask()) {
positiontasks++; positiontasks++;
}
}
if (positiontasks >= 2) { if (positiontasks >= 2) {
m_poleconstraint = false; m_poleconstraint = false;
@ -200,8 +218,9 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
m_poleangle = angle(mat.row(1), polemat.row(1)); m_poleangle = angle(mat.row(1), polemat.row(1));
double dt = rootz.dot(mat.row(1) * cos(m_poleangle) + mat.row(0) * sin(m_poleangle)); double dt = rootz.dot(mat.row(1) * cos(m_poleangle) + mat.row(0) * sin(m_poleangle));
if (dt > 0.0) if (dt > 0.0) {
m_poleangle = -m_poleangle; m_poleangle = -m_poleangle;
}
// solve again, with the pole angle we just computed // solve again, with the pole angle we just computed
m_getpoleangle = false; m_getpoleangle = false;
@ -259,16 +278,18 @@ bool IK_QJacobianSolver::UpdateAngles(double &norm)
minseg->Lock(mindof, m_jacobian, mindelta); minseg->Lock(mindof, m_jacobian, mindelta);
locked = true; locked = true;
if (minabsdelta > norm) if (minabsdelta > norm) {
norm = minabsdelta; norm = minabsdelta;
} }
}
if (locked == false) if (locked == false) {
// no locking done, last inner iteration, apply the angles // no locking done, last inner iteration, apply the angles
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) { for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
(*seg)->UnLock(); (*seg)->UnLock();
(*seg)->UpdateAngleApply(); (*seg)->UpdateAngleApply();
} }
}
// signal if another inner iteration is needed // signal if another inner iteration is needed
return locked; return locked;
@ -298,11 +319,13 @@ bool IK_QJacobianSolver::Solve(IK_QSegment *root,
// compute jacobian // compute jacobian
for (task = tasks.begin(); task != tasks.end(); task++) { for (task = tasks.begin(); task != tasks.end(); task++) {
if ((*task)->Primary()) if ((*task)->Primary()) {
(*task)->ComputeJacobian(m_jacobian); (*task)->ComputeJacobian(m_jacobian);
else }
else {
(*task)->ComputeJacobian(m_jacobian_sub); (*task)->ComputeJacobian(m_jacobian_sub);
} }
}
double norm = 0.0; double norm = 0.0;
@ -310,9 +333,10 @@ bool IK_QJacobianSolver::Solve(IK_QSegment *root,
// invert jacobian // invert jacobian
try { try {
m_jacobian.Invert(); m_jacobian.Invert();
if (m_secondary_enabled) if (m_secondary_enabled) {
m_jacobian.SubTask(m_jacobian_sub); m_jacobian.SubTask(m_jacobian_sub);
} }
}
catch (...) { catch (...) {
fprintf(stderr, "IK Exception\n"); fprintf(stderr, "IK Exception\n");
return false; return false;
@ -323,13 +347,15 @@ bool IK_QJacobianSolver::Solve(IK_QSegment *root,
// unlock segments again after locking in clamping loop // unlock segments again after locking in clamping loop
std::vector<IK_QSegment *>::iterator seg; std::vector<IK_QSegment *>::iterator seg;
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
(*seg)->UnLock(); (*seg)->UnLock();
}
// compute angle update norm // compute angle update norm
double maxnorm = m_jacobian.AngleUpdateNorm(); double maxnorm = m_jacobian.AngleUpdateNorm();
if (maxnorm > norm) if (maxnorm > norm) {
norm = maxnorm; norm = maxnorm;
}
// check for convergence // check for convergence
if (norm < 1e-3 && iterations > 10) { if (norm < 1e-3 && iterations > 10) {
@ -338,8 +364,9 @@ bool IK_QJacobianSolver::Solve(IK_QSegment *root,
} }
} }
if (m_poleconstraint) if (m_poleconstraint) {
root->PrependBasis(m_rootmatrix.linear()); root->PrependBasis(m_rootmatrix.linear());
}
Scale(1.0f / scale, tasks); Scale(1.0f / scale, tasks);

@ -40,8 +40,9 @@ void IK_QSegment::Reset()
m_translation = m_orig_translation; m_translation = m_orig_translation;
SetBasis(m_basis); SetBasis(m_basis);
for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
seg->Reset(); seg->Reset();
}
} }
void IK_QSegment::SetTransform(const Vector3d &start, void IK_QSegment::SetTransform(const Vector3d &start,
@ -73,20 +74,24 @@ Vector3d IK_QSegment::TranslationChange() const
IK_QSegment::~IK_QSegment() IK_QSegment::~IK_QSegment()
{ {
if (m_parent) if (m_parent) {
m_parent->RemoveChild(this); m_parent->RemoveChild(this);
}
for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
seg->m_parent = NULL; seg->m_parent = NULL;
}
} }
void IK_QSegment::SetParent(IK_QSegment *parent) void IK_QSegment::SetParent(IK_QSegment *parent)
{ {
if (m_parent == parent) if (m_parent == parent) {
return; return;
}
if (m_parent) if (m_parent) {
m_parent->RemoveChild(this); m_parent->RemoveChild(this);
}
if (parent) { if (parent) {
m_sibling = parent->m_child; m_sibling = parent->m_child;
@ -103,19 +108,23 @@ void IK_QSegment::SetComposite(IK_QSegment *seg)
void IK_QSegment::RemoveChild(IK_QSegment *child) void IK_QSegment::RemoveChild(IK_QSegment *child)
{ {
if (m_child == NULL) if (m_child == NULL) {
return; return;
else if (m_child == child) }
else if (m_child == child) {
m_child = m_child->m_sibling; m_child = m_child->m_sibling;
}
else { else {
IK_QSegment *seg = m_child; IK_QSegment *seg = m_child;
while (seg->m_sibling != child) while (seg->m_sibling != child) {
seg = seg->m_sibling; seg = seg->m_sibling;
}
if (child == seg->m_sibling) if (child == seg->m_sibling) {
seg->m_sibling = child->m_sibling; seg->m_sibling = child->m_sibling;
} }
}
} }
void IK_QSegment::UpdateTransform(const Affine3d &global) void IK_QSegment::UpdateTransform(const Affine3d &global)
@ -128,8 +137,9 @@ void IK_QSegment::UpdateTransform(const Affine3d &global)
m_global_transform.translate(m_translation); m_global_transform.translate(m_translation);
// update child transforms // update child transforms
for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
seg->UpdateTransform(m_global_transform); seg->UpdateTransform(m_global_transform);
}
} }
void IK_QSegment::PrependBasis(const Matrix3d &mat) void IK_QSegment::PrependBasis(const Matrix3d &mat)
@ -161,8 +171,9 @@ Vector3d IK_QSphericalSegment::Axis(int dof) const
void IK_QSphericalSegment::SetLimit(int axis, double lmin, double lmax) void IK_QSphericalSegment::SetLimit(int axis, double lmin, double lmax)
{ {
if (lmin > lmax) if (lmin > lmax) {
return; return;
}
if (axis == 1) { if (axis == 1) {
lmin = Clamp(lmin, -M_PI, M_PI); lmin = Clamp(lmin, -M_PI, M_PI);
@ -201,8 +212,9 @@ void IK_QSphericalSegment::SetWeight(int axis, double weight)
bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
{ {
if (m_locked[0] && m_locked[1] && m_locked[2]) if (m_locked[0] && m_locked[1] && m_locked[2]) {
return false; return false;
}
Vector3d dq; Vector3d dq;
dq.x() = jacobian.AngleUpdate(m_DoF_id); dq.x() = jacobian.AngleUpdate(m_DoF_id);
@ -244,20 +256,25 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &d
m_new_basis = m_basis * M; m_new_basis = m_basis * M;
} }
else else {
m_new_basis = m_basis; m_new_basis = m_basis;
}
if (m_limit_y == false && m_limit_x == false && m_limit_z == false) if (m_limit_y == false && m_limit_x == false && m_limit_z == false) {
return false; return false;
}
Vector3d a = SphericalRangeParameters(m_new_basis); Vector3d a = SphericalRangeParameters(m_new_basis);
if (m_locked[0]) if (m_locked[0]) {
a.x() = m_locked_ax; a.x() = m_locked_ax;
if (m_locked[1]) }
if (m_locked[1]) {
a.y() = m_locked_ay; a.y() = m_locked_ay;
if (m_locked[2]) }
if (m_locked[2]) {
a.z() = m_locked_az; a.z() = m_locked_az;
}
double ax = a.x(), ay = a.y(), az = a.z(); double ax = a.x(), ay = a.y(), az = a.z();
@ -275,9 +292,10 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &d
} }
if (m_limit_x && m_limit_z) { if (m_limit_x && m_limit_z) {
if (EllipseClamp(ax, az, m_min, m_max)) if (EllipseClamp(ax, az, m_min, m_max)) {
clamp[0] = clamp[2] = true; clamp[0] = clamp[2] = true;
} }
}
else if (m_limit_x) { else if (m_limit_x) {
if (ax < m_min[0]) { if (ax < m_min[0]) {
ax = m_min[0]; ax = m_min[0];
@ -300,8 +318,9 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &d
} }
if (clamp[0] == false && clamp[1] == false && clamp[2] == false) { if (clamp[0] == false && clamp[1] == false && clamp[2] == false) {
if (m_locked[0] || m_locked[1] || m_locked[2]) if (m_locked[0] || m_locked[1] || m_locked[2]) {
m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay); m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
}
return false; return false;
} }
@ -314,8 +333,9 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &d
m_locked_az = az; m_locked_az = az;
} }
if (!m_locked[1] && clamp[1]) if (!m_locked[1] && clamp[1]) {
m_locked_ay = ay; m_locked_ay = ay;
}
return true; return true;
} }
@ -368,22 +388,27 @@ Vector3d IK_QRevoluteSegment::Axis(int) const
bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
{ {
if (m_locked[0]) if (m_locked[0]) {
return false; return false;
}
m_new_angle = m_angle + jacobian.AngleUpdate(m_DoF_id); m_new_angle = m_angle + jacobian.AngleUpdate(m_DoF_id);
clamp[0] = false; clamp[0] = false;
if (m_limit == false) if (m_limit == false) {
return false; return false;
}
if (m_new_angle > m_max) if (m_new_angle > m_max) {
delta[0] = m_max - m_angle; delta[0] = m_max - m_angle;
else if (m_new_angle < m_min) }
else if (m_new_angle < m_min) {
delta[0] = m_min - m_angle; delta[0] = m_min - m_angle;
else }
else {
return false; return false;
}
clamp[0] = true; clamp[0] = true;
m_new_angle = m_angle + delta[0]; m_new_angle = m_angle + delta[0];
@ -405,8 +430,9 @@ void IK_QRevoluteSegment::UpdateAngleApply()
void IK_QRevoluteSegment::SetLimit(int axis, double lmin, double lmax) void IK_QRevoluteSegment::SetLimit(int axis, double lmin, double lmax)
{ {
if (lmin > lmax || m_axis != axis) if (lmin > lmax || m_axis != axis) {
return; return;
}
// clamp and convert to axis angle parameters // clamp and convert to axis angle parameters
lmin = Clamp(lmin, -M_PI, M_PI); lmin = Clamp(lmin, -M_PI, M_PI);
@ -420,8 +446,9 @@ void IK_QRevoluteSegment::SetLimit(int axis, double lmin, double lmax)
void IK_QRevoluteSegment::SetWeight(int axis, double weight) void IK_QRevoluteSegment::SetWeight(int axis, double weight)
{ {
if (axis == m_axis) if (axis == m_axis) {
m_weight[0] = weight; m_weight[0] = weight;
}
} }
// IK_QSwingSegment // IK_QSwingSegment
@ -441,8 +468,9 @@ Vector3d IK_QSwingSegment::Axis(int dof) const
bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
{ {
if (m_locked[0] && m_locked[1]) if (m_locked[0] && m_locked[1]) {
return false; return false;
}
Vector3d dq; Vector3d dq;
dq.x() = jacobian.AngleUpdate(m_DoF_id); dq.x() = jacobian.AngleUpdate(m_DoF_id);
@ -482,11 +510,13 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta
RemoveTwist(m_new_basis); RemoveTwist(m_new_basis);
} }
else else {
m_new_basis = m_basis; m_new_basis = m_basis;
}
if (m_limit_x == false && m_limit_z == false) if (m_limit_x == false && m_limit_z == false) {
return false; return false;
}
Vector3d a = SphericalRangeParameters(m_new_basis); Vector3d a = SphericalRangeParameters(m_new_basis);
double ax = 0, az = 0; double ax = 0, az = 0;
@ -497,9 +527,10 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta
ax = a.x(); ax = a.x();
az = a.z(); az = a.z();
if (EllipseClamp(ax, az, m_min, m_max)) if (EllipseClamp(ax, az, m_min, m_max)) {
clamp[0] = clamp[1] = true; clamp[0] = clamp[1] = true;
} }
}
else if (m_limit_x) { else if (m_limit_x) {
if (ax < m_min[0]) { if (ax < m_min[0]) {
ax = m_min[0]; ax = m_min[0];
@ -521,8 +552,9 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta
} }
} }
if (clamp[0] == false && clamp[1] == false) if (clamp[0] == false && clamp[1] == false) {
return false; return false;
}
m_new_basis = ComputeSwingMatrix(ax, az); m_new_basis = ComputeSwingMatrix(ax, az);
@ -547,8 +579,9 @@ void IK_QSwingSegment::UpdateAngleApply()
void IK_QSwingSegment::SetLimit(int axis, double lmin, double lmax) void IK_QSwingSegment::SetLimit(int axis, double lmin, double lmax)
{ {
if (lmin > lmax) if (lmin > lmax) {
return; return;
}
// clamp and convert to axis angle parameters // clamp and convert to axis angle parameters
lmin = Clamp(lmin, -M_PI, M_PI); lmin = Clamp(lmin, -M_PI, M_PI);
@ -581,10 +614,12 @@ void IK_QSwingSegment::SetLimit(int axis, double lmin, double lmax)
void IK_QSwingSegment::SetWeight(int axis, double weight) void IK_QSwingSegment::SetWeight(int axis, double weight)
{ {
if (axis == 0) if (axis == 0) {
m_weight[0] = weight; m_weight[0] = weight;
else if (axis == 2) }
else if (axis == 2) {
m_weight[1] = weight; m_weight[1] = weight;
}
} }
// IK_QElbowSegment // IK_QElbowSegment
@ -616,21 +651,25 @@ Vector3d IK_QElbowSegment::Axis(int dof) const
{ {
if (dof == 0) { if (dof == 0) {
Vector3d v; Vector3d v;
if (m_axis == 0) if (m_axis == 0) {
v = Vector3d(m_cos_twist, 0, m_sin_twist); v = Vector3d(m_cos_twist, 0, m_sin_twist);
else }
else {
v = Vector3d(-m_sin_twist, 0, m_cos_twist); v = Vector3d(-m_sin_twist, 0, m_cos_twist);
}
return m_global_transform.linear() * v; return m_global_transform.linear() * v;
} }
else else {
return m_global_transform.linear().col(1); return m_global_transform.linear().col(1);
}
} }
bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
{ {
if (m_locked[0] && m_locked[1]) if (m_locked[0] && m_locked[1]) {
return false; return false;
}
clamp[0] = clamp[1] = false; clamp[0] = clamp[1] = false;
@ -699,8 +738,9 @@ void IK_QElbowSegment::UpdateAngleApply()
void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax) void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax)
{ {
if (lmin > lmax) if (lmin > lmax) {
return; return;
}
// clamp and convert to axis angle parameters // clamp and convert to axis angle parameters
lmin = Clamp(lmin, -M_PI, M_PI); lmin = Clamp(lmin, -M_PI, M_PI);
@ -720,10 +760,12 @@ void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax)
void IK_QElbowSegment::SetWeight(int axis, double weight) void IK_QElbowSegment::SetWeight(int axis, double weight)
{ {
if (axis == m_axis) if (axis == m_axis) {
m_weight[0] = weight; m_weight[0] = weight;
else if (axis == 1) }
else if (axis == 1) {
m_weight[1] = weight; m_weight[1] = weight;
}
} }
// IK_QTranslateSegment // IK_QTranslateSegment
@ -819,15 +861,18 @@ void IK_QTranslateSegment::SetWeight(int axis, double weight)
{ {
int i; int i;
for (i = 0; i < m_num_DoF; i++) for (i = 0; i < m_num_DoF; i++) {
if (m_axis[i] == axis) if (m_axis[i] == axis) {
m_weight[i] = weight; m_weight[i] = weight;
}
}
} }
void IK_QTranslateSegment::SetLimit(int axis, double lmin, double lmax) void IK_QTranslateSegment::SetLimit(int axis, double lmin, double lmax)
{ {
if (lmax < lmin) if (lmax < lmin) {
return; return;
}
m_min[axis] = lmin; m_min[axis] = lmin;
m_max[axis] = lmax; m_max[axis] = lmax;

@ -43,8 +43,9 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian &jacobian)
Vector3d d_pos = m_goal - pos; Vector3d d_pos = m_goal - pos;
double length = d_pos.norm(); double length = d_pos.norm();
if (length > m_clamp_length) if (length > m_clamp_length) {
d_pos = (m_clamp_length / length) * d_pos; d_pos = (m_clamp_length / length) * d_pos;
}
jacobian.SetBetas(m_id, m_size, m_weight * d_pos); jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
@ -58,8 +59,9 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian &jacobian)
for (i = 0; i < seg->NumberOfDoF(); i++) { for (i = 0; i < seg->NumberOfDoF(); i++) {
Vector3d axis = seg->Axis(i) * m_weight; Vector3d axis = seg->Axis(i) * m_weight;
if (seg->Translational()) if (seg->Translational()) {
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2); jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2);
}
else { else {
Vector3d pa = p.cross(axis); Vector3d pa = p.cross(axis);
jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0); jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0);
@ -104,16 +106,18 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian &jacobian)
int i; int i;
const IK_QSegment *seg; const IK_QSegment *seg;
for (seg = m_segment; seg; seg = seg->Parent()) for (seg = m_segment; seg; seg = seg->Parent()) {
for (i = 0; i < seg->NumberOfDoF(); i++) { for (i = 0; i < seg->NumberOfDoF(); i++) {
if (seg->Translational()) if (seg->Translational()) {
jacobian.SetDerivatives(m_id, seg->DoFId() + i, Vector3d(0, 0, 0), 1e2); jacobian.SetDerivatives(m_id, seg->DoFId() + i, Vector3d(0, 0, 0), 1e2);
}
else { else {
Vector3d axis = seg->Axis(i) * m_weight; Vector3d axis = seg->Axis(i) * m_weight;
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0); jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0);
} }
} }
}
} }
// IK_QCenterOfMassTask // IK_QCenterOfMassTask
@ -125,8 +129,9 @@ IK_QCenterOfMassTask::IK_QCenterOfMassTask(bool primary,
: IK_QTask(3, primary, true, segment), m_goal_center(goal_center) : IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
{ {
m_total_mass_inv = ComputeTotalMass(m_segment); m_total_mass_inv = ComputeTotalMass(m_segment);
if (!FuzzyZero(m_total_mass_inv)) if (!FuzzyZero(m_total_mass_inv)) {
m_total_mass_inv = 1.0 / m_total_mass_inv; m_total_mass_inv = 1.0 / m_total_mass_inv;
}
} }
double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment) double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
@ -134,8 +139,9 @@ double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
double mass = /*seg->Mass()*/ 1.0; double mass = /*seg->Mass()*/ 1.0;
const IK_QSegment *seg; const IK_QSegment *seg;
for (seg = segment->Child(); seg; seg = seg->Sibling()) for (seg = segment->Child(); seg; seg = seg->Sibling()) {
mass += ComputeTotalMass(seg); mass += ComputeTotalMass(seg);
}
return mass; return mass;
} }
@ -145,8 +151,9 @@ Vector3d IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
Vector3d center = /*seg->Mass()**/ segment->GlobalStart(); Vector3d center = /*seg->Mass()**/ segment->GlobalStart();
const IK_QSegment *seg; const IK_QSegment *seg;
for (seg = segment->Child(); seg; seg = seg->Sibling()) for (seg = segment->Child(); seg; seg = seg->Sibling()) {
center += ComputeCenter(seg); center += ComputeCenter(seg);
}
return center; return center;
} }
@ -162,8 +169,9 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian &jacobian,
Vector3d axis = segment->Axis(i) * m_weight; Vector3d axis = segment->Axis(i) * m_weight;
axis *= /*segment->Mass()**/ m_total_mass_inv; axis *= /*segment->Mass()**/ m_total_mass_inv;
if (segment->Translational()) if (segment->Translational()) {
jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2); jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2);
}
else { else {
Vector3d pa = axis.cross(p); Vector3d pa = axis.cross(p);
jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0); jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0);
@ -171,8 +179,9 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian &jacobian,
} }
const IK_QSegment *seg; const IK_QSegment *seg;
for (seg = segment->Child(); seg; seg = seg->Sibling()) for (seg = segment->Child(); seg; seg = seg->Sibling()) {
JacobianSegment(jacobian, center, seg); JacobianSegment(jacobian, center, seg);
}
} }
void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian &jacobian) void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian &jacobian)

@ -35,23 +35,29 @@ static IK_QSegment *CreateSegment(int flag, bool translate)
IK_QSegment *seg; IK_QSegment *seg;
if (ndof == 0) if (ndof == 0) {
return NULL; return NULL;
}
else if (ndof == 1) { else if (ndof == 1) {
int axis; int axis;
if (flag & IK_XDOF) if (flag & IK_XDOF) {
axis = 0; axis = 0;
else if (flag & IK_YDOF) }
else if (flag & IK_YDOF) {
axis = 1; axis = 1;
else }
else {
axis = 2; axis = 2;
}
if (translate) if (translate) {
seg = new IK_QTranslateSegment(axis); seg = new IK_QTranslateSegment(axis);
else }
else {
seg = new IK_QRevoluteSegment(axis); seg = new IK_QRevoluteSegment(axis);
} }
}
else if (ndof == 2) { else if (ndof == 2) {
int axis1, axis2; int axis1, axis2;
@ -64,21 +70,26 @@ static IK_QSegment *CreateSegment(int flag, bool translate)
axis2 = 2; axis2 = 2;
} }
if (translate) if (translate) {
seg = new IK_QTranslateSegment(axis1, axis2); seg = new IK_QTranslateSegment(axis1, axis2);
}
else { else {
if (axis1 + axis2 == 2) if (axis1 + axis2 == 2) {
seg = new IK_QSwingSegment(); seg = new IK_QSwingSegment();
else }
else {
seg = new IK_QElbowSegment((axis1 == 0) ? 0 : 2); seg = new IK_QElbowSegment((axis1 == 0) ? 0 : 2);
} }
} }
}
else { else {
if (translate) if (translate) {
seg = new IK_QTranslateSegment(); seg = new IK_QTranslateSegment();
else }
else {
seg = new IK_QSphericalSegment(); seg = new IK_QSphericalSegment();
} }
}
return seg; return seg;
} }
@ -90,10 +101,12 @@ IK_Segment *IK_CreateSegment(int flag)
IK_QSegment *seg; IK_QSegment *seg;
if (rot == NULL && trans == NULL) if (rot == NULL && trans == NULL) {
seg = new IK_QNullSegment(); seg = new IK_QNullSegment();
else if (rot == NULL) }
else if (rot == NULL) {
seg = trans; seg = trans;
}
else { else {
seg = rot; seg = rot;
@ -112,8 +125,9 @@ void IK_FreeSegment(IK_Segment *seg)
{ {
IK_QSegment *qseg = (IK_QSegment *)seg; IK_QSegment *qseg = (IK_QSegment *)seg;
if (qseg->Composite()) if (qseg->Composite()) {
delete qseg->Composite(); delete qseg->Composite();
}
delete qseg; delete qseg;
} }
@ -122,10 +136,12 @@ void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
IK_QSegment *qseg = (IK_QSegment *)seg; IK_QSegment *qseg = (IK_QSegment *)seg;
IK_QSegment *qparent = (IK_QSegment *)parent; IK_QSegment *qparent = (IK_QSegment *)parent;
if (qparent && qparent->Composite()) if (qparent && qparent->Composite()) {
qseg->SetParent(qparent->Composite()); qseg->SetParent(qparent->Composite());
else }
else {
qseg->SetParent(qparent); qseg->SetParent(qparent);
}
} }
void IK_SetTransform( void IK_SetTransform(
@ -163,8 +179,9 @@ void IK_SetTransform(
qseg->SetTransform(mstart, mrest, mbasis, 0.0); qseg->SetTransform(mstart, mrest, mbasis, 0.0);
qseg->Composite()->SetTransform(cstart, cbasis, cbasis, mlength); qseg->Composite()->SetTransform(cstart, cbasis, cbasis, mlength);
} }
else else {
qseg->SetTransform(mstart, mrest, mbasis, mlength); qseg->SetTransform(mstart, mrest, mbasis, mlength);
}
} }
void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax) void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
@ -173,49 +190,61 @@ void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
if (axis >= IK_TRANS_X) { if (axis >= IK_TRANS_X) {
if (!qseg->Translational()) { if (!qseg->Translational()) {
if (qseg->Composite() && qseg->Composite()->Translational()) if (qseg->Composite() && qseg->Composite()->Translational()) {
qseg = qseg->Composite(); qseg = qseg->Composite();
else }
else {
return; return;
} }
}
if (axis == IK_TRANS_X) if (axis == IK_TRANS_X) {
axis = IK_X; axis = IK_X;
else if (axis == IK_TRANS_Y) }
else if (axis == IK_TRANS_Y) {
axis = IK_Y; axis = IK_Y;
else }
else {
axis = IK_Z; axis = IK_Z;
} }
}
qseg->SetLimit(axis, lmin, lmax); qseg->SetLimit(axis, lmin, lmax);
} }
void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
{ {
if (stiffness < 0.0f) if (stiffness < 0.0f) {
return; return;
}
if (stiffness > (1.0 - IK_STRETCH_STIFF_EPS)) if (stiffness > (1.0 - IK_STRETCH_STIFF_EPS)) {
stiffness = (1.0 - IK_STRETCH_STIFF_EPS); stiffness = (1.0 - IK_STRETCH_STIFF_EPS);
}
IK_QSegment *qseg = (IK_QSegment *)seg; IK_QSegment *qseg = (IK_QSegment *)seg;
double weight = 1.0f - stiffness; double weight = 1.0f - stiffness;
if (axis >= IK_TRANS_X) { if (axis >= IK_TRANS_X) {
if (!qseg->Translational()) { if (!qseg->Translational()) {
if (qseg->Composite() && qseg->Composite()->Translational()) if (qseg->Composite() && qseg->Composite()->Translational()) {
qseg = qseg->Composite(); qseg = qseg->Composite();
else }
else {
return; return;
} }
}
if (axis == IK_TRANS_X) if (axis == IK_TRANS_X) {
axis = IK_X; axis = IK_X;
else if (axis == IK_TRANS_Y) }
else if (axis == IK_TRANS_Y) {
axis = IK_Y; axis = IK_Y;
else }
else {
axis = IK_Z; axis = IK_Z;
} }
}
qseg->SetWeight(axis, weight); qseg->SetWeight(axis, weight);
} }
@ -224,8 +253,9 @@ void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
{ {
IK_QSegment *qseg = (IK_QSegment *)seg; IK_QSegment *qseg = (IK_QSegment *)seg;
if (qseg->Translational() && qseg->Composite()) if (qseg->Translational() && qseg->Composite()) {
qseg = qseg->Composite(); qseg = qseg->Composite();
}
const Matrix3d &change = qseg->BasisChange(); const Matrix3d &change = qseg->BasisChange();
@ -245,8 +275,9 @@ void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
{ {
IK_QSegment *qseg = (IK_QSegment *)seg; IK_QSegment *qseg = (IK_QSegment *)seg;
if (!qseg->Translational() && qseg->Composite()) if (!qseg->Translational() && qseg->Composite()) {
qseg = qseg->Composite(); qseg = qseg->Composite();
}
const Vector3d &change = qseg->TranslationChange(); const Vector3d &change = qseg->TranslationChange();
@ -257,8 +288,9 @@ void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
IK_Solver *IK_CreateSolver(IK_Segment *root) IK_Solver *IK_CreateSolver(IK_Segment *root)
{ {
if (root == NULL) if (root == NULL) {
return NULL; return NULL;
}
IK_QSolver *solver = new IK_QSolver(); IK_QSolver *solver = new IK_QSolver();
solver->root = (IK_QSegment *)root; solver->root = (IK_QSegment *)root;
@ -268,30 +300,34 @@ IK_Solver *IK_CreateSolver(IK_Segment *root)
void IK_FreeSolver(IK_Solver *solver) void IK_FreeSolver(IK_Solver *solver)
{ {
if (solver == NULL) if (solver == NULL) {
return; return;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
std::list<IK_QTask *> &tasks = qsolver->tasks; std::list<IK_QTask *> &tasks = qsolver->tasks;
std::list<IK_QTask *>::iterator task; std::list<IK_QTask *>::iterator task;
for (task = tasks.begin(); task != tasks.end(); task++) for (task = tasks.begin(); task != tasks.end(); task++) {
delete (*task); delete (*task);
}
delete qsolver; delete qsolver;
} }
void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight)
{ {
if (solver == NULL || tip == NULL) if (solver == NULL || tip == NULL) {
return; return;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip; IK_QSegment *qtip = (IK_QSegment *)tip;
// in case of composite segment the second segment is the tip // in case of composite segment the second segment is the tip
if (qtip->Composite()) if (qtip->Composite()) {
qtip = qtip->Composite(); qtip = qtip->Composite();
}
Vector3d pos(goal[0], goal[1], goal[2]); Vector3d pos(goal[0], goal[1], goal[2]);
@ -302,15 +338,17 @@ void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float w
void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight)
{ {
if (solver == NULL || tip == NULL) if (solver == NULL || tip == NULL) {
return; return;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip; IK_QSegment *qtip = (IK_QSegment *)tip;
// in case of composite segment the second segment is the tip // in case of composite segment the second segment is the tip
if (qtip->Composite()) if (qtip->Composite()) {
qtip = qtip->Composite(); qtip = qtip->Composite();
}
// convert from blender column major // convert from blender column major
Matrix3d rot = CreateMatrix(goal[0][0], Matrix3d rot = CreateMatrix(goal[0][0],
@ -335,15 +373,17 @@ void IK_SolverSetPoleVectorConstraint(IK_Solver *solver,
float poleangle, float poleangle,
int getangle) int getangle)
{ {
if (solver == NULL || tip == NULL) if (solver == NULL || tip == NULL) {
return; return;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip; IK_QSegment *qtip = (IK_QSegment *)tip;
// in case of composite segment the second segment is the tip // in case of composite segment the second segment is the tip
if (qtip->Composite()) if (qtip->Composite()) {
qtip = qtip->Composite(); qtip = qtip->Composite();
}
Vector3d qgoal(goal[0], goal[1], goal[2]); Vector3d qgoal(goal[0], goal[1], goal[2]);
Vector3d qpolegoal(polegoal[0], polegoal[1], polegoal[2]); Vector3d qpolegoal(polegoal[0], polegoal[1], polegoal[2]);
@ -353,8 +393,9 @@ void IK_SolverSetPoleVectorConstraint(IK_Solver *solver,
float IK_SolverGetPoleAngle(IK_Solver *solver) float IK_SolverGetPoleAngle(IK_Solver *solver)
{ {
if (solver == NULL) if (solver == NULL) {
return 0.0f; return 0.0f;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
@ -384,8 +425,9 @@ static void IK_SolverAddCenterOfMass(IK_Solver *solver,
int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
{ {
if (solver == NULL) if (solver == NULL) {
return 0; return 0;
}
IK_QSolver *qsolver = (IK_QSolver *)solver; IK_QSolver *qsolver = (IK_QSolver *)solver;
@ -394,8 +436,9 @@ int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
std::list<IK_QTask *> &tasks = qsolver->tasks; std::list<IK_QTask *> &tasks = qsolver->tasks;
double tol = tolerance; double tol = tolerance;
if (!jacobian.Setup(root, tasks)) if (!jacobian.Setup(root, tasks)) {
return 0; return 0;
}
bool result = jacobian.Solve(root, tasks, tol, max_iterations); bool result = jacobian.Solve(root, tasks, tol, max_iterations);

@ -307,10 +307,10 @@ TEST(ArrayND, MultiplyElementsGeneric) {
MultiplyElements(A, B, &C); MultiplyElements(A, B, &C);
ArrayND<double, 5>::Index cIndex; ArrayND<double, 5>::Index cIndex;
for (int d0 = 0; d0 < shape[0]; ++d0) for (int d0 = 0; d0 < shape[0]; ++d0) {
for (int d1 = 0; d1 < shape[1]; ++d1) for (int d1 = 0; d1 < shape[1]; ++d1) {
for (int d2 = 0; d2 < shape[2]; ++d2) for (int d2 = 0; d2 < shape[2]; ++d2) {
for (int d3 = 0; d3 < shape[3]; ++d3) for (int d3 = 0; d3 < shape[3]; ++d3) {
for (int d4 = 0; d4 < shape[4]; ++d4) { for (int d4 = 0; d4 < shape[4]; ++d4) {
cIndex(0) = d0; cIndex(0) = d0;
cIndex(1) = d1; cIndex(1) = d1;
@ -319,6 +319,10 @@ TEST(ArrayND, MultiplyElementsGeneric) {
cIndex(4) = d4; cIndex(4) = d4;
EXPECT_EQ(2.2, C(cIndex)); EXPECT_EQ(2.2, C(cIndex));
} }
}
}
}
}
} }
} // namespace } // namespace

@ -331,18 +331,21 @@ void LaplaceFilter(unsigned char* src,
int width, int width,
int height, int height,
int strength) { int strength) {
for (int y = 1; y < height - 1; y++) for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) { for (int x = 1; x < width - 1; x++) {
const unsigned char* s = &src[y * width + x]; const unsigned char* s = &src[y * width + x];
int l = 128 + s[-width - 1] + s[-width] + s[-width + 1] + s[1] - int l = 128 + s[-width - 1] + s[-width] + s[-width + 1] + s[1] -
8 * s[0] + s[1] + s[width - 1] + s[width] + s[width + 1]; 8 * s[0] + s[1] + s[width - 1] + s[width] + s[width + 1];
int d = ((256 - strength) * s[0] + strength * l) / 256; int d = ((256 - strength) * s[0] + strength * l) / 256;
if (d < 0) if (d < 0) {
d = 0; d = 0;
if (d > 255) }
if (d > 255) {
d = 255; d = 255;
}
dst[y * width + x] = d; dst[y * width + x] = d;
} }
}
} }
} // namespace libmv } // namespace libmv

@ -38,8 +38,9 @@ TEST(Tuple, InitFromPointer) {
float vals[3] = {1.0f, 2.0f, 3.0f}; float vals[3] = {1.0f, 2.0f, 3.0f};
Tuple<float, 3> t(vals); Tuple<float, 3> t(vals);
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) {
EXPECT_EQ(t(i), vals[i]); EXPECT_EQ(t(i), vals[i]);
}
Tuple<int, 3> b(t); Tuple<int, 3> b(t);
EXPECT_EQ(b(0), int(vals[0])); EXPECT_EQ(b(0), int(vals[0]));

@ -33,10 +33,12 @@ void PreconditionerFromPoints(const Mat& points, Mat3* T) {
// If variance is equal to 0.0 set scaling factor to identity. // If variance is equal to 0.0 set scaling factor to identity.
// -> Else it will provide nan value (because division by 0). // -> Else it will provide nan value (because division by 0).
if (variance(0) < 1e-8) if (variance(0) < 1e-8) {
xfactor = mean(0) = 1.0; xfactor = mean(0) = 1.0;
if (variance(1) < 1e-8) }
if (variance(1) < 1e-8) {
yfactor = mean(1) = 1.0; yfactor = mean(1) = 1.0;
}
// clang-format off // clang-format off
*T << xfactor, 0, -xfactor * mean(0), *T << xfactor, 0, -xfactor * mean(0),

@ -63,8 +63,9 @@ TEST(Homography2DTest, Rotation45AndTranslationXY) {
Mat x2 = x1; Mat x2 = x1;
// Transform point from ground truth matrix // Transform point from ground truth matrix
for (int i = 0; i < x2.cols(); ++i) for (int i = 0; i < x2.cols(); ++i) {
x2.col(i) = m * x1.col(i); x2.col(i) = m * x1.col(i);
}
Mat3 homography_mat; Mat3 homography_mat;
EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat)); EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
@ -128,8 +129,9 @@ TEST(Homography2DTest, AffineGeneral5) {
// clang-format on // clang-format on
Mat x2 = x1; Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) for (int i = 0; i < x2.cols(); ++i) {
x2.col(i) = m * x1.col(i); x2.col(i) = m * x1.col(i);
}
Mat3 homography_mat; Mat3 homography_mat;
EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat)); EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
@ -165,8 +167,9 @@ TEST(Homography2DTest, HomographyGeneral) {
// clang-format on // clang-format on
Mat x2 = x1; Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) for (int i = 0; i < x2.cols(); ++i) {
x2.col(i) = m * x1.col(i); x2.col(i) = m * x1.col(i);
}
Mat3 homography_mat; Mat3 homography_mat;
EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat)); EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));

@ -90,8 +90,9 @@ NViewDataSet NRealisticCamerasFull(int nviews,
d.X *= 0.6; d.X *= 0.6;
Vecu all_point_ids(npoints); Vecu all_point_ids(npoints);
for (size_t j = 0; j < npoints; ++j) for (size_t j = 0; j < npoints; ++j) {
all_point_ids[j] = j; all_point_ids[j] = j;
}
for (size_t i = 0; i < nviews; ++i) { for (size_t i = 0; i < nviews; ++i) {
Vec3 camera_center, t, jitter, lookdir; Vec3 camera_center, t, jitter, lookdir;

@ -221,31 +221,38 @@ void DetectMORAVEC(const FloatImage& grayscale_image,
// clang-format on // clang-format on
score /= 256; // normalize score /= 256; // normalize
if (pattern) // find only features similar to pattern if (pattern) { // find only features similar to pattern
score -= SAD(s, pattern, stride, 16); score -= SAD(s, pattern, stride, 16);
if (score <= 16) }
if (score <= 16) {
continue; // filter very self-similar features continue; // filter very self-similar features
}
score -= 16; // translate to score/histogram values score -= 16; // translate to score/histogram values
if (score > 255) if (score > 255) {
score = 255; // clip score = 255; // clip
}
ubyte* c = &scores[y * width + x]; ubyte* c = &scores[y * width + x];
for (int i = -distance; i < 0; i++) { for (int i = -distance; i < 0; i++) {
for (int j = -distance; j < distance; j++) { for (int j = -distance; j < distance; j++) {
int s = c[i * width + j]; int s = c[i * width + j];
if (s == 0) if (s == 0) {
continue; continue;
if (s >= score) }
if (s >= score) {
goto nonmax; goto nonmax;
}
c[i * width + j] = 0; c[i * width + j] = 0;
histogram[s]--; histogram[s]--;
} }
} }
for (int i = 0, j = -distance; j < 0; j++) { for (int i = 0, j = -distance; j < 0; j++) {
int s = c[i * width + j]; int s = c[i * width + j];
if (s == 0) if (s == 0) {
continue; continue;
if (s >= score) }
if (s >= score) {
goto nonmax; goto nonmax;
}
c[i * width + j] = 0; c[i * width + j] = 0;
histogram[s]--; histogram[s]--;
} }

@ -184,8 +184,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
<< current_keyframe << " and " << candidate_image; << current_keyframe << " and " << candidate_image;
// Not enough points to construct fundamental matrix // Not enough points to construct fundamental matrix
if (x1.cols() < 8 || x2.cols() < 8) if (x1.cols() < 8 || x2.cols() < 8) {
continue; continue;
}
// STEP 1: Correspondence ratio constraint // STEP 1: Correspondence ratio constraint
int Tc = tracked_markers.size(); int Tc = tracked_markers.size();
@ -195,8 +196,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
LG << "Correspondence between " << current_keyframe << " and " LG << "Correspondence between " << current_keyframe << " and "
<< candidate_image << ": " << Rc; << candidate_image << ": " << Rc;
if (Rc < Tmin || Rc > Tmax) if (Rc < Tmin || Rc > Tmax) {
continue; continue;
}
Mat3 H, F; Mat3 H, F;
@ -246,8 +248,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
LG << "GRIC values for frames " << current_keyframe << " and " LG << "GRIC values for frames " << current_keyframe << " and "
<< candidate_image << ", H-GRIC: " << GRIC_H << ", F-GRIC: " << GRIC_F; << candidate_image << ", H-GRIC: " << GRIC_H << ", F-GRIC: " << GRIC_F;
if (GRIC_H <= GRIC_F) if (GRIC_H <= GRIC_F) {
continue; continue;
}
// TODO(sergey): STEP 4: PELC criterion // TODO(sergey): STEP 4: PELC criterion
@ -386,8 +389,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
<< candidate_image << ": " << Sc; << candidate_image << ": " << Sc;
// Pairing with a lower Sc indicates a better choice // Pairing with a lower Sc indicates a better choice
if (Sc > Sc_best_candidate) if (Sc > Sc_best_candidate) {
continue; continue;
}
Sc_best_candidate = Sc; Sc_best_candidate = Sc;
@ -405,8 +409,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
if (next_keyframe == -1) { if (next_keyframe == -1) {
next_keyframe = current_keyframe + 10; next_keyframe = current_keyframe + 10;
if (next_keyframe >= max_image) if (next_keyframe >= max_image) {
break; break;
}
LG << "Starting searching for keyframes starting from " << next_keyframe; LG << "Starting searching for keyframes starting from " << next_keyframe;
} else { } else {

@ -130,17 +130,18 @@ static void CompleteReconstructionLogProgress(
if (update_callback) { if (update_callback) {
char message[256]; char message[256];
if (step) if (step) {
snprintf(message, snprintf(message,
sizeof(message), sizeof(message),
"Completing solution %d%% | %s", "Completing solution %d%% | %s",
(int)(progress * 100), (int)(progress * 100),
step); step);
else } else {
snprintf(message, snprintf(message,
sizeof(message), sizeof(message),
"Completing solution %d%%", "Completing solution %d%%",
(int)(progress * 100)); (int)(progress * 100));
}
update_callback->invoke(progress, message); update_callback->invoke(progress, message);
} }

@ -117,8 +117,9 @@ bool EuclideanResect(const vector<Marker>& markers,
LG << "No fallback; failing resection for " << markers[0].image; LG << "No fallback; failing resection for " << markers[0].image;
return false; return false;
if (!final_pass) if (!final_pass) {
return false; return false;
}
// Euclidean resection failed. Fall back to projective resection, which is // Euclidean resection failed. Fall back to projective resection, which is
// less reliable but better conditioned when there are many points. // less reliable but better conditioned when there are many points.
Mat34 P; Mat34 P;

@ -77,9 +77,10 @@ vector<Marker> Tracks::MarkersInBothImages(int image1, int image2) const {
vector<Marker> markers; vector<Marker> markers;
for (int i = 0; i < markers_.size(); ++i) { for (int i = 0; i < markers_.size(); ++i) {
int image = markers_[i].image; int image = markers_[i].image;
if (image == image1 || image == image2) if (image == image1 || image == image2) {
markers.push_back(markers_[i]); markers.push_back(markers_[i]);
} }
}
return markers; return markers;
} }

@ -1595,11 +1595,12 @@ bool SamplePlanarPatch(const FloatImage& image,
float mask_value = float mask_value =
SampleLinear(*mask, image_position(1), image_position(0), 0); SampleLinear(*mask, image_position(1), image_position(0), 0);
for (int d = 0; d < image.Depth(); d++) for (int d = 0; d < image.Depth(); d++) {
(*patch)(r, c, d) *= mask_value; (*patch)(r, c, d) *= mask_value;
} }
} }
} }
}
Vec3 warped_position = canonical_homography.inverse() * Vec3(xs[4], ys[4], 1); Vec3 warped_position = canonical_homography.inverse() * Vec3(xs[4], ys[4], 1);
warped_position /= warped_position(2); warped_position /= warped_position(2);

@ -44,9 +44,10 @@ int MANTA::with_debug(0);
MANTA::MANTA(int *res, FluidModifierData *fmd) MANTA::MANTA(int *res, FluidModifierData *fmd)
: mCurrentID(++solverID), mMaxRes(fmd->domain->maxres) : mCurrentID(++solverID), mMaxRes(fmd->domain->maxres)
{ {
if (with_debug) if (with_debug) {
cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2] cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2]
<< ")" << endl; << ")" << endl;
}
FluidDomainSettings *fds = fmd->domain; FluidDomainSettings *fds = fmd->domain;
fds->fluid = this; fds->fluid = this;
@ -177,12 +178,15 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
if (mUsingLiquid) { if (mUsingLiquid) {
initSuccess &= initDomain(); initSuccess &= initDomain();
initSuccess &= initLiquid(); initSuccess &= initLiquid();
if (mUsingObstacle) if (mUsingObstacle) {
initSuccess &= initObstacle(); initSuccess &= initObstacle();
if (mUsingInvel) }
if (mUsingInvel) {
initSuccess &= initInVelocity(); initSuccess &= initInVelocity();
if (mUsingOutflow) }
if (mUsingOutflow) {
initSuccess &= initOutflow(); initSuccess &= initOutflow();
}
if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) { if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
mUpresParticle = fds->particle_scale; mUpresParticle = fds->particle_scale;
@ -228,18 +232,24 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
if (mUsingSmoke) { if (mUsingSmoke) {
initSuccess &= initDomain(); initSuccess &= initDomain();
initSuccess &= initSmoke(); initSuccess &= initSmoke();
if (mUsingHeat) if (mUsingHeat) {
initSuccess &= initHeat(); initSuccess &= initHeat();
if (mUsingFire) }
if (mUsingFire) {
initSuccess &= initFire(); initSuccess &= initFire();
if (mUsingColors) }
if (mUsingColors) {
initSuccess &= initColors(); initSuccess &= initColors();
if (mUsingObstacle) }
if (mUsingObstacle) {
initSuccess &= initObstacle(); initSuccess &= initObstacle();
if (mUsingInvel) }
if (mUsingInvel) {
initSuccess &= initInVelocity(); initSuccess &= initInVelocity();
if (mUsingOutflow) }
if (mUsingOutflow) {
initSuccess &= initOutflow(); initSuccess &= initOutflow();
}
if (mUsingGuiding) { if (mUsingGuiding) {
mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res; mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res;
@ -256,12 +266,14 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
/* Initialize Mantaflow variables in Python. */ /* Initialize Mantaflow variables in Python. */
initSuccess &= initNoise(); initSuccess &= initNoise();
initSuccess &= initSmokeNoise(); initSuccess &= initSmokeNoise();
if (mUsingFire) if (mUsingFire) {
initSuccess &= initFireHigh(); initSuccess &= initFireHigh();
if (mUsingColors) }
if (mUsingColors) {
initSuccess &= initColorsHigh(); initSuccess &= initColorsHigh();
} }
} }
}
/* All requested initializations must not fail in constructor. */ /* All requested initializations must not fail in constructor. */
BLI_assert(initSuccess); BLI_assert(initSuccess);
(void)initSuccess; /* Ignored in release. */ (void)initSuccess; /* Ignored in release. */
@ -543,9 +555,10 @@ bool MANTA::initLiquidSndParts(FluidModifierData *fmd)
MANTA::~MANTA() MANTA::~MANTA()
{ {
if (with_debug) if (with_debug) {
cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ
<< ")" << endl; << ")" << endl;
}
/* Destruction string for Python. */ /* Destruction string for Python. */
string tmpString = ""; string tmpString = "";
@ -689,8 +702,9 @@ bool MANTA::runPythonString(vector<string> commands)
void MANTA::initializeMantaflow() void MANTA::initializeMantaflow()
{ {
if (with_debug) if (with_debug) {
cout << "Fluid: Initializing Mantaflow framework" << endl; cout << "Fluid: Initializing Mantaflow framework" << endl;
}
string filename = "manta_scene_" + to_string(mCurrentID) + ".py"; string filename = "manta_scene_" + to_string(mCurrentID) + ".py";
vector<string> fill = vector<string>(); vector<string> fill = vector<string>();
@ -707,8 +721,9 @@ void MANTA::initializeMantaflow()
void MANTA::terminateMantaflow() void MANTA::terminateMantaflow()
{ {
if (with_debug) if (with_debug) {
cout << "Fluid: Releasing Mantaflow framework" << endl; cout << "Fluid: Releasing Mantaflow framework" << endl;
}
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
Pb::finalize(false); /* Namespace from Mantaflow (registry). */ Pb::finalize(false); /* Namespace from Mantaflow (registry). */
@ -718,8 +733,9 @@ void MANTA::terminateMantaflow()
static string getCacheFileEnding(char cache_format) static string getCacheFileEnding(char cache_format)
{ {
if (MANTA::with_debug) if (MANTA::with_debug) {
cout << "MANTA::getCacheFileEnding()" << endl; cout << "MANTA::getCacheFileEnding()" << endl;
}
switch (cache_format) { switch (cache_format) {
case FLUID_DOMAIN_FILE_UNI: case FLUID_DOMAIN_FILE_UNI:
@ -746,14 +762,16 @@ static string getBooleanString(int value)
void MANTA::initializeRNAMap(FluidModifierData *fmd) void MANTA::initializeRNAMap(FluidModifierData *fmd)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::initializeRNAMap()" << endl; cout << "MANTA::initializeRNAMap()" << endl;
}
mRNAMap["ID"] = to_string(mCurrentID); mRNAMap["ID"] = to_string(mCurrentID);
if (!fmd) { if (!fmd) {
if (with_debug) if (with_debug) {
cout << "Fluid: No modifier data given in RNA map setup - returning early" << endl; cout << "Fluid: No modifier data given in RNA map setup - returning early" << endl;
}
return; return;
} }
@ -761,39 +779,50 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
bool is2D = (fds->solver_res == 2); bool is2D = (fds->solver_res == 2);
string borderCollisions = ""; string borderCollisions = "";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) if ((fds->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) {
borderCollisions += "x"; borderCollisions += "x";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) }
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) {
borderCollisions += "X"; borderCollisions += "X";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) }
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) {
borderCollisions += "y"; borderCollisions += "y";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) }
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) {
borderCollisions += "Y"; borderCollisions += "Y";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) }
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) {
borderCollisions += "z"; borderCollisions += "z";
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) }
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) {
borderCollisions += "Z"; borderCollisions += "Z";
}
string particleTypesStr = ""; string particleTypesStr = "";
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) if (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) {
particleTypesStr += "PtypeSpray"; particleTypesStr += "PtypeSpray";
}
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) { if (fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) {
if (!particleTypesStr.empty()) if (!particleTypesStr.empty()) {
particleTypesStr += "|"; particleTypesStr += "|";
}
particleTypesStr += "PtypeBubble"; particleTypesStr += "PtypeBubble";
} }
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) { if (fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) {
if (!particleTypesStr.empty()) if (!particleTypesStr.empty()) {
particleTypesStr += "|"; particleTypesStr += "|";
}
particleTypesStr += "PtypeFoam"; particleTypesStr += "PtypeFoam";
} }
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) { if (fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) {
if (!particleTypesStr.empty()) if (!particleTypesStr.empty()) {
particleTypesStr += "|"; particleTypesStr += "|";
}
particleTypesStr += "PtypeTracer"; particleTypesStr += "PtypeTracer";
} }
if (particleTypesStr.empty()) if (particleTypesStr.empty()) {
particleTypesStr = "0"; particleTypesStr = "0";
}
int particleTypes = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE | int particleTypes = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE |
FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER); FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER);
@ -804,20 +833,26 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
float domainSize = MAX3(fds->global_size[0], fds->global_size[1], fds->global_size[2]); float domainSize = MAX3(fds->global_size[0], fds->global_size[1], fds->global_size[2]);
string vdbCompressionMethod = "Compression_None"; string vdbCompressionMethod = "Compression_None";
if (fds->openvdb_compression == VDB_COMPRESSION_NONE) if (fds->openvdb_compression == VDB_COMPRESSION_NONE) {
vdbCompressionMethod = "Compression_None"; vdbCompressionMethod = "Compression_None";
else if (fds->openvdb_compression == VDB_COMPRESSION_ZIP) }
else if (fds->openvdb_compression == VDB_COMPRESSION_ZIP) {
vdbCompressionMethod = "Compression_Zip"; vdbCompressionMethod = "Compression_Zip";
else if (fds->openvdb_compression == VDB_COMPRESSION_BLOSC) }
else if (fds->openvdb_compression == VDB_COMPRESSION_BLOSC) {
vdbCompressionMethod = "Compression_Blosc"; vdbCompressionMethod = "Compression_Blosc";
}
string vdbPrecisionHalf = "Precision_Half"; string vdbPrecisionHalf = "Precision_Half";
if (fds->openvdb_data_depth == VDB_PRECISION_FULL_FLOAT) if (fds->openvdb_data_depth == VDB_PRECISION_FULL_FLOAT) {
vdbPrecisionHalf = "Precision_Full"; vdbPrecisionHalf = "Precision_Full";
else if (fds->openvdb_data_depth == VDB_PRECISION_HALF_FLOAT) }
else if (fds->openvdb_data_depth == VDB_PRECISION_HALF_FLOAT) {
vdbPrecisionHalf = "Precision_Half"; vdbPrecisionHalf = "Precision_Half";
else if (fds->openvdb_data_depth == VDB_PRECISION_MINI_FLOAT) }
else if (fds->openvdb_data_depth == VDB_PRECISION_MINI_FLOAT) {
vdbPrecisionHalf = "Precision_Mini"; vdbPrecisionHalf = "Precision_Mini";
}
mRNAMap["USING_SMOKE"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_GAS); mRNAMap["USING_SMOKE"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_GAS);
mRNAMap["USING_LIQUID"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_LIQUID); mRNAMap["USING_LIQUID"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_LIQUID);
@ -1120,8 +1155,9 @@ string MANTA::getRealValue(const string &varName)
string MANTA::parseLine(const string &line) string MANTA::parseLine(const string &line)
{ {
if (line.size() == 0) if (line.size() == 0) {
return ""; return "";
}
string res = ""; string res = "";
int currPos = 0, start_del = 0, end_del = -1; int currPos = 0, start_del = 0, end_del = -1;
bool readingVar = false; bool readingVar = false;
@ -1145,8 +1181,9 @@ string MANTA::parseLine(const string &line)
string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd) string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd)
{ {
if (MANTA::with_debug) if (MANTA::with_debug) {
cout << "MANTA::parseScript()" << endl; cout << "MANTA::parseScript()" << endl;
}
istringstream f(setup_string); istringstream f(setup_string);
ostringstream res; ostringstream res;
@ -1182,8 +1219,9 @@ static string escapePath(string const &s)
bool MANTA::writeConfiguration(FluidModifierData *fmd, int framenr) bool MANTA::writeConfiguration(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::writeConfiguration()" << endl; cout << "MANTA::writeConfiguration()" << endl;
}
FluidDomainSettings *fds = fmd->domain; FluidDomainSettings *fds = fmd->domain;
@ -1223,8 +1261,9 @@ bool MANTA::writeConfiguration(FluidModifierData *fmd, int framenr)
bool MANTA::writeData(FluidModifierData *fmd, int framenr) bool MANTA::writeData(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::writeData()" << endl; cout << "MANTA::writeData()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1251,8 +1290,9 @@ bool MANTA::writeData(FluidModifierData *fmd, int framenr)
bool MANTA::writeNoise(FluidModifierData *fmd, int framenr) bool MANTA::writeNoise(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::writeNoise()" << endl; cout << "MANTA::writeNoise()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1273,8 +1313,9 @@ bool MANTA::writeNoise(FluidModifierData *fmd, int framenr)
bool MANTA::readConfiguration(FluidModifierData *fmd, int framenr) bool MANTA::readConfiguration(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readConfiguration()" << endl; cout << "MANTA::readConfiguration()" << endl;
}
FluidDomainSettings *fds = fmd->domain; FluidDomainSettings *fds = fmd->domain;
float dummy; float dummy;
@ -1283,8 +1324,9 @@ bool MANTA::readConfiguration(FluidModifierData *fmd, int framenr)
string format = FLUID_DOMAIN_EXTENSION_UNI; string format = FLUID_DOMAIN_EXTENSION_UNI;
string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr); string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr);
if (!hasConfig(fmd, framenr)) if (!hasConfig(fmd, framenr)) {
return false; return false;
}
gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); /* Do some compression. */ gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); /* Do some compression. */
if (!gzf) { if (!gzf) {
@ -1316,11 +1358,13 @@ bool MANTA::readConfiguration(FluidModifierData *fmd, int framenr)
bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable) bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readData()" << endl; cout << "MANTA::readData()" << endl;
}
if (!mUsingSmoke && !mUsingLiquid) if (!mUsingSmoke && !mUsingLiquid) {
return false; return false;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1332,8 +1376,9 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
string resumable_cache = (!resumable) ? "False" : "True"; string resumable_cache = (!resumable) ? "False" : "True";
/* Sanity check: Are cache files present? */ /* Sanity check: Are cache files present? */
if (!hasData(fmd, framenr)) if (!hasData(fmd, framenr)) {
return false; return false;
}
if (mUsingSmoke) { if (mUsingSmoke) {
ss.str(""); ss.str("");
@ -1356,11 +1401,13 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable) bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readNoise()" << endl; cout << "MANTA::readNoise()" << endl;
}
if (!mUsingSmoke || !mUsingNoise) if (!mUsingSmoke || !mUsingNoise) {
return false; return false;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1375,8 +1422,9 @@ bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
string volume_format = getCacheFileEnding(format); string volume_format = getCacheFileEnding(format);
/* Sanity check: Are cache files present? */ /* Sanity check: Are cache files present? */
if (!hasNoise(fmd, framenr)) if (!hasNoise(fmd, framenr)) {
return false; return false;
}
ss.str(""); ss.str("");
ss << "smoke_load_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr ss << "smoke_load_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
@ -1388,11 +1436,13 @@ bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
bool MANTA::readMesh(FluidModifierData *fmd, int framenr) bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readMesh()" << endl; cout << "MANTA::readMesh()" << endl;
}
if (!mUsingLiquid || !mUsingMesh) if (!mUsingLiquid || !mUsingMesh) {
return false; return false;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1403,8 +1453,9 @@ bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
string volume_format = getCacheFileEnding(fds->cache_data_format); string volume_format = getCacheFileEnding(fds->cache_data_format);
/* Sanity check: Are cache files present? */ /* Sanity check: Are cache files present? */
if (!hasMesh(fmd, framenr)) if (!hasMesh(fmd, framenr)) {
return false; return false;
}
ss.str(""); ss.str("");
ss << "liquid_load_mesh_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr ss << "liquid_load_mesh_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
@ -1423,13 +1474,16 @@ bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable) bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readParticles()" << endl; cout << "MANTA::readParticles()" << endl;
}
if (!mUsingLiquid) if (!mUsingLiquid) {
return false; return false;
if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) }
if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) {
return false; return false;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1444,8 +1498,9 @@ bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
string volume_format = getCacheFileEnding(format); string volume_format = getCacheFileEnding(format);
/* Sanity check: Are cache files present? */ /* Sanity check: Are cache files present? */
if (!hasParticles(fmd, framenr)) if (!hasParticles(fmd, framenr)) {
return false; return false;
}
ss.str(""); ss.str("");
ss << "liquid_load_particles_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr ss << "liquid_load_particles_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
@ -1457,13 +1512,16 @@ bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain) bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::readGuiding()" << endl; cout << "MANTA::readGuiding()" << endl;
}
if (!mUsingGuiding) if (!mUsingGuiding) {
return false; return false;
if (!fmd) }
if (!fmd) {
return false; return false;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1474,8 +1532,9 @@ bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
string volume_format = getCacheFileEnding(fds->cache_data_format); string volume_format = getCacheFileEnding(fds->cache_data_format);
/* Sanity check: Are cache files present? */ /* Sanity check: Are cache files present? */
if (!hasGuiding(fmd, framenr, sourceDomain)) if (!hasGuiding(fmd, framenr, sourceDomain)) {
return false; return false;
}
if (sourceDomain) { if (sourceDomain) {
ss.str(""); ss.str("");
@ -1494,8 +1553,9 @@ bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
bool MANTA::bakeData(FluidModifierData *fmd, int framenr) bool MANTA::bakeData(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::bakeData()" << endl; cout << "MANTA::bakeData()" << endl;
}
string tmpString, finalString; string tmpString, finalString;
ostringstream ss; ostringstream ss;
@ -1524,8 +1584,9 @@ bool MANTA::bakeData(FluidModifierData *fmd, int framenr)
bool MANTA::bakeNoise(FluidModifierData *fmd, int framenr) bool MANTA::bakeNoise(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::bakeNoise()" << endl; cout << "MANTA::bakeNoise()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1550,8 +1611,9 @@ bool MANTA::bakeNoise(FluidModifierData *fmd, int framenr)
bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr) bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::bakeMesh()" << endl; cout << "MANTA::bakeMesh()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1576,8 +1638,9 @@ bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr)
bool MANTA::bakeParticles(FluidModifierData *fmd, int framenr) bool MANTA::bakeParticles(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::bakeParticles()" << endl; cout << "MANTA::bakeParticles()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1605,8 +1668,9 @@ bool MANTA::bakeParticles(FluidModifierData *fmd, int framenr)
bool MANTA::bakeGuiding(FluidModifierData *fmd, int framenr) bool MANTA::bakeGuiding(FluidModifierData *fmd, int framenr)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::bakeGuiding()" << endl; cout << "MANTA::bakeGuiding()" << endl;
}
ostringstream ss; ostringstream ss;
vector<string> pythonCommands; vector<string> pythonCommands;
@ -1636,12 +1700,15 @@ bool MANTA::updateVariables(FluidModifierData *fmd)
vector<string> pythonCommands; vector<string> pythonCommands;
tmpString += fluid_variables; tmpString += fluid_variables;
if (mUsingSmoke) if (mUsingSmoke) {
tmpString += smoke_variables; tmpString += smoke_variables;
if (mUsingLiquid) }
if (mUsingLiquid) {
tmpString += liquid_variables; tmpString += liquid_variables;
if (mUsingGuiding) }
if (mUsingGuiding) {
tmpString += fluid_variables_guiding; tmpString += fluid_variables_guiding;
}
if (mUsingNoise) { if (mUsingNoise) {
tmpString += fluid_variables_noise; tmpString += fluid_variables_noise;
tmpString += smoke_variables_noise; tmpString += smoke_variables_noise;
@ -1651,8 +1718,9 @@ bool MANTA::updateVariables(FluidModifierData *fmd)
tmpString += fluid_variables_particles; tmpString += fluid_variables_particles;
tmpString += liquid_variables_particles; tmpString += liquid_variables_particles;
} }
if (mUsingMesh) if (mUsingMesh) {
tmpString += fluid_variables_mesh; tmpString += fluid_variables_mesh;
}
finalString = parseScript(tmpString, fmd); finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString); pythonCommands.push_back(finalString);
@ -1662,8 +1730,9 @@ bool MANTA::updateVariables(FluidModifierData *fmd)
bool MANTA::exportSmokeScript(FluidModifierData *fmd) bool MANTA::exportSmokeScript(FluidModifierData *fmd)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::exportSmokeScript()" << endl; cout << "MANTA::exportSmokeScript()" << endl;
}
char cacheDir[FILE_MAX] = "\0"; char cacheDir[FILE_MAX] = "\0";
char cacheDirScript[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0";
@ -1696,53 +1765,68 @@ bool MANTA::exportSmokeScript(FluidModifierData *fmd)
if (noise) { if (noise) {
manta_script += fluid_variables_noise + smoke_variables_noise; manta_script += fluid_variables_noise + smoke_variables_noise;
} }
if (guiding) if (guiding) {
manta_script += fluid_variables_guiding; manta_script += fluid_variables_guiding;
}
/* Solvers. */ /* Solvers. */
manta_script += header_solvers + fluid_solver; manta_script += header_solvers + fluid_solver;
if (noise) if (noise) {
manta_script += fluid_solver_noise; manta_script += fluid_solver_noise;
if (guiding) }
if (guiding) {
manta_script += fluid_solver_guiding; manta_script += fluid_solver_guiding;
}
/* Grids. */ /* Grids. */
manta_script += header_grids + fluid_alloc + smoke_alloc; manta_script += header_grids + fluid_alloc + smoke_alloc;
if (noise) { if (noise) {
manta_script += smoke_alloc_noise; manta_script += smoke_alloc_noise;
if (colors) if (colors) {
manta_script += smoke_alloc_colors_noise; manta_script += smoke_alloc_colors_noise;
if (fire) }
if (fire) {
manta_script += smoke_alloc_fire_noise; manta_script += smoke_alloc_fire_noise;
} }
if (heat) }
if (heat) {
manta_script += smoke_alloc_heat; manta_script += smoke_alloc_heat;
if (colors) }
if (colors) {
manta_script += smoke_alloc_colors; manta_script += smoke_alloc_colors;
if (fire) }
if (fire) {
manta_script += smoke_alloc_fire; manta_script += smoke_alloc_fire;
if (guiding) }
if (guiding) {
manta_script += fluid_alloc_guiding; manta_script += fluid_alloc_guiding;
if (obstacle) }
if (obstacle) {
manta_script += fluid_alloc_obstacle; manta_script += fluid_alloc_obstacle;
if (invel) }
if (invel) {
manta_script += fluid_alloc_invel; manta_script += fluid_alloc_invel;
if (outflow) }
if (outflow) {
manta_script += fluid_alloc_outflow; manta_script += fluid_alloc_outflow;
}
/* Noise field. */ /* Noise field. */
if (noise) if (noise) {
manta_script += smoke_wavelet_noise; manta_script += smoke_wavelet_noise;
}
/* Time. */ /* Time. */
manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step; manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
/* Import. */ /* Import. */
manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data; manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data;
if (noise) if (noise) {
manta_script += smoke_load_noise; manta_script += smoke_load_noise;
if (guiding) }
if (guiding) {
manta_script += fluid_load_guiding; manta_script += fluid_load_guiding;
}
/* Pre/Post Steps. */ /* Pre/Post Steps. */
manta_script += header_prepost + fluid_pre_step + fluid_post_step; manta_script += header_prepost + fluid_pre_step + fluid_post_step;
@ -1773,8 +1857,9 @@ bool MANTA::exportSmokeScript(FluidModifierData *fmd)
bool MANTA::exportLiquidScript(FluidModifierData *fmd) bool MANTA::exportLiquidScript(FluidModifierData *fmd)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::exportLiquidScript()" << endl; cout << "MANTA::exportLiquidScript()" << endl;
}
char cacheDir[FILE_MAX] = "\0"; char cacheDir[FILE_MAX] = "\0";
char cacheDirScript[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0";
@ -1807,44 +1892,60 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
/* Variables. */ /* Variables. */
manta_script += header_variables + fluid_variables + liquid_variables; manta_script += header_variables + fluid_variables + liquid_variables;
if (mesh) if (mesh) {
manta_script += fluid_variables_mesh; manta_script += fluid_variables_mesh;
if (drops || bubble || floater || tracer) }
if (drops || bubble || floater || tracer) {
manta_script += fluid_variables_particles + liquid_variables_particles; manta_script += fluid_variables_particles + liquid_variables_particles;
if (guiding) }
if (guiding) {
manta_script += fluid_variables_guiding; manta_script += fluid_variables_guiding;
if (viscosity) }
if (viscosity) {
manta_script += fluid_variables_viscosity; manta_script += fluid_variables_viscosity;
}
/* Solvers. */ /* Solvers. */
manta_script += header_solvers + fluid_solver; manta_script += header_solvers + fluid_solver;
if (mesh) if (mesh) {
manta_script += fluid_solver_mesh; manta_script += fluid_solver_mesh;
if (drops || bubble || floater || tracer) }
if (drops || bubble || floater || tracer) {
manta_script += fluid_solver_particles; manta_script += fluid_solver_particles;
if (guiding) }
if (guiding) {
manta_script += fluid_solver_guiding; manta_script += fluid_solver_guiding;
if (viscosity) }
if (viscosity) {
manta_script += fluid_solver_viscosity; manta_script += fluid_solver_viscosity;
}
/* Grids. */ /* Grids. */
manta_script += header_grids + fluid_alloc + liquid_alloc; manta_script += header_grids + fluid_alloc + liquid_alloc;
if (mesh) if (mesh) {
manta_script += liquid_alloc_mesh; manta_script += liquid_alloc_mesh;
if (drops || bubble || floater || tracer) }
if (drops || bubble || floater || tracer) {
manta_script += liquid_alloc_particles; manta_script += liquid_alloc_particles;
if (guiding) }
if (guiding) {
manta_script += fluid_alloc_guiding; manta_script += fluid_alloc_guiding;
if (obstacle) }
if (obstacle) {
manta_script += fluid_alloc_obstacle; manta_script += fluid_alloc_obstacle;
if (fractions) }
if (fractions) {
manta_script += fluid_alloc_fractions; manta_script += fluid_alloc_fractions;
if (invel) }
if (invel) {
manta_script += fluid_alloc_invel; manta_script += fluid_alloc_invel;
if (outflow) }
if (outflow) {
manta_script += fluid_alloc_outflow; manta_script += fluid_alloc_outflow;
if (viscosity) }
if (viscosity) {
manta_script += liquid_alloc_viscosity; manta_script += liquid_alloc_viscosity;
}
/* Domain init. */ /* Domain init. */
manta_script += header_gridinit + liquid_init_phi; manta_script += header_gridinit + liquid_init_phi;
@ -1854,22 +1955,27 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
/* Import. */ /* Import. */
manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data; manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data;
if (mesh) if (mesh) {
manta_script += liquid_load_mesh; manta_script += liquid_load_mesh;
if (drops || bubble || floater || tracer) }
if (drops || bubble || floater || tracer) {
manta_script += liquid_load_particles; manta_script += liquid_load_particles;
if (guiding) }
if (guiding) {
manta_script += fluid_load_guiding; manta_script += fluid_load_guiding;
}
/* Pre/Post Steps. */ /* Pre/Post Steps. */
manta_script += header_prepost + fluid_pre_step + fluid_post_step; manta_script += header_prepost + fluid_pre_step + fluid_post_step;
/* Steps. */ /* Steps. */
manta_script += header_steps + liquid_adaptive_step + liquid_step; manta_script += header_steps + liquid_adaptive_step + liquid_step;
if (mesh) if (mesh) {
manta_script += liquid_step_mesh; manta_script += liquid_step_mesh;
if (drops || bubble || floater || tracer) }
if (drops || bubble || floater || tracer) {
manta_script += liquid_step_particles; manta_script += liquid_step_particles;
}
/* Main. */ /* Main. */
manta_script += header_main + liquid_standalone + fluid_standalone; manta_script += header_main + liquid_standalone + fluid_standalone;
@ -1899,9 +2005,10 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false) static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false)
{ {
if ((varName == "") || (functionName == "")) { if ((varName == "") || (functionName == "")) {
if (MANTA::with_debug) if (MANTA::with_debug) {
cout << "Fluid: Missing Python variable name and/or function name -- name is: " << varName cout << "Fluid: Missing Python variable name and/or function name -- name is: " << varName
<< ", function name is: " << functionName << endl; << ", function name is: " << functionName << endl;
}
return nullptr; return nullptr;
} }
@ -1950,8 +2057,9 @@ static PyObject *callPythonFunction(string varName, string functionName, bool is
* If it's not function will handle the reference count decrement of that argument. */ * If it's not function will handle the reference count decrement of that argument. */
static void *pyObjectToPointer(PyObject *inputObject) static void *pyObjectToPointer(PyObject *inputObject)
{ {
if (!inputObject) if (!inputObject) {
return nullptr; return nullptr;
}
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
@ -1975,8 +2083,9 @@ static void *pyObjectToPointer(PyObject *inputObject)
* If it's not function will handle the reference count decrement of that argument. */ * If it's not function will handle the reference count decrement of that argument. */
static double pyObjectToDouble(PyObject *inputObject) static double pyObjectToDouble(PyObject *inputObject)
{ {
if (!inputObject) if (!inputObject) {
return 0.0; return 0.0;
}
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
@ -1993,8 +2102,9 @@ static double pyObjectToDouble(PyObject *inputObject)
* If it's not function will handle the reference count decrement of that argument. */ * If it's not function will handle the reference count decrement of that argument. */
static long pyObjectToLong(PyObject *inputObject) static long pyObjectToLong(PyObject *inputObject)
{ {
if (!inputObject) if (!inputObject) {
return 0; return 0;
}
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
@ -2012,8 +2122,9 @@ template<class T> static T *getPointer(string pyObjectName, string pyFunctionNam
int MANTA::getFrame() int MANTA::getFrame()
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::getFrame()" << endl; cout << "MANTA::getFrame()" << endl;
}
string func = "frame"; string func = "frame";
string id = to_string(mCurrentID); string id = to_string(mCurrentID);
@ -2024,8 +2135,9 @@ int MANTA::getFrame()
float MANTA::getTimestep() float MANTA::getTimestep()
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::getTimestep()" << endl; cout << "MANTA::getTimestep()" << endl;
}
string func = "timestep"; string func = "timestep";
string id = to_string(mCurrentID); string id = to_string(mCurrentID);
@ -2044,8 +2156,9 @@ bool MANTA::needsRealloc(FluidModifierData *fmd)
void MANTA::adaptTimestep() void MANTA::adaptTimestep()
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::adaptTimestep()" << endl; cout << "MANTA::adaptTimestep()" << endl;
}
vector<string> pythonCommands; vector<string> pythonCommands;
ostringstream ss; ostringstream ss;
@ -2058,8 +2171,9 @@ void MANTA::adaptTimestep()
void MANTA::updatePointers(FluidModifierData *fmd, bool flush) void MANTA::updatePointers(FluidModifierData *fmd, bool flush)
{ {
if (with_debug) if (with_debug) {
cout << "MANTA::updatePointers()" << endl; cout << "MANTA::updatePointers()" << endl;
}
FluidDomainSettings *fds = fmd->domain; FluidDomainSettings *fds = fmd->domain;
@ -2214,8 +2328,9 @@ bool MANTA::hasData(FluidModifierData *fmd, int framenr)
string filename = (mUsingSmoke) ? FLUID_NAME_DENSITY : FLUID_NAME_PP; string filename = (mUsingSmoke) ? FLUID_NAME_DENSITY : FLUID_NAME_PP;
exists = BLI_exists(getFile(fmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str()); exists = BLI_exists(getFile(fmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
} }
if (with_debug) if (with_debug) {
cout << "Fluid: Has Data: " << exists << endl; cout << "Fluid: Has Data: " << exists << endl;
}
return exists; return exists;
} }
@ -2240,8 +2355,9 @@ bool MANTA::hasNoise(FluidModifierData *fmd, int framenr)
getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr) getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr)
.c_str()); .c_str());
} }
if (with_debug) if (with_debug) {
cout << "Fluid: Has Noise: " << exists << endl; cout << "Fluid: Has Noise: " << exists << endl;
}
return exists; return exists;
} }
@ -2257,8 +2373,9 @@ bool MANTA::hasMesh(FluidModifierData *fmd, int framenr)
exists = BLI_exists( exists = BLI_exists(
getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str()); getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str());
} }
if (with_debug) if (with_debug) {
cout << "Fluid: Has Mesh: " << exists << endl; cout << "Fluid: Has Mesh: " << exists << endl;
}
return exists; return exists;
} }
@ -2283,8 +2400,9 @@ bool MANTA::hasParticles(FluidModifierData *fmd, int framenr)
getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr) getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr)
.c_str()); .c_str());
} }
if (with_debug) if (with_debug) {
cout << "Fluid: Has Particles: " << exists << endl; cout << "Fluid: Has Particles: " << exists << endl;
}
return exists; return exists;
} }
@ -2302,8 +2420,9 @@ bool MANTA::hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str()); exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str());
} }
if (with_debug) if (with_debug) {
cout << "Fluid: Has Guiding: " << exists << endl; cout << "Fluid: Has Guiding: " << exists << endl;
}
return exists; return exists;
} }

@ -142,10 +142,12 @@ int FallbackImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr * /*config*/)
const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/, const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/,
int index) int index)
{ {
if (index == 0) if (index == 0) {
return "Linear"; return "Linear";
else if (index == 1) }
else if (index == 1) {
return "sRGB"; return "sRGB";
}
return NULL; return NULL;
} }
@ -153,24 +155,33 @@ const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *
OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/, OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/,
const char *name) const char *name)
{ {
if (strcmp(name, "scene_linear") == 0) if (strcmp(name, "scene_linear") == 0) {
return COLORSPACE_LINEAR; return COLORSPACE_LINEAR;
else if (strcmp(name, "color_picking") == 0) }
else if (strcmp(name, "color_picking") == 0) {
return COLORSPACE_SRGB; return COLORSPACE_SRGB;
else if (strcmp(name, "texture_paint") == 0) }
else if (strcmp(name, "texture_paint") == 0) {
return COLORSPACE_LINEAR; return COLORSPACE_LINEAR;
else if (strcmp(name, "default_byte") == 0) }
else if (strcmp(name, "default_byte") == 0) {
return COLORSPACE_SRGB; return COLORSPACE_SRGB;
else if (strcmp(name, "default_float") == 0) }
else if (strcmp(name, "default_float") == 0) {
return COLORSPACE_LINEAR; return COLORSPACE_LINEAR;
else if (strcmp(name, "default_sequencer") == 0) }
else if (strcmp(name, "default_sequencer") == 0) {
return COLORSPACE_SRGB; return COLORSPACE_SRGB;
else if (strcmp(name, "Linear") == 0) }
else if (strcmp(name, "Linear") == 0) {
return COLORSPACE_LINEAR; return COLORSPACE_LINEAR;
else if (strcmp(name, "sRGB") == 0) }
else if (strcmp(name, "sRGB") == 0) {
return COLORSPACE_SRGB; return COLORSPACE_SRGB;
else if (strcmp(name, "data") == 0) }
else if (strcmp(name, "data") == 0) {
return COLORSPACE_DATA; return COLORSPACE_DATA;
}
return NULL; return NULL;
} }
@ -368,12 +379,14 @@ void FallbackImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
for (x = 0; x < width; x++) { for (x = 0; x < width; x++) {
float *pixel = pixels + channels * (y * width + x); float *pixel = pixels + channels * (y * width + x);
if (channels == 4) if (channels == 4) {
cpuProcessorApplyRGBA(cpu_processor, pixel); cpuProcessorApplyRGBA(cpu_processor, pixel);
else if (channels == 3) }
else if (channels == 3) {
cpuProcessorApplyRGB(cpu_processor, pixel); cpuProcessorApplyRGB(cpu_processor, pixel);
} }
} }
}
} }
void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
@ -391,12 +404,14 @@ void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_
for (x = 0; x < width; x++) { for (x = 0; x < width; x++) {
float *pixel = pixels + channels * (y * width + x); float *pixel = pixels + channels * (y * width + x);
if (channels == 4) if (channels == 4) {
cpuProcessorApplyRGBA_predivide(cpu_processor, pixel); cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
else if (channels == 3) }
else if (channels == 3) {
cpuProcessorApplyRGB(cpu_processor, pixel); cpuProcessorApplyRGB(cpu_processor, pixel);
} }
} }
}
} }
void FallbackImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) void FallbackImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)

@ -56,9 +56,10 @@ OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
try { try {
*config = GetCurrentConfig(); *config = GetCurrentConfig();
if (*config) if (*config) {
return (OCIO_ConstConfigRcPtr *)config; return (OCIO_ConstConfigRcPtr *)config;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -85,9 +86,10 @@ OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
try { try {
*config = Config::CreateFromEnv(); *config = Config::CreateFromEnv();
if (*config) if (*config) {
return (OCIO_ConstConfigRcPtr *)config; return (OCIO_ConstConfigRcPtr *)config;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -104,9 +106,10 @@ OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
try { try {
*config = Config::CreateFromFile(filename); *config = Config::CreateFromFile(filename);
if (*config) if (*config) {
return (OCIO_ConstConfigRcPtr *)config; return (OCIO_ConstConfigRcPtr *)config;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -153,9 +156,10 @@ OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *
try { try {
*cs = (*(ConstConfigRcPtr *)config)->getColorSpace(name); *cs = (*(ConstConfigRcPtr *)config)->getColorSpace(name);
if (*cs) if (*cs) {
return (OCIO_ConstColorSpaceRcPtr *)cs; return (OCIO_ConstColorSpaceRcPtr *)cs;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -372,9 +376,10 @@ OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, cons
try { try {
*look = (*(ConstConfigRcPtr *)config)->getLook(name); *look = (*(ConstConfigRcPtr *)config)->getLook(name);
if (*look) if (*look) {
return (OCIO_ConstLookRcPtr *)look; return (OCIO_ConstLookRcPtr *)look;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -522,9 +527,10 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfig
try { try {
*processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName); *processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
if (*processor) if (*processor) {
return (OCIO_ConstProcessorRcPtr *)processor; return (OCIO_ConstProcessorRcPtr *)processor;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
@ -738,9 +744,10 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr
try { try {
*p = config->getProcessor(group); *p = config->getProcessor(group);
if (*p) if (*p) {
return (OCIO_ConstProcessorRcPtr *)p; return (OCIO_ConstProcessorRcPtr *)p;
} }
}
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }

@ -110,24 +110,33 @@ GLStencilTableSSBO::GLStencilTableSSBO(LimitStencilTable const *limitStencilTabl
GLStencilTableSSBO::~GLStencilTableSSBO() GLStencilTableSSBO::~GLStencilTableSSBO()
{ {
if (_sizes) if (_sizes) {
glDeleteBuffers(1, &_sizes); glDeleteBuffers(1, &_sizes);
if (_offsets) }
if (_offsets) {
glDeleteBuffers(1, &_offsets); glDeleteBuffers(1, &_offsets);
if (_indices) }
if (_indices) {
glDeleteBuffers(1, &_indices); glDeleteBuffers(1, &_indices);
if (_weights) }
if (_weights) {
glDeleteBuffers(1, &_weights); glDeleteBuffers(1, &_weights);
if (_duWeights) }
if (_duWeights) {
glDeleteBuffers(1, &_duWeights); glDeleteBuffers(1, &_duWeights);
if (_dvWeights) }
if (_dvWeights) {
glDeleteBuffers(1, &_dvWeights); glDeleteBuffers(1, &_dvWeights);
if (_duuWeights) }
if (_duuWeights) {
glDeleteBuffers(1, &_duuWeights); glDeleteBuffers(1, &_duuWeights);
if (_duvWeights) }
if (_duvWeights) {
glDeleteBuffers(1, &_duvWeights); glDeleteBuffers(1, &_duvWeights);
if (_dvvWeights) }
if (_dvvWeights) {
glDeleteBuffers(1, &_dvvWeights); glDeleteBuffers(1, &_dvvWeights);
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -363,8 +372,9 @@ bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
int end) const int end) const
{ {
if (!_stencilKernel.program) if (!_stencilKernel.program) {
return false; return false;
}
int count = end - start; int count = end - start;
if (count <= 0) { if (count <= 0) {
return true; return true;
@ -381,16 +391,21 @@ bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
if (duWeightsBuffer) if (duWeightsBuffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
if (dvWeightsBuffer) }
if (dvWeightsBuffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);
if (duuWeightsBuffer) }
if (duuWeightsBuffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer);
if (duvWeightsBuffer) }
if (duvWeightsBuffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer);
if (dvvWeightsBuffer) }
if (dvvWeightsBuffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer);
}
GLint activeProgram; GLint activeProgram;
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram); glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
@ -485,8 +500,9 @@ bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
GLuint patchParamsBuffer) const GLuint patchParamsBuffer) const
{ {
if (!_patchKernel.program) if (!_patchKernel.program) {
return false; return false;
}
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
@ -578,8 +594,9 @@ bool GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc
program = compileKernel( program = compileKernel(
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize); srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
if (program == 0) if (program == 0) {
return false; return false;
}
// cache uniform locations (TODO: use uniform block) // cache uniform locations (TODO: use uniform block)
uniformStart = glGetUniformLocation(program, "batchStart"); uniformStart = glGetUniformLocation(program, "batchStart");
@ -623,8 +640,9 @@ bool GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
program = compileKernel( program = compileKernel(
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize); srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
if (program == 0) if (program == 0) {
return false; return false;
}
// cache uniform locations // cache uniform locations
uniformSrcOffset = glGetUniformLocation(program, "srcOffset"); uniformSrcOffset = glGetUniformLocation(program, "srcOffset");