Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/bvh/bvh_embree.cpp
| Show First 20 Lines • Show All 371 Lines • ▼ Show 20 Lines | void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_) | ||||
| rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress); | rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress); | ||||
| rtcCommitScene(scene); | rtcCommitScene(scene); | ||||
| } | } | ||||
| void BVHEmbree::add_object(Object *ob, int i) | void BVHEmbree::add_object(Object *ob, int i) | ||||
| { | { | ||||
| Geometry *geom = ob->get_geometry(); | Geometry *geom = ob->get_geometry(); | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| if (mesh->num_triangles() > 0) { | if (mesh->num_triangles() > 0) { | ||||
| add_triangles(ob, mesh, i); | add_triangles(ob, mesh, i); | ||||
| } | } | ||||
| } | } | ||||
| else if (geom->geometry_type == Geometry::HAIR) { | else if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| if (hair->num_curves() > 0) { | if (hair->num_curves() > 0) { | ||||
| add_curves(ob, hair, i); | add_curves(ob, hair, i); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void BVHEmbree::add_instance(Object *ob, int i) | void BVHEmbree::add_instance(Object *ob, int i) | ||||
| { | { | ||||
| BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->bvh); | BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->get_bvh()); | ||||
| assert(instance_bvh != NULL); | assert(instance_bvh != NULL); | ||||
| const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1; | const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1; | ||||
| const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT); | const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT); | ||||
| assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | ||||
| RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE); | RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE); | ||||
| rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene); | rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene); | ||||
| Show All 26 Lines | void BVHEmbree::add_instance(Object *ob, int i) | ||||
| rtcCommitGeometry(geom_id); | rtcCommitGeometry(geom_id); | ||||
| rtcAttachGeometryByID(scene, geom_id, i * 2); | rtcAttachGeometryByID(scene, geom_id, i * 2); | ||||
| rtcReleaseGeometry(geom_id); | rtcReleaseGeometry(geom_id); | ||||
| } | } | ||||
| void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) | void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) | ||||
| { | { | ||||
| size_t prim_offset = mesh->optix_prim_offset; | size_t prim_offset = mesh->get_optix_prim_offset(); | ||||
| const Attribute *attr_mP = NULL; | const Attribute *attr_mP = NULL; | ||||
| size_t num_motion_steps = 1; | size_t num_motion_steps = 1; | ||||
| if (mesh->has_motion_blur()) { | if (mesh->has_motion_blur()) { | ||||
| attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = mesh->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| if (attr_mP) { | if (attr_mP) { | ||||
| num_motion_steps = mesh->get_motion_steps(); | num_motion_steps = mesh->get_motion_steps(); | ||||
| } | } | ||||
| } | } | ||||
| assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | ||||
| num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT); | num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT); | ||||
| const size_t num_triangles = mesh->num_triangles(); | const size_t num_triangles = mesh->num_triangles(); | ||||
| RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE); | RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE); | ||||
| rtcSetGeometryBuildQuality(geom_id, build_quality); | rtcSetGeometryBuildQuality(geom_id, build_quality); | ||||
| rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); | rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); | ||||
| unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer( | unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer( | ||||
| geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles); | geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles); | ||||
| assert(rtc_indices); | assert(rtc_indices); | ||||
| if (!rtc_indices) { | if (!rtc_indices) { | ||||
| VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str() | VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->get_name().c_str() | ||||
| << ".\n"; | << ".\n"; | ||||
| return; | return; | ||||
| } | } | ||||
| for (size_t j = 0; j < num_triangles; ++j) { | for (size_t j = 0; j < num_triangles; ++j) { | ||||
| Mesh::Triangle t = mesh->get_triangle(j); | Mesh::Triangle t = mesh->get_triangle(j); | ||||
| rtc_indices[j * 3] = t.v[0]; | rtc_indices[j * 3] = t.v[0]; | ||||
| rtc_indices[j * 3 + 1] = t.v[1]; | rtc_indices[j * 3 + 1] = t.v[1]; | ||||
| rtc_indices[j * 3 + 2] = t.v[2]; | rtc_indices[j * 3 + 2] = t.v[2]; | ||||
| Show All 11 Lines | |||||
| } | } | ||||
| void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update) | void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update) | ||||
| { | { | ||||
| const Attribute *attr_mP = NULL; | const Attribute *attr_mP = NULL; | ||||
| size_t num_motion_steps = 1; | size_t num_motion_steps = 1; | ||||
| int t_mid = 0; | int t_mid = 0; | ||||
| if (mesh->has_motion_blur()) { | if (mesh->has_motion_blur()) { | ||||
| attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = mesh->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| if (attr_mP) { | if (attr_mP) { | ||||
| num_motion_steps = mesh->get_motion_steps(); | num_motion_steps = mesh->get_motion_steps(); | ||||
| t_mid = (num_motion_steps - 1) / 2; | t_mid = (num_motion_steps - 1) / 2; | ||||
| if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { | if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { | ||||
| assert(0); | assert(0); | ||||
| num_motion_steps = RTC_MAX_TIME_STEP_COUNT; | num_motion_steps = RTC_MAX_TIME_STEP_COUNT; | ||||
| } | } | ||||
| } | } | ||||
| Show All 35 Lines | void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update) | ||||
| } | } | ||||
| } | } | ||||
| void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update) | void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update) | ||||
| { | { | ||||
| const Attribute *attr_mP = NULL; | const Attribute *attr_mP = NULL; | ||||
| size_t num_motion_steps = 1; | size_t num_motion_steps = 1; | ||||
| if (hair->has_motion_blur()) { | if (hair->has_motion_blur()) { | ||||
| attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = hair->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| if (attr_mP) { | if (attr_mP) { | ||||
| num_motion_steps = hair->get_motion_steps(); | num_motion_steps = hair->get_motion_steps(); | ||||
| } | } | ||||
| } | } | ||||
| const size_t num_curves = hair->num_curves(); | const size_t num_curves = hair->num_curves(); | ||||
| size_t num_keys = 0; | size_t num_keys = 0; | ||||
| for (size_t j = 0; j < num_curves; ++j) { | for (size_t j = 0; j < num_curves; ++j) { | ||||
| const Hair::Curve c = hair->get_curve(j); | const Hair::Curve c = hair->get_curve(j); | ||||
| num_keys += c.num_keys; | num_keys += c.get_num_keys(); | ||||
| } | } | ||||
| /* Catmull-Rom splines need extra CVs at the beginning and end of each curve. */ | /* Catmull-Rom splines need extra CVs at the beginning and end of each curve. */ | ||||
| size_t num_keys_embree = num_keys; | size_t num_keys_embree = num_keys; | ||||
| num_keys_embree += num_curves * 2; | num_keys_embree += num_curves * 2; | ||||
| /* Copy the CV data to Embree */ | /* Copy the CV data to Embree */ | ||||
| const int t_mid = (num_motion_steps - 1) / 2; | const int t_mid = (num_motion_steps - 1) / 2; | ||||
| Show All 17 Lines | float4 *rtc_verts = (update) ? (float4 *)rtcGetGeometryBufferData( | ||||
| sizeof(float) * 4, | sizeof(float) * 4, | ||||
| num_keys_embree); | num_keys_embree); | ||||
| assert(rtc_verts); | assert(rtc_verts); | ||||
| if (rtc_verts) { | if (rtc_verts) { | ||||
| const size_t num_curves = hair->num_curves(); | const size_t num_curves = hair->num_curves(); | ||||
| for (size_t j = 0; j < num_curves; ++j) { | for (size_t j = 0; j < num_curves; ++j) { | ||||
| Hair::Curve c = hair->get_curve(j); | Hair::Curve c = hair->get_curve(j); | ||||
| int fk = c.first_key; | int fk = c.get_first_key(); | ||||
| int k = 1; | int k = 1; | ||||
| for (; k < c.num_keys + 1; ++k, ++fk) { | for (; k < c.get_num_keys() + 1; ++k, ++fk) { | ||||
| rtc_verts[k] = float3_to_float4(verts[fk]); | rtc_verts[k] = float3_to_float4(verts[fk]); | ||||
| rtc_verts[k].w = curve_radius[fk]; | rtc_verts[k].w = curve_radius[fk]; | ||||
| } | } | ||||
| /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */ | /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */ | ||||
| rtc_verts[0] = rtc_verts[1]; | rtc_verts[0] = rtc_verts[1]; | ||||
| rtc_verts[k] = rtc_verts[k - 1]; | rtc_verts[k] = rtc_verts[k - 1]; | ||||
| rtc_verts += c.num_keys + 2; | rtc_verts += c.get_num_keys() + 2; | ||||
| } | } | ||||
| } | } | ||||
| if (update) { | if (update) { | ||||
| rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t); | rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) | void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) | ||||
| { | { | ||||
| size_t prim_offset = hair->optix_prim_offset; | size_t prim_offset = hair->get_optix_prim_offset(); | ||||
| const Attribute *attr_mP = NULL; | const Attribute *attr_mP = NULL; | ||||
| size_t num_motion_steps = 1; | size_t num_motion_steps = 1; | ||||
| if (hair->has_motion_blur()) { | if (hair->has_motion_blur()) { | ||||
| attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = hair->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| if (attr_mP) { | if (attr_mP) { | ||||
| num_motion_steps = hair->get_motion_steps(); | num_motion_steps = hair->get_motion_steps(); | ||||
| } | } | ||||
| } | } | ||||
| assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT); | ||||
| num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT); | num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT); | ||||
| const size_t num_curves = hair->num_curves(); | const size_t num_curves = hair->num_curves(); | ||||
| size_t num_segments = 0; | size_t num_segments = 0; | ||||
| for (size_t j = 0; j < num_curves; ++j) { | for (size_t j = 0; j < num_curves; ++j) { | ||||
| Hair::Curve c = hair->get_curve(j); | Hair::Curve c = hair->get_curve(j); | ||||
| assert(c.num_segments() > 0); | assert(c.num_segments() > 0); | ||||
| num_segments += c.num_segments(); | num_segments += c.num_segments(); | ||||
| } | } | ||||
| enum RTCGeometryType type = (hair->curve_shape == CURVE_RIBBON ? | enum RTCGeometryType type = (hair->get_curve_shape() == CURVE_RIBBON ? | ||||
| RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : | RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : | ||||
| RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); | RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); | ||||
| RTCGeometry geom_id = rtcNewGeometry(rtc_device, type); | RTCGeometry geom_id = rtcNewGeometry(rtc_device, type); | ||||
| rtcSetGeometryTessellationRate(geom_id, params.curve_subdivisions + 1); | rtcSetGeometryTessellationRate(geom_id, params.curve_subdivisions + 1); | ||||
| unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer( | unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer( | ||||
| geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments); | geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments); | ||||
| size_t rtc_index = 0; | size_t rtc_index = 0; | ||||
| for (size_t j = 0; j < num_curves; ++j) { | for (size_t j = 0; j < num_curves; ++j) { | ||||
| Hair::Curve c = hair->get_curve(j); | Hair::Curve c = hair->get_curve(j); | ||||
| for (size_t k = 0; k < c.num_segments(); ++k) { | for (size_t k = 0; k < c.num_segments(); ++k) { | ||||
| rtc_indices[rtc_index] = c.first_key + k; | rtc_indices[rtc_index] = c.get_first_key() + k; | ||||
| /* Room for extra CVs at Catmull-Rom splines. */ | /* Room for extra CVs at Catmull-Rom splines. */ | ||||
| rtc_indices[rtc_index] += j * 2; | rtc_indices[rtc_index] += j * 2; | ||||
| ++rtc_index; | ++rtc_index; | ||||
| } | } | ||||
| } | } | ||||
| rtcSetGeometryBuildQuality(geom_id, build_quality); | rtcSetGeometryBuildQuality(geom_id, build_quality); | ||||
| rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); | rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); | ||||
| set_curve_vertex_buffer(geom_id, hair, false); | set_curve_vertex_buffer(geom_id, hair, false); | ||||
| rtcSetGeometryUserData(geom_id, (void *)prim_offset); | rtcSetGeometryUserData(geom_id, (void *)prim_offset); | ||||
| if (hair->curve_shape == CURVE_RIBBON) { | if (hair->get_curve_shape() == CURVE_RIBBON) { | ||||
| rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); | rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); | ||||
| } | } | ||||
| else { | else { | ||||
| rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve); | rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve); | ||||
| rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve); | rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve); | ||||
| } | } | ||||
| rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); | rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); | ||||
| rtcCommitGeometry(geom_id); | rtcCommitGeometry(geom_id); | ||||
| rtcAttachGeometryByID(scene, geom_id, i * 2 + 1); | rtcAttachGeometryByID(scene, geom_id, i * 2 + 1); | ||||
| rtcReleaseGeometry(geom_id); | rtcReleaseGeometry(geom_id); | ||||
| } | } | ||||
| void BVHEmbree::refit(Progress &progress) | void BVHEmbree::refit(Progress &progress) | ||||
| { | { | ||||
| progress.set_substatus("Refitting BVH nodes"); | progress.set_substatus("Refitting BVH nodes"); | ||||
| /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */ | /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */ | ||||
| unsigned geom_id = 0; | unsigned geom_id = 0; | ||||
| foreach (Object *ob, objects) { | foreach (Object *ob, objects) { | ||||
| if (!params.top_level || (ob->is_traceable() && !ob->get_geometry()->is_instanced())) { | if (!params.top_level || (ob->is_traceable() && !ob->get_geometry()->is_instanced())) { | ||||
| Geometry *geom = ob->get_geometry(); | Geometry *geom = ob->get_geometry(); | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| if (mesh->num_triangles() > 0) { | if (mesh->num_triangles() > 0) { | ||||
| RTCGeometry geom = rtcGetGeometry(scene, geom_id); | RTCGeometry geom = rtcGetGeometry(scene, geom_id); | ||||
| set_tri_vertex_buffer(geom, mesh, true); | set_tri_vertex_buffer(geom, mesh, true); | ||||
| rtcSetGeometryUserData(geom, (void *)mesh->optix_prim_offset); | rtcSetGeometryUserData(geom, (void *)mesh->get_optix_prim_offset()); | ||||
| rtcCommitGeometry(geom); | rtcCommitGeometry(geom); | ||||
| } | } | ||||
| } | } | ||||
| else if (geom->geometry_type == Geometry::HAIR) { | else if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| if (hair->num_curves() > 0) { | if (hair->num_curves() > 0) { | ||||
| RTCGeometry geom = rtcGetGeometry(scene, geom_id + 1); | RTCGeometry geom = rtcGetGeometry(scene, geom_id + 1); | ||||
| set_curve_vertex_buffer(geom, hair, true); | set_curve_vertex_buffer(geom, hair, true); | ||||
| rtcSetGeometryUserData(geom, (void *)hair->optix_prim_offset); | rtcSetGeometryUserData(geom, (void *)hair->get_optix_prim_offset()); | ||||
| rtcCommitGeometry(geom); | rtcCommitGeometry(geom); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| geom_id += 2; | geom_id += 2; | ||||
| } | } | ||||
| rtcCommitScene(scene); | rtcCommitScene(scene); | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||
| #endif /* WITH_EMBREE */ | #endif /* WITH_EMBREE */ | ||||