forked from blender/blender
Rename some functions #25
@ -9,15 +9,92 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
CameraData::CameraData(bContext *context)
|
||||||
|
{
|
||||||
|
View3D *view3d = CTX_wm_view3d(context);
|
||||||
|
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context);
|
||||||
|
ARegion *region = CTX_wm_region(context);
|
||||||
|
|
||||||
|
/* This constant was found experimentally, didn't find such option in
|
||||||
|
* context.view3d or context.region_data. */
|
||||||
|
float VIEWPORT_SENSOR_SIZE = 72.0;
|
||||||
|
|
||||||
|
pxr::GfVec2i res(region->winx, region->winy);
|
||||||
|
float ratio = (float)res[0] / res[1];
|
||||||
|
transform_ = gf_matrix_from_transform(region_data->viewmat).GetInverse();
|
||||||
|
|
||||||
|
switch (region_data->persp) {
|
||||||
|
case RV3D_PERSP: {
|
||||||
|
mode_ = CAM_PERSP;
|
||||||
|
clip_range_ = pxr::GfRange1f(view3d->clip_start, view3d->clip_end);
|
||||||
|
lens_shift_ = pxr::GfVec2f(0.0, 0.0);
|
||||||
|
focal_length_ = view3d->lens;
|
||||||
|
|
||||||
|
if (ratio > 1.0) {
|
||||||
|
sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE * ratio, VIEWPORT_SENSOR_SIZE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RV3D_ORTHO: {
|
||||||
|
mode_ = CAM_ORTHO;
|
||||||
|
lens_shift_ = pxr::GfVec2f(0.0f, 0.0f);
|
||||||
|
|
||||||
|
float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / view3d->lens;
|
||||||
|
float o_depth = view3d->clip_end;
|
||||||
|
|
||||||
|
clip_range_ = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5);
|
||||||
|
|
||||||
|
if (ratio > 1.0f) {
|
||||||
|
ortho_size_ = pxr::GfVec2f(o_size, o_size / ratio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ortho_size_ = pxr::GfVec2f(o_size * ratio, o_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RV3D_CAMOB: {
|
||||||
|
pxr::GfMatrix4d mat = transform_;
|
||||||
|
*this = CameraData(view3d->camera, res, pxr::GfVec4f(0, 0, 1, 1));
|
||||||
|
transform_ = mat;
|
||||||
|
|
||||||
|
/* This formula was taken from previous plugin with corresponded comment.
|
||||||
|
* See blender/intern/cycles/blender/blender_camera.cpp:blender_camera_from_view (look
|
||||||
|
* for 1.41421f). */
|
||||||
|
float zoom = 4.0 / pow((pow(2.0, 0.5) + region_data->camzoom / 50.0), 2);
|
||||||
|
|
||||||
|
/* Updating l_shift due to viewport zoom and view_camera_offset
|
||||||
|
* view_camera_offset should be multiplied by 2. */
|
||||||
|
lens_shift_ = pxr::GfVec2f((lens_shift_[0] + region_data->camdx * 2) / zoom,
|
||||||
|
(lens_shift_[1] + region_data->camdy * 2) / zoom);
|
||||||
|
|
||||||
|
if (mode_ == CAM_ORTHO) {
|
||||||
|
ortho_size_ *= zoom;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sensor_size_ *= zoom;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
|
CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
|
||||||
{
|
{
|
||||||
Camera *camera = (Camera *)camera_obj->data;
|
Camera *camera = (Camera *)camera_obj->data;
|
||||||
|
|
||||||
float t_pos[2] = {tile[0], tile[1]};
|
float t_pos[2] = {tile[0], tile[1]};
|
||||||
float t_size[2] = {tile[2], tile[3]};
|
float t_size[2] = {tile[2], tile[3]};
|
||||||
transform = gf_matrix_from_transform(camera_obj->object_to_world);
|
transform_ = gf_matrix_from_transform(camera_obj->object_to_world);
|
||||||
clip_range = pxr::GfRange1f(camera->clip_start, camera->clip_end);
|
clip_range_ = pxr::GfRange1f(camera->clip_start, camera->clip_end);
|
||||||
mode = camera->type;
|
mode_ = camera->type;
|
||||||
|
|
||||||
if (camera->dof.flag & CAM_DOF_ENABLED) {
|
if (camera->dof.flag & CAM_DOF_ENABLED) {
|
||||||
float focus_distance;
|
float focus_distance;
|
||||||
@ -28,11 +105,11 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
|
|||||||
pxr::GfVec3f obj_pos(camera->dof.focus_object->object_to_world[0][3],
|
pxr::GfVec3f obj_pos(camera->dof.focus_object->object_to_world[0][3],
|
||||||
camera->dof.focus_object->object_to_world[1][3],
|
camera->dof.focus_object->object_to_world[1][3],
|
||||||
camera->dof.focus_object->object_to_world[2][3]);
|
camera->dof.focus_object->object_to_world[2][3]);
|
||||||
pxr::GfVec3f cam_pos(transform[0][3], transform[1][3], transform[2][3]);
|
pxr::GfVec3f cam_pos(transform_[0][3], transform_[1][3], transform_[2][3]);
|
||||||
focus_distance = (obj_pos - cam_pos).GetLength();
|
focus_distance = (obj_pos - cam_pos).GetLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
dof_data = std::tuple(
|
dof_data_ = std::tuple(
|
||||||
std::max(focus_distance, 0.001f), camera->dof.aperture_fstop, camera->dof.aperture_blades);
|
std::max(focus_distance, 0.001f), camera->dof.aperture_fstop, camera->dof.aperture_blades);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,184 +117,112 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
|
|||||||
|
|
||||||
switch (camera->sensor_fit) {
|
switch (camera->sensor_fit) {
|
||||||
case CAMERA_SENSOR_FIT_VERT:
|
case CAMERA_SENSOR_FIT_VERT:
|
||||||
lens_shift = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
|
lens_shift_ = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_HOR:
|
case CAMERA_SENSOR_FIT_HOR:
|
||||||
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
|
lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_AUTO:
|
case CAMERA_SENSOR_FIT_AUTO:
|
||||||
if (ratio > 1.0f) {
|
if (ratio > 1.0f) {
|
||||||
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
|
lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lens_shift = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
|
lens_shift_ = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty);
|
lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lens_shift = pxr::GfVec2f(
|
lens_shift_ = pxr::GfVec2f(
|
||||||
lens_shift[0] / t_size[0] + (t_pos[0] + t_size[0] * 0.5 - 0.5) / t_size[0],
|
lens_shift_[0] / t_size[0] + (t_pos[0] + t_size[0] * 0.5 - 0.5) / t_size[0],
|
||||||
lens_shift[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]);
|
lens_shift_[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]);
|
||||||
|
|
||||||
switch (camera->type) {
|
switch (camera->type) {
|
||||||
case CAM_PERSP:
|
case CAM_PERSP:
|
||||||
focal_length = camera->lens;
|
focal_length_ = camera->lens;
|
||||||
|
|
||||||
switch (camera->sensor_fit) {
|
switch (camera->sensor_fit) {
|
||||||
case CAMERA_SENSOR_FIT_VERT:
|
case CAMERA_SENSOR_FIT_VERT:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_HOR:
|
case CAMERA_SENSOR_FIT_HOR:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_AUTO:
|
case CAMERA_SENSOR_FIT_AUTO:
|
||||||
if (ratio > 1.0f) {
|
if (ratio > 1.0f) {
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sensor_size = pxr::GfVec2f(sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]);
|
sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAM_ORTHO:
|
case CAM_ORTHO:
|
||||||
focal_length = 0.0f;
|
focal_length_ = 0.0f;
|
||||||
switch (camera->sensor_fit) {
|
switch (camera->sensor_fit) {
|
||||||
case CAMERA_SENSOR_FIT_VERT:
|
case CAMERA_SENSOR_FIT_VERT:
|
||||||
ortho_size = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
|
ortho_size_ = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_HOR:
|
case CAMERA_SENSOR_FIT_HOR:
|
||||||
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
|
ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_AUTO:
|
case CAMERA_SENSOR_FIT_AUTO:
|
||||||
if (ratio > 1.0f) {
|
if (ratio > 1.0f) {
|
||||||
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
|
ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ortho_size = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
|
ortho_size_ = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale);
|
ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ortho_size = pxr::GfVec2f(ortho_size[0] * t_size[0], ortho_size[1] * t_size[1]);
|
ortho_size_ = pxr::GfVec2f(ortho_size_[0] * t_size[0], ortho_size_[1] * t_size[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAM_PANO:
|
case CAM_PANO:
|
||||||
/* TODO: Recheck parameters for PANO camera */
|
/* TODO: Recheck parameters for PANO camera */
|
||||||
focal_length = camera->lens;
|
focal_length_ = camera->lens;
|
||||||
|
|
||||||
switch (camera->sensor_fit) {
|
switch (camera->sensor_fit) {
|
||||||
case CAMERA_SENSOR_FIT_VERT:
|
case CAMERA_SENSOR_FIT_VERT:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_HOR:
|
case CAMERA_SENSOR_FIT_HOR:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
||||||
break;
|
break;
|
||||||
case CAMERA_SENSOR_FIT_AUTO:
|
case CAMERA_SENSOR_FIT_AUTO:
|
||||||
if (ratio > 1.0f) {
|
if (ratio > 1.0f) {
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sensor_size = pxr::GfVec2f(sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]);
|
sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
focal_length = camera->lens;
|
focal_length_ = camera->lens;
|
||||||
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraData::CameraData(bContext *context)
|
pxr::GfCamera CameraData::gf_camera()
|
||||||
{
|
{
|
||||||
View3D *view3d = CTX_wm_view3d(context);
|
return gf_camera(pxr::GfVec4f(0, 0, 1, 1));
|
||||||
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context);
|
|
||||||
ARegion *region = CTX_wm_region(context);
|
|
||||||
|
|
||||||
// this constant was found experimentally, didn't find such option in
|
|
||||||
// context.view3d or context.region_data
|
|
||||||
float VIEWPORT_SENSOR_SIZE = 72.0;
|
|
||||||
|
|
||||||
pxr::GfVec2i res(region->winx, region->winy);
|
|
||||||
float ratio = (float)res[0] / res[1];
|
|
||||||
transform = gf_matrix_from_transform(region_data->viewmat).GetInverse();
|
|
||||||
|
|
||||||
switch (region_data->persp) {
|
|
||||||
case RV3D_PERSP: {
|
|
||||||
mode = CAM_PERSP;
|
|
||||||
clip_range = pxr::GfRange1f(view3d->clip_start, view3d->clip_end);
|
|
||||||
lens_shift = pxr::GfVec2f(0.0, 0.0);
|
|
||||||
focal_length = view3d->lens;
|
|
||||||
|
|
||||||
if (ratio > 1.0) {
|
|
||||||
sensor_size = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sensor_size = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE * ratio, VIEWPORT_SENSOR_SIZE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RV3D_ORTHO: {
|
|
||||||
mode = CAM_ORTHO;
|
|
||||||
lens_shift = pxr::GfVec2f(0.0f, 0.0f);
|
|
||||||
|
|
||||||
float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / view3d->lens;
|
|
||||||
float o_depth = view3d->clip_end;
|
|
||||||
|
|
||||||
clip_range = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5);
|
|
||||||
|
|
||||||
if (ratio > 1.0f) {
|
|
||||||
ortho_size = pxr::GfVec2f(o_size, o_size / ratio);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ortho_size = pxr::GfVec2f(o_size * ratio, o_size);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RV3D_CAMOB: {
|
|
||||||
pxr::GfMatrix4d mat = transform;
|
|
||||||
*this = CameraData(view3d->camera, res, pxr::GfVec4f(0, 0, 1, 1));
|
|
||||||
transform = mat;
|
|
||||||
|
|
||||||
// This formula was taken from previous plugin with corresponded comment
|
|
||||||
// See blender/intern/cycles/blender/blender_camera.cpp:blender_camera_from_view (look
|
|
||||||
// for 1.41421f)
|
|
||||||
float zoom = 4.0 / pow((pow(2.0, 0.5) + region_data->camzoom / 50.0), 2);
|
|
||||||
|
|
||||||
// Updating l_shift due to viewport zoom and view_camera_offset
|
|
||||||
// view_camera_offset should be multiplied by 2
|
|
||||||
lens_shift = pxr::GfVec2f((lens_shift[0] + region_data->camdx * 2) / zoom,
|
|
||||||
(lens_shift[1] + region_data->camdy * 2) / zoom);
|
|
||||||
|
|
||||||
if (mode == CAM_ORTHO) {
|
|
||||||
ortho_size *= zoom;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sensor_size *= zoom;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
|
pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
|
||||||
@ -226,19 +231,19 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
|
|||||||
|
|
||||||
pxr::GfCamera gf_camera = pxr::GfCamera();
|
pxr::GfCamera gf_camera = pxr::GfCamera();
|
||||||
|
|
||||||
gf_camera.SetClippingRange(clip_range);
|
gf_camera.SetClippingRange(clip_range_);
|
||||||
|
|
||||||
float l_shift[2] = {(lens_shift[0] + t_pos[0] + t_size[0] * 0.5f - 0.5f) / t_size[0],
|
float l_shift[2] = {(lens_shift_[0] + t_pos[0] + t_size[0] * 0.5f - 0.5f) / t_size[0],
|
||||||
(lens_shift[1] + t_pos[1] + t_size[1] * 0.5f - 0.5f) / t_size[1]};
|
(lens_shift_[1] + t_pos[1] + t_size[1] * 0.5f - 0.5f) / t_size[1]};
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode_) {
|
||||||
case CAM_PERSP:
|
case CAM_PERSP:
|
||||||
case CAM_PANO: {
|
case CAM_PANO: {
|
||||||
/* TODO: store panoramic camera settings */
|
/* TODO: store panoramic camera settings */
|
||||||
gf_camera.SetProjection(pxr::GfCamera::Projection::Perspective);
|
gf_camera.SetProjection(pxr::GfCamera::Projection::Perspective);
|
||||||
gf_camera.SetFocalLength(focal_length);
|
gf_camera.SetFocalLength(focal_length_);
|
||||||
|
|
||||||
float s_size[2] = {sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]};
|
float s_size[2] = {sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]};
|
||||||
|
|
||||||
gf_camera.SetHorizontalAperture(s_size[0]);
|
gf_camera.SetHorizontalAperture(s_size[0]);
|
||||||
gf_camera.SetVerticalAperture(s_size[1]);
|
gf_camera.SetVerticalAperture(s_size[1]);
|
||||||
@ -250,9 +255,9 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
|
|||||||
case CAM_ORTHO: {
|
case CAM_ORTHO: {
|
||||||
gf_camera.SetProjection(pxr::GfCamera::Projection::Orthographic);
|
gf_camera.SetProjection(pxr::GfCamera::Projection::Orthographic);
|
||||||
|
|
||||||
// Use tenths of a world unit accorging to USD docs
|
/* Use tenths of a world unit accorging to USD docs
|
||||||
// https://graphics.pixar.com/usd/docs/api/class_gf_camera.html
|
* https://graphics.pixar.com/usd/docs/api/class_gf_camera.html */
|
||||||
float o_size[2] = {ortho_size[0] * t_size[0] * 10, ortho_size[1] * t_size[1] * 10};
|
float o_size[2] = {ortho_size_[0] * t_size[0] * 10, ortho_size_[1] * t_size[1] * 10};
|
||||||
|
|
||||||
gf_camera.SetHorizontalAperture(o_size[0]);
|
gf_camera.SetHorizontalAperture(o_size[0]);
|
||||||
gf_camera.SetVerticalAperture(o_size[1]);
|
gf_camera.SetVerticalAperture(o_size[1]);
|
||||||
@ -265,13 +270,8 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gf_camera.SetTransform(transform);
|
gf_camera.SetTransform(transform_);
|
||||||
return gf_camera;
|
return gf_camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::GfCamera CameraData::gf_camera()
|
|
||||||
{
|
|
||||||
return gf_camera(pxr::GfVec4f(0, 0, 1, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -23,14 +23,14 @@ class CameraData {
|
|||||||
pxr::GfCamera gf_camera(pxr::GfVec4f tile);
|
pxr::GfCamera gf_camera(pxr::GfVec4f tile);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mode;
|
int mode_;
|
||||||
pxr::GfRange1f clip_range;
|
pxr::GfRange1f clip_range_;
|
||||||
float focal_length;
|
float focal_length_;
|
||||||
pxr::GfVec2f sensor_size;
|
pxr::GfVec2f sensor_size_;
|
||||||
pxr::GfMatrix4d transform;
|
pxr::GfMatrix4d transform_;
|
||||||
pxr::GfVec2f lens_shift;
|
pxr::GfVec2f lens_shift_;
|
||||||
pxr::GfVec2f ortho_size;
|
pxr::GfVec2f ortho_size_;
|
||||||
std::tuple<float, float, int> dof_data;
|
std::tuple<float, float, int> dof_data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -14,51 +14,39 @@ namespace blender::render::hydra {
|
|||||||
|
|
||||||
CLG_LOGREF_DECLARE_GLOBAL(LOG_EN, "rhd.en");
|
CLG_LOGREF_DECLARE_GLOBAL(LOG_EN, "rhd.en");
|
||||||
|
|
||||||
Engine::Engine(RenderEngine *bl_engine, const std::string &delegate_id) : bl_engine(bl_engine)
|
Engine::Engine(RenderEngine *bl_engine, const std::string &delegate_id) : bl_engine_(bl_engine)
|
||||||
{
|
{
|
||||||
pxr::HdRendererPluginRegistry ®istry = pxr::HdRendererPluginRegistry::GetInstance();
|
pxr::HdRendererPluginRegistry ®istry = pxr::HdRendererPluginRegistry::GetInstance();
|
||||||
|
|
||||||
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||||
render_delegate = registry.CreateRenderDelegate(pxr::TfToken(delegate_id));
|
render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(delegate_id));
|
||||||
|
|
||||||
pxr::HdDriverVector hd_drivers;
|
pxr::HdDriverVector hd_drivers;
|
||||||
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
|
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
|
||||||
hgi = pxr::Hgi::CreatePlatformDefaultHgi();
|
hgi_ = pxr::Hgi::CreatePlatformDefaultHgi();
|
||||||
hgi_driver.name = pxr::HgiTokens->renderDriver;
|
hgi_driver_.name = pxr::HgiTokens->renderDriver;
|
||||||
hgi_driver.driver = pxr::VtValue(hgi.get());
|
hgi_driver_.driver = pxr::VtValue(hgi_.get());
|
||||||
|
|
||||||
hd_drivers.push_back(&hgi_driver);
|
hd_drivers.push_back(&hgi_driver_);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_index.reset(pxr::HdRenderIndex::New(render_delegate.Get(), hd_drivers));
|
render_index_.reset(pxr::HdRenderIndex::New(render_delegate_.Get(), hd_drivers));
|
||||||
free_camera_delegate = std::make_unique<pxr::HdxFreeCameraSceneDelegate>(
|
free_camera_delegate_ = std::make_unique<pxr::HdxFreeCameraSceneDelegate>(
|
||||||
render_index.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("freeCamera"));
|
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("freeCamera"));
|
||||||
render_task_delegate = std::make_unique<RenderTaskDelegate>(
|
render_task_delegate_ = std::make_unique<RenderTaskDelegate>(
|
||||||
render_index.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
||||||
if (render_delegate->GetRendererDisplayName() == "GL") {
|
if (render_delegate_->GetRendererDisplayName() == "GL") {
|
||||||
simple_light_task_delegate = std::make_unique<SimpleLightTaskDelegate>(
|
simple_light_task_delegate_ = std::make_unique<SimpleLightTaskDelegate>(
|
||||||
render_index.get(),
|
render_index_.get(),
|
||||||
pxr::SdfPath::AbsoluteRootPath().AppendElementString("simpleLightTask"));
|
pxr::SdfPath::AbsoluteRootPath().AppendElementString("simpleLightTask"));
|
||||||
}
|
}
|
||||||
|
|
||||||
engine = std::make_unique<pxr::HdEngine>();
|
engine_ = std::make_unique<pxr::HdEngine>();
|
||||||
}
|
|
||||||
|
|
||||||
Engine::~Engine()
|
|
||||||
{
|
|
||||||
scene_delegate = nullptr;
|
|
||||||
render_task_delegate = nullptr;
|
|
||||||
free_camera_delegate = nullptr;
|
|
||||||
simple_light_task_delegate = nullptr;
|
|
||||||
render_index = nullptr;
|
|
||||||
render_delegate = nullptr;
|
|
||||||
engine = nullptr;
|
|
||||||
hgi = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Engine::renderer_percent_done()
|
float Engine::renderer_percent_done()
|
||||||
{
|
{
|
||||||
pxr::VtDictionary render_stats = render_delegate->GetRenderStats();
|
pxr::VtDictionary render_stats = render_delegate_->GetRenderStats();
|
||||||
auto it = render_stats.find("percentDone");
|
auto it = render_stats.find("percentDone");
|
||||||
if (it == render_stats.end()) {
|
if (it == render_stats.end()) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include <Python.h>
|
|
||||||
|
|
||||||
#include <pxr/imaging/hd/driver.h>
|
#include <pxr/imaging/hd/driver.h>
|
||||||
#include <pxr/imaging/hd/engine.h>
|
#include <pxr/imaging/hd/engine.h>
|
||||||
#include <pxr/imaging/hd/pluginRenderDelegateUniqueHandle.h>
|
#include <pxr/imaging/hd/pluginRenderDelegateUniqueHandle.h>
|
||||||
@ -28,7 +26,7 @@ extern struct CLG_LogRef *LOG_EN; /* EN - Engine */
|
|||||||
class Engine {
|
class Engine {
|
||||||
public:
|
public:
|
||||||
Engine(RenderEngine *bl_engine, const std::string &render_delegate_id);
|
Engine(RenderEngine *bl_engine, const std::string &render_delegate_id);
|
||||||
virtual ~Engine();
|
virtual ~Engine() = default;
|
||||||
|
|
||||||
virtual void sync(Depsgraph *depsgraph,
|
virtual void sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
@ -38,19 +36,19 @@ class Engine {
|
|||||||
protected:
|
protected:
|
||||||
float renderer_percent_done();
|
float renderer_percent_done();
|
||||||
|
|
||||||
protected:
|
RenderEngine *bl_engine_;
|
||||||
RenderEngine *bl_engine;
|
|
||||||
|
|
||||||
pxr::HdPluginRenderDelegateUniqueHandle render_delegate;
|
/* The order is important due to deletion order */
|
||||||
std::unique_ptr<pxr::HdRenderIndex> render_index;
|
pxr::HdPluginRenderDelegateUniqueHandle render_delegate_;
|
||||||
std::unique_ptr<BlenderSceneDelegate> scene_delegate;
|
std::unique_ptr<pxr::HdRenderIndex> render_index_;
|
||||||
std::unique_ptr<RenderTaskDelegate> render_task_delegate;
|
std::unique_ptr<BlenderSceneDelegate> scene_delegate_;
|
||||||
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate;
|
std::unique_ptr<RenderTaskDelegate> render_task_delegate_;
|
||||||
std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate;
|
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
|
||||||
std::unique_ptr<pxr::HdEngine> engine;
|
std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate_;
|
||||||
|
std::unique_ptr<pxr::HdEngine> engine_;
|
||||||
|
|
||||||
pxr::HgiUniquePtr hgi;
|
pxr::HgiUniquePtr hgi_;
|
||||||
pxr::HdDriver hgi_driver;
|
pxr::HdDriver hgi_driver_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -16,27 +16,27 @@ void FinalEngine::sync(Depsgraph *depsgraph,
|
|||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings)
|
pxr::HdRenderSettingsMap &render_settings)
|
||||||
{
|
{
|
||||||
scene_delegate = std::make_unique<BlenderSceneDelegate>(
|
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
|
||||||
render_index.get(),
|
render_index_.get(),
|
||||||
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
||||||
BlenderSceneDelegate::EngineType::FINAL);
|
BlenderSceneDelegate::EngineType::FINAL);
|
||||||
scene_delegate->populate(depsgraph, context);
|
scene_delegate_->populate(depsgraph, context);
|
||||||
|
|
||||||
for (auto const &setting : render_settings) {
|
for (auto const &setting : render_settings) {
|
||||||
render_delegate->SetRenderSetting(setting.first, setting.second);
|
render_delegate_->SetRenderSetting(setting.first, setting.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalEngine::render(Depsgraph *depsgraph)
|
void FinalEngine::render(Depsgraph *depsgraph)
|
||||||
{
|
{
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
const Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||||
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
|
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
||||||
|
|
||||||
std::string scene_name(MAX_ID_FULL_NAME, 0);
|
std::string scene_name(MAX_ID_FULL_NAME, 0);
|
||||||
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
|
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
|
||||||
std::string layer_name = view_layer->name;
|
std::string layer_name = view_layer->name;
|
||||||
|
|
||||||
RenderData &r = scene->r;
|
const RenderData &r = scene->r;
|
||||||
pxr::GfVec4f border(0, 0, 1, 1);
|
pxr::GfVec4f border(0, 0, 1, 1);
|
||||||
if (r.mode & R_BORDER) {
|
if (r.mode & R_BORDER) {
|
||||||
border = pxr::GfVec4f(r.border.xmin,
|
border = pxr::GfVec4f(r.border.xmin,
|
||||||
@ -49,19 +49,19 @@ void FinalEngine::render(Depsgraph *depsgraph)
|
|||||||
pxr::GfCamera camera =
|
pxr::GfCamera camera =
|
||||||
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
|
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
|
||||||
|
|
||||||
free_camera_delegate->SetCamera(camera);
|
free_camera_delegate_->SetCamera(camera);
|
||||||
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(),
|
render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
|
||||||
pxr::GfVec4d(0, 0, res[0], res[1]));
|
pxr::GfVec4d(0, 0, res[0], res[1]));
|
||||||
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color);
|
render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId());
|
simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
pxr::HdTaskSharedPtrVector tasks;
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
tasks.push_back(simple_light_task_delegate->get_task());
|
tasks.push_back(simple_light_task_delegate_->get_task());
|
||||||
}
|
}
|
||||||
tasks.push_back(render_task_delegate->get_task());
|
tasks.push_back(render_task_delegate_->get_task());
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
|
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
|
||||||
time_current;
|
time_current;
|
||||||
@ -70,17 +70,17 @@ void FinalEngine::render(Depsgraph *depsgraph)
|
|||||||
float percent_done = 0.0;
|
float percent_done = 0.0;
|
||||||
|
|
||||||
std::map<std::string, std::vector<float>> render_images{
|
std::map<std::string, std::vector<float>> render_images{
|
||||||
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; // 4 - number of channels
|
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; /* 4 - number of channels. */
|
||||||
std::vector<float> &pixels = render_images["Combined"];
|
std::vector<float> &pixels = render_images["Combined"];
|
||||||
|
|
||||||
{
|
{
|
||||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
|
||||||
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||||
engine->Execute(render_index.get(), &tasks);
|
engine_->Execute(render_index_.get(), &tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (RE_engine_test_break(bl_engine)) {
|
if (RE_engine_test_break(bl_engine_)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,15 +94,15 @@ void FinalEngine::render(Depsgraph *depsgraph)
|
|||||||
"Render Time: " + format_duration(elapsed_time) +
|
"Render Time: " + format_duration(elapsed_time) +
|
||||||
" | Done: " + std::to_string(int(percent_done)) + "%");
|
" | Done: " + std::to_string(int(percent_done)) + "%");
|
||||||
|
|
||||||
if (render_task_delegate->is_converged()) {
|
if (render_task_delegate_->is_converged()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
||||||
update_render_result(render_images, layer_name, res[0], res[1]);
|
update_render_result(render_images, layer_name, res[0], res[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
||||||
update_render_result(render_images, layer_name, res[0], res[1]);
|
update_render_result(render_images, layer_name, res[0], res[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ void FinalEngine::update_render_result(std::map<std::string, std::vector<float>>
|
|||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
RenderResult *result = RE_engine_begin_result(
|
RenderResult *result = RE_engine_begin_result(
|
||||||
bl_engine, 0, 0, width, height, layer_name.c_str(), nullptr);
|
bl_engine_, 0, 0, width, height, layer_name.c_str(), nullptr);
|
||||||
|
|
||||||
/* TODO: only for the first render layer */
|
/* TODO: only for the first render layer */
|
||||||
RenderLayer *layer = (RenderLayer *)result->layers.first;
|
RenderLayer *layer = (RenderLayer *)result->layers.first;
|
||||||
@ -138,25 +138,25 @@ void FinalEngine::update_render_result(std::map<std::string, std::vector<float>>
|
|||||||
sizeof(float) * pass->rectx * pass->recty * pass->channels);
|
sizeof(float) * pass->rectx * pass->recty * pass->channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
RE_engine_end_result(bl_engine, result, false, false, false);
|
RE_engine_end_result(bl_engine_, result, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalEngine::notify_status(float progress, const std::string &title, const std::string &info)
|
void FinalEngine::notify_status(float progress, const std::string &title, const std::string &info)
|
||||||
{
|
{
|
||||||
RE_engine_update_progress(bl_engine, progress);
|
RE_engine_update_progress(bl_engine_, progress);
|
||||||
RE_engine_update_stats(bl_engine, title.c_str(), info.c_str());
|
RE_engine_update_stats(bl_engine_, title.c_str(), info.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalEngineGL::render(Depsgraph *depsgraph)
|
void FinalEngineGL::render(Depsgraph *depsgraph)
|
||||||
{
|
{
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
const Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||||
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
|
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
||||||
|
|
||||||
std::string scene_name(MAX_ID_FULL_NAME, 0);
|
std::string scene_name(MAX_ID_FULL_NAME, 0);
|
||||||
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
|
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
|
||||||
std::string layer_name = view_layer->name;
|
std::string layer_name = view_layer->name;
|
||||||
|
|
||||||
RenderData &r = scene->r;
|
const RenderData &r = scene->r;
|
||||||
pxr::GfVec4f border(0, 0, 1, 1);
|
pxr::GfVec4f border(0, 0, 1, 1);
|
||||||
if (r.mode & R_BORDER) {
|
if (r.mode & R_BORDER) {
|
||||||
border = pxr::GfVec4f(r.border.xmin,
|
border = pxr::GfVec4f(r.border.xmin,
|
||||||
@ -169,21 +169,21 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
|
|||||||
pxr::GfCamera camera =
|
pxr::GfCamera camera =
|
||||||
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
|
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
|
||||||
|
|
||||||
free_camera_delegate->SetCamera(camera);
|
free_camera_delegate_->SetCamera(camera);
|
||||||
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(),
|
render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
|
||||||
pxr::GfVec4d(0, 0, res[0], res[1]));
|
pxr::GfVec4d(0, 0, res[0], res[1]));
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId());
|
simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
pxr::HdTaskSharedPtrVector tasks;
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
/* TODO: Uncomment this and fix GL error:
|
/* TODO: Uncomment this and fix GL error:
|
||||||
invalid operation, reported from void __cdecl
|
* invalid operation, reported from void __cdecl
|
||||||
pxrInternal_v0_22__pxrReserved__::HgiGLResourceBindings::BindResources(void) */
|
* pxrInternal_v0_22__pxrReserved__::HgiGLResourceBindings::BindResources(void) */
|
||||||
// tasks.push_back(simple_light_task_delegate->get_task());
|
// tasks.push_back(simple_light_task_delegate_->get_task());
|
||||||
}
|
}
|
||||||
tasks.push_back(render_task_delegate->get_task());
|
tasks.push_back(render_task_delegate_->get_task());
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
|
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
|
||||||
time_current;
|
time_current;
|
||||||
@ -192,11 +192,11 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
|
|||||||
float percent_done = 0.0;
|
float percent_done = 0.0;
|
||||||
|
|
||||||
std::map<std::string, std::vector<float>> render_images{
|
std::map<std::string, std::vector<float>> render_images{
|
||||||
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; // 4 - number of channels
|
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; /* 4 - number of channels. */
|
||||||
std::vector<float> &pixels = render_images["Combined"];
|
std::vector<float> &pixels = render_images["Combined"];
|
||||||
|
|
||||||
GPUFrameBuffer *framebuffer = GPU_framebuffer_create("fbHydraRenderFinal");
|
GPUFrameBuffer *framebuffer = GPU_framebuffer_create("fb_hdyra_render_final");
|
||||||
GPUTexture *texture = GPU_texture_create_2d("texHydraRenderFinal",
|
GPUTexture *texture = GPU_texture_create_2d("tex_hydra_render_final",
|
||||||
res[0],
|
res[0],
|
||||||
res[1],
|
res[1],
|
||||||
1,
|
1,
|
||||||
@ -212,13 +212,13 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
|
|||||||
GPU_framebuffer_clear_color_depth(framebuffer, clear_color, 1.0);
|
GPU_framebuffer_clear_color_depth(framebuffer, clear_color, 1.0);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
|
||||||
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||||
engine->Execute(render_index.get(), &tasks);
|
engine_->Execute(render_index_.get(), &tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (RE_engine_test_break(bl_engine)) {
|
if (RE_engine_test_break(bl_engine_)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
|
|||||||
"Render Time: " + format_duration(elapsed_time) +
|
"Render Time: " + format_duration(elapsed_time) +
|
||||||
" | Done: " + std::to_string(int(percent_done)) + "%");
|
" | Done: " + std::to_string(int(percent_done)) + "%");
|
||||||
|
|
||||||
if (render_task_delegate->is_converged()) {
|
if (render_task_delegate_->is_converged()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ namespace blender::render::hydra {
|
|||||||
class FinalEngine : public Engine {
|
class FinalEngine : public Engine {
|
||||||
public:
|
public:
|
||||||
using Engine::Engine;
|
using Engine::Engine;
|
||||||
|
|
||||||
virtual void sync(Depsgraph *depsgraph,
|
virtual void sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings) override;
|
pxr::HdRenderSettingsMap &render_settings) override;
|
||||||
@ -25,13 +26,13 @@ class FinalEngine : public Engine {
|
|||||||
int height);
|
int height);
|
||||||
void notify_status(float progress, const std::string &title, const std::string &info);
|
void notify_status(float progress, const std::string &title, const std::string &info);
|
||||||
|
|
||||||
protected:
|
pxr::HdRenderSettingsMap render_settings_;
|
||||||
pxr::HdRenderSettingsMap render_settings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FinalEngineGL : public FinalEngine {
|
class FinalEngineGL : public FinalEngine {
|
||||||
public:
|
public:
|
||||||
using FinalEngine::FinalEngine;
|
using FinalEngine::FinalEngine;
|
||||||
|
|
||||||
void render(Depsgraph *depsgraph) override;
|
void render(Depsgraph *depsgraph) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,77 +3,61 @@
|
|||||||
|
|
||||||
#include "DEG_depsgraph_query.h"
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
|
#include "BLI_timer.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "preview_engine.h"
|
#include "preview_engine.h"
|
||||||
#include "BLI_timer.h"
|
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
const double LIFETIME = 180.0;
|
const double LIFETIME = 180.0;
|
||||||
|
|
||||||
std::unique_ptr<PreviewEngine> PreviewEngine::instance;
|
std::unique_ptr<PreviewEngine> PreviewEngine::instance_;
|
||||||
|
|
||||||
|
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine,
|
||||||
|
const std::string &render_delegate_id)
|
||||||
|
{
|
||||||
|
if (!instance_) {
|
||||||
|
instance_ = std::make_unique<PreviewEngine>(bl_engine, render_delegate_id);
|
||||||
|
}
|
||||||
|
if (BLI_timer_is_registered((uintptr_t)instance_.get())) {
|
||||||
|
/* Unregister timer while PreviewEngine is working */
|
||||||
|
BLI_timer_unregister((uintptr_t)instance_.get());
|
||||||
|
}
|
||||||
|
instance_->update(bl_engine, render_delegate_id);
|
||||||
|
|
||||||
|
return instance_.get();
|
||||||
|
}
|
||||||
|
|
||||||
void PreviewEngine::schedule_free()
|
void PreviewEngine::schedule_free()
|
||||||
{
|
{
|
||||||
instance->render_delegate->Stop();
|
instance_->render_delegate_->Stop();
|
||||||
|
|
||||||
/* Register timer for schedule free PreviewEngine instance */
|
/* Register timer for schedule free PreviewEngine instance */
|
||||||
BLI_timer_register((uintptr_t)instance.get(),
|
BLI_timer_register((uintptr_t)instance_.get(), free_instance, nullptr, nullptr, LIFETIME, true);
|
||||||
free_instance,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
LIFETIME,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id)
|
|
||||||
{
|
|
||||||
if (!instance) {
|
|
||||||
instance = std::make_unique<PreviewEngine>(bl_engine, render_delegate_id);
|
|
||||||
}
|
|
||||||
if (BLI_timer_is_registered((uintptr_t)instance.get())) {
|
|
||||||
/* Unregister timer while PreviewEngine is working */
|
|
||||||
BLI_timer_unregister((uintptr_t)instance.get());
|
|
||||||
}
|
|
||||||
instance->update(bl_engine, render_delegate_id);
|
|
||||||
|
|
||||||
return instance.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
|
|
||||||
{
|
|
||||||
if (!instance->render_task_delegate->is_converged()) {
|
|
||||||
/* Restart timer if render isn't completed */
|
|
||||||
return LIFETIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOG_INFO(LOG_EN, 2, "");
|
|
||||||
instance = nullptr;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewEngine::sync(Depsgraph *depsgraph,
|
void PreviewEngine::sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings)
|
pxr::HdRenderSettingsMap &render_settings)
|
||||||
{
|
{
|
||||||
if (!scene_delegate) {
|
if (!scene_delegate_) {
|
||||||
scene_delegate = std::make_unique<BlenderSceneDelegate>(
|
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
|
||||||
render_index.get(),
|
render_index_.get(),
|
||||||
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
||||||
BlenderSceneDelegate::EngineType::PREVIEW);
|
BlenderSceneDelegate::EngineType::PREVIEW);
|
||||||
}
|
}
|
||||||
scene_delegate->clear();
|
scene_delegate_->clear();
|
||||||
scene_delegate->populate(depsgraph, context);
|
scene_delegate_->populate(depsgraph, context);
|
||||||
|
|
||||||
for (auto const &setting : render_settings) {
|
for (auto const &setting : render_settings) {
|
||||||
render_delegate->SetRenderSetting(setting.first, setting.second);
|
render_delegate_->SetRenderSetting(setting.first, setting.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewEngine::render(Depsgraph *depsgraph)
|
void PreviewEngine::render(Depsgraph *depsgraph)
|
||||||
{
|
{
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
const Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||||
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
|
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
||||||
|
|
||||||
std::string layer_name = view_layer->name;
|
std::string layer_name = view_layer->name;
|
||||||
pxr::GfVec2i res(scene->r.xsch, scene->r.ysch);
|
pxr::GfVec2i res(scene->r.xsch, scene->r.ysch);
|
||||||
@ -81,45 +65,58 @@ void PreviewEngine::render(Depsgraph *depsgraph)
|
|||||||
pxr::GfCamera camera =
|
pxr::GfCamera camera =
|
||||||
CameraData(scene->camera, res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(pxr::GfVec4f(0, 0, 1, 1));
|
CameraData(scene->camera, res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(pxr::GfVec4f(0, 0, 1, 1));
|
||||||
|
|
||||||
free_camera_delegate->SetCamera(camera);
|
free_camera_delegate_->SetCamera(camera);
|
||||||
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(),
|
render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
|
||||||
pxr::GfVec4d(0, 0, res[0], res[1]));
|
pxr::GfVec4d(0, 0, res[0], res[1]));
|
||||||
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color);
|
render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
pxr::HdTaskSharedPtrVector tasks;
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
tasks.push_back(simple_light_task_delegate->get_task());
|
tasks.push_back(simple_light_task_delegate_->get_task());
|
||||||
}
|
}
|
||||||
tasks.push_back(render_task_delegate->get_task());
|
tasks.push_back(render_task_delegate_->get_task());
|
||||||
|
|
||||||
std::vector<float> pixels = std::vector<float>(res[0] * res[1] * 4); // 4 - number of channels
|
std::vector<float> pixels = std::vector<float>(res[0] * res[1] *
|
||||||
|
4); /* 4 - number of channels. */
|
||||||
|
|
||||||
{
|
{
|
||||||
// Release the GIL before calling into hydra, in case any hydra plugins call into python.
|
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
|
||||||
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||||
engine->Execute(render_index.get(), &tasks);
|
engine_->Execute(render_index_.get(), &tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (RE_engine_test_break(bl_engine)) {
|
if (RE_engine_test_break(bl_engine_)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render_task_delegate->is_converged()) {
|
if (render_task_delegate_->is_converged()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
||||||
update_render_result(layer_name, res[0], res[1], pixels);
|
update_render_result(layer_name, res[0], res[1], pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
|
||||||
update_render_result(layer_name, res[0], res[1], pixels);
|
update_render_result(layer_name, res[0], res[1], pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
|
||||||
|
{
|
||||||
|
if (!instance_->render_task_delegate_->is_converged()) {
|
||||||
|
/* Restart timer if render isn't completed */
|
||||||
|
return LIFETIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOG_INFO(LOG_EN, 2, "");
|
||||||
|
instance_ = nullptr;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_id)
|
void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_id)
|
||||||
{
|
{
|
||||||
this->bl_engine = bl_engine;
|
this->bl_engine_ = bl_engine;
|
||||||
/* TODO: recreate render_delegate when render_delegate_id is changed */
|
/* TODO: recreate render_delegate when render_delegate_id is changed */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,13 +126,13 @@ void PreviewEngine::update_render_result(const std::string &layer_name,
|
|||||||
std::vector<float> &pixels)
|
std::vector<float> &pixels)
|
||||||
{
|
{
|
||||||
RenderResult *result = RE_engine_begin_result(
|
RenderResult *result = RE_engine_begin_result(
|
||||||
bl_engine, 0, 0, width, height, layer_name.c_str(), nullptr);
|
bl_engine_, 0, 0, width, height, layer_name.c_str(), nullptr);
|
||||||
|
|
||||||
RenderLayer *layer = (RenderLayer *)result->layers.first;
|
RenderLayer *layer = (RenderLayer *)result->layers.first;
|
||||||
RenderPass *pass = (RenderPass *)layer->passes.first;
|
RenderPass *pass = (RenderPass *)layer->passes.first;
|
||||||
memcpy(pass->rect, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels);
|
memcpy(pass->rect, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels);
|
||||||
|
|
||||||
RE_engine_end_result(bl_engine, result, false, false, false);
|
RE_engine_end_result(bl_engine_, result, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -8,28 +8,28 @@
|
|||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
class PreviewEngine : public FinalEngine {
|
class PreviewEngine : public FinalEngine {
|
||||||
private:
|
|
||||||
/* Singleton class instance */
|
|
||||||
static std::unique_ptr<PreviewEngine> instance;
|
|
||||||
static double free_instance(uintptr_t uuid, void *user_data);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static PreviewEngine *get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id);
|
using FinalEngine::FinalEngine;
|
||||||
|
|
||||||
|
static PreviewEngine *get_instance(RenderEngine *bl_engine,
|
||||||
|
const std::string &render_delegate_id);
|
||||||
static void schedule_free();
|
static void schedule_free();
|
||||||
|
|
||||||
using FinalEngine::FinalEngine;
|
|
||||||
void sync(Depsgraph *depsgraph,
|
void sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings) override;
|
pxr::HdRenderSettingsMap &render_settings) override;
|
||||||
void render(Depsgraph *depsgraph) override;
|
void render(Depsgraph *depsgraph) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/* Singleton class instance */
|
||||||
|
static double free_instance(uintptr_t uuid, void *user_data);
|
||||||
|
static std::unique_ptr<PreviewEngine> instance_;
|
||||||
|
|
||||||
void update(RenderEngine *bl_engine, const std::string &render_delegate_id);
|
void update(RenderEngine *bl_engine, const std::string &render_delegate_id);
|
||||||
void update_render_result(const std::string &layer_name,
|
void update_render_result(const std::string &layer_name,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
std::vector<float> &pixels);
|
std::vector<float> &pixels);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -236,8 +236,8 @@ static PyMethodDef methods[] = {
|
|||||||
|
|
||||||
{"engine_create", engine_create_func, METH_VARARGS, ""},
|
{"engine_create", engine_create_func, METH_VARARGS, ""},
|
||||||
{"engine_free", engine_free_func, METH_VARARGS, ""},
|
{"engine_free", engine_free_func, METH_VARARGS, ""},
|
||||||
{"engine_render", engine_render_func, METH_VARARGS, ""},
|
|
||||||
{"engine_sync", engine_sync_func, METH_VARARGS, ""},
|
{"engine_sync", engine_sync_func, METH_VARARGS, ""},
|
||||||
|
{"engine_render", engine_render_func, METH_VARARGS, ""},
|
||||||
{"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""},
|
{"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL},
|
{NULL, NULL, 0, NULL},
|
||||||
|
@ -22,8 +22,8 @@ RenderTaskDelegate::RenderTaskDelegate(pxr::HdRenderIndex *parent_index,
|
|||||||
GetRenderIndex().GetChangeTracker().MarkTaskDirty(render_task_id,
|
GetRenderIndex().GetChangeTracker().MarkTaskDirty(render_task_id,
|
||||||
pxr::HdChangeTracker::DirtyRenderTags);
|
pxr::HdChangeTracker::DirtyRenderTags);
|
||||||
|
|
||||||
task_params.enableLighting = true;
|
task_params_.enableLighting = true;
|
||||||
task_params.alphaThreshold = 0.1f;
|
task_params_.alphaThreshold = 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::SdfPath RenderTaskDelegate::get_task_id() const
|
pxr::SdfPath RenderTaskDelegate::get_task_id() const
|
||||||
@ -36,32 +36,6 @@ pxr::SdfPath RenderTaskDelegate::get_aov_id(pxr::TfToken const &aov) const
|
|||||||
return GetDelegateID().AppendElementString("aov_" + aov.GetString());
|
return GetDelegateID().AppendElementString("aov_" + aov.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
|
||||||
{
|
|
||||||
if (key == pxr::HdTokens->params) {
|
|
||||||
return pxr::VtValue(task_params);
|
|
||||||
}
|
|
||||||
if (key == pxr::HdTokens->collection) {
|
|
||||||
pxr::HdRprimCollection rprim_collection(pxr::HdTokens->geometry,
|
|
||||||
pxr::HdReprSelector(pxr::HdReprTokens->smoothHull),
|
|
||||||
false,
|
|
||||||
pxr::TfToken());
|
|
||||||
rprim_collection.SetRootPath(pxr::SdfPath::AbsoluteRootPath());
|
|
||||||
return pxr::VtValue(rprim_collection);
|
|
||||||
}
|
|
||||||
return pxr::VtValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr::SdfPath const &id)
|
|
||||||
{
|
|
||||||
return buffer_descriptors[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::TfTokenVector RenderTaskDelegate::GetTaskRenderTags(pxr::SdfPath const &task_id)
|
|
||||||
{
|
|
||||||
return {pxr::HdRenderTagTokens->geometry};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderTaskDelegate::is_converged()
|
bool RenderTaskDelegate::is_converged()
|
||||||
{
|
{
|
||||||
pxr::HdTaskSharedPtr renderTask = GetRenderIndex().GetTask(get_task_id());
|
pxr::HdTaskSharedPtr renderTask = GetRenderIndex().GetTask(get_task_id());
|
||||||
@ -73,14 +47,14 @@ void RenderTaskDelegate::set_renderer_aov(pxr::TfToken const &aov)
|
|||||||
pxr::HdAovDescriptor aov_desc = GetRenderIndex().GetRenderDelegate()->GetDefaultAovDescriptor(
|
pxr::HdAovDescriptor aov_desc = GetRenderIndex().GetRenderDelegate()->GetDefaultAovDescriptor(
|
||||||
aov);
|
aov);
|
||||||
pxr::HdRenderBufferDescriptor desc(
|
pxr::HdRenderBufferDescriptor desc(
|
||||||
pxr::GfVec3i(task_params.viewport[2], task_params.viewport[3], 1),
|
pxr::GfVec3i(task_params_.viewport[2], task_params_.viewport[3], 1),
|
||||||
aov_desc.format,
|
aov_desc.format,
|
||||||
aov_desc.multiSampled);
|
aov_desc.multiSampled);
|
||||||
pxr::SdfPath buffer_id = get_aov_id(aov);
|
pxr::SdfPath buffer_id = get_aov_id(aov);
|
||||||
|
|
||||||
if (buffer_descriptors.find(buffer_id) == buffer_descriptors.end()) {
|
if (buffer_descriptors_.find(buffer_id) == buffer_descriptors_.end()) {
|
||||||
GetRenderIndex().InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buffer_id);
|
GetRenderIndex().InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buffer_id);
|
||||||
buffer_descriptors[buffer_id] = desc;
|
buffer_descriptors_[buffer_id] = desc;
|
||||||
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
|
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
|
||||||
pxr::HdRenderBuffer::DirtyDescription);
|
pxr::HdRenderBuffer::DirtyDescription);
|
||||||
|
|
||||||
@ -88,13 +62,13 @@ void RenderTaskDelegate::set_renderer_aov(pxr::TfToken const &aov)
|
|||||||
binding.aovName = aov;
|
binding.aovName = aov;
|
||||||
binding.renderBufferId = buffer_id;
|
binding.renderBufferId = buffer_id;
|
||||||
binding.aovSettings = aov_desc.aovSettings;
|
binding.aovSettings = aov_desc.aovSettings;
|
||||||
task_params.aovBindings.push_back(binding);
|
task_params_.aovBindings.push_back(binding);
|
||||||
|
|
||||||
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
|
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
|
||||||
pxr::HdChangeTracker::DirtyParams);
|
pxr::HdChangeTracker::DirtyParams);
|
||||||
}
|
}
|
||||||
else if (buffer_descriptors[buffer_id] != desc) {
|
else if (buffer_descriptors_[buffer_id] != desc) {
|
||||||
buffer_descriptors[buffer_id] = desc;
|
buffer_descriptors_[buffer_id] = desc;
|
||||||
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
|
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
|
||||||
pxr::HdRenderBuffer::DirtyDescription);
|
pxr::HdRenderBuffer::DirtyDescription);
|
||||||
}
|
}
|
||||||
@ -124,12 +98,38 @@ pxr::HdTaskSharedPtr RenderTaskDelegate::get_task()
|
|||||||
void RenderTaskDelegate::set_camera_and_viewport(pxr::SdfPath const &camera_id,
|
void RenderTaskDelegate::set_camera_and_viewport(pxr::SdfPath const &camera_id,
|
||||||
pxr::GfVec4d const &viewport)
|
pxr::GfVec4d const &viewport)
|
||||||
{
|
{
|
||||||
if (task_params.viewport != viewport || task_params.camera != camera_id) {
|
if (task_params_.viewport != viewport || task_params_.camera != camera_id) {
|
||||||
task_params.viewport = viewport;
|
task_params_.viewport = viewport;
|
||||||
task_params.camera = camera_id;
|
task_params_.camera = camera_id;
|
||||||
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
|
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
|
||||||
pxr::HdChangeTracker::DirtyParams);
|
pxr::HdChangeTracker::DirtyParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
||||||
|
{
|
||||||
|
if (key == pxr::HdTokens->params) {
|
||||||
|
return pxr::VtValue(task_params_);
|
||||||
|
}
|
||||||
|
if (key == pxr::HdTokens->collection) {
|
||||||
|
pxr::HdRprimCollection rprim_collection(pxr::HdTokens->geometry,
|
||||||
|
pxr::HdReprSelector(pxr::HdReprTokens->smoothHull),
|
||||||
|
false,
|
||||||
|
pxr::TfToken());
|
||||||
|
rprim_collection.SetRootPath(pxr::SdfPath::AbsoluteRootPath());
|
||||||
|
return pxr::VtValue(rprim_collection);
|
||||||
|
}
|
||||||
|
return pxr::VtValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr::SdfPath const &id)
|
||||||
|
{
|
||||||
|
return buffer_descriptors_[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::TfTokenVector RenderTaskDelegate::GetTaskRenderTags(pxr::SdfPath const &task_id)
|
||||||
|
{
|
||||||
|
return {pxr::HdRenderTagTokens->geometry};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -16,10 +16,6 @@ class RenderTaskDelegate : public pxr::HdSceneDelegate {
|
|||||||
pxr::SdfPath get_task_id() const;
|
pxr::SdfPath get_task_id() const;
|
||||||
pxr::SdfPath get_aov_id(pxr::TfToken const &aov) const;
|
pxr::SdfPath get_aov_id(pxr::TfToken const &aov) const;
|
||||||
|
|
||||||
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
|
||||||
pxr::HdRenderBufferDescriptor GetRenderBufferDescriptor(pxr::SdfPath const &id) override;
|
|
||||||
pxr::TfTokenVector GetTaskRenderTags(pxr::SdfPath const &taskId) override;
|
|
||||||
|
|
||||||
bool is_converged();
|
bool is_converged();
|
||||||
void set_renderer_aov(pxr::TfToken const &aovId);
|
void set_renderer_aov(pxr::TfToken const &aovId);
|
||||||
pxr::HdRenderBuffer *get_renderer_aov(pxr::TfToken const &id);
|
pxr::HdRenderBuffer *get_renderer_aov(pxr::TfToken const &id);
|
||||||
@ -28,10 +24,15 @@ class RenderTaskDelegate : public pxr::HdSceneDelegate {
|
|||||||
pxr::HdTaskSharedPtr get_task();
|
pxr::HdTaskSharedPtr get_task();
|
||||||
void set_camera_and_viewport(pxr::SdfPath const &cameraId, pxr::GfVec4d const &viewport);
|
void set_camera_and_viewport(pxr::SdfPath const &cameraId, pxr::GfVec4d const &viewport);
|
||||||
|
|
||||||
|
/* Delegate methods */
|
||||||
|
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
||||||
|
pxr::HdRenderBufferDescriptor GetRenderBufferDescriptor(pxr::SdfPath const &id) override;
|
||||||
|
pxr::TfTokenVector GetTaskRenderTags(pxr::SdfPath const &taskId) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pxr::HdxRenderTaskParams task_params;
|
pxr::HdxRenderTaskParams task_params_;
|
||||||
pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash>
|
pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash>
|
||||||
buffer_descriptors;
|
buffer_descriptors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -16,31 +16,205 @@ CLG_LOGREF_DECLARE_GLOBAL(LOG_BSD, "rhd.bsd");
|
|||||||
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
|
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
|
||||||
pxr::SdfPath const &delegate_id,
|
pxr::SdfPath const &delegate_id,
|
||||||
BlenderSceneDelegate::EngineType engine_type)
|
BlenderSceneDelegate::EngineType engine_type)
|
||||||
: HdSceneDelegate(parent_index, delegate_id),
|
: HdSceneDelegate(parent_index, delegate_id), engine_type(engine_type)
|
||||||
engine_type(engine_type),
|
|
||||||
depsgraph(nullptr),
|
|
||||||
context(nullptr),
|
|
||||||
view3d(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::update_world()
|
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
|
||||||
{
|
{
|
||||||
World *world = scene->world;
|
bool is_populated = depsgraph_ != nullptr;
|
||||||
if (!world_data) {
|
|
||||||
if (world) {
|
depsgraph_ = deps;
|
||||||
world_data = WorldData::create(this, world, context);
|
context_ = cont;
|
||||||
|
scene_ = DEG_get_input_scene(depsgraph_);
|
||||||
|
view3d_ = CTX_wm_view3d(context_);
|
||||||
|
|
||||||
|
if (!is_populated) {
|
||||||
|
/* Export initial objects */
|
||||||
|
update_collection(false, false);
|
||||||
|
update_world();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Working with updates */
|
||||||
|
bool do_update_collection = false;
|
||||||
|
bool do_update_visibility = false;
|
||||||
|
bool do_update_world = false;
|
||||||
|
|
||||||
|
unsigned int scene_recalc = ((ID *)scene_)->recalc;
|
||||||
|
if (scene_recalc) {
|
||||||
|
/* Checking scene updates */
|
||||||
|
CLOG_INFO(LOG_BSD,
|
||||||
|
2,
|
||||||
|
"Update: %s [%s]",
|
||||||
|
((ID *)scene_)->name,
|
||||||
|
std::bitset<32>(scene_recalc).to_string().c_str());
|
||||||
|
|
||||||
|
if (scene_recalc & ID_RECALC_BASE_FLAGS) {
|
||||||
|
do_update_visibility = true;
|
||||||
|
}
|
||||||
|
if (scene_recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) {
|
||||||
|
do_update_collection = true;
|
||||||
|
}
|
||||||
|
if (scene_recalc & ID_RECALC_AUDIO_VOLUME) {
|
||||||
|
if ((scene_->world && !world_data_) || (!scene_->world && world_data_)) {
|
||||||
|
do_update_world = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if (do_update_collection || do_update_visibility) {
|
||||||
if (world) {
|
update_collection(do_update_collection, do_update_visibility);
|
||||||
world_data->update(world);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
world_data->remove();
|
|
||||||
world_data = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Checking other objects updates */
|
||||||
|
DEGIDIterData data = {0};
|
||||||
|
data.graph = depsgraph_;
|
||||||
|
data.only_updated = true;
|
||||||
|
ITER_BEGIN (
|
||||||
|
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) {
|
||||||
|
|
||||||
|
CLOG_INFO(
|
||||||
|
LOG_BSD, 2, "Update: %s [%s]", id->name, std::bitset<32>(id->recalc).to_string().c_str());
|
||||||
|
|
||||||
|
switch (GS(id->name)) {
|
||||||
|
case ID_OB: {
|
||||||
|
Object *object = (Object *)id;
|
||||||
|
if (!ObjectData::is_supported(object)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
add_update_object(object);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ID_MA: {
|
||||||
|
MaterialData *mat_data = material_data(MaterialData::prim_id(this, (Material *)id));
|
||||||
|
if (mat_data) {
|
||||||
|
mat_data->update();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ID_WO: {
|
||||||
|
if (id->recalc & ID_RECALC_SHADING) {
|
||||||
|
do_update_world = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ITER_END;
|
||||||
|
|
||||||
|
if (do_update_world) {
|
||||||
|
update_world();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlenderSceneDelegate::clear()
|
||||||
|
{
|
||||||
|
for (auto &it : materials_) {
|
||||||
|
it.second->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &it : objects_) {
|
||||||
|
it.second->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
materials_.clear();
|
||||||
|
objects_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 3, "%s", id.GetText());
|
||||||
|
MeshData *m_data = mesh_data(id);
|
||||||
|
return m_data->mesh_topology();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 3, "%s", id.GetText());
|
||||||
|
ObjectData *obj_data = object_data(id);
|
||||||
|
if (obj_data) {
|
||||||
|
return obj_data->transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == WorldData::prim_id(this)) {
|
||||||
|
return world_data_->transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
InstancerData *i_data = instancer_data(id);
|
||||||
|
if (i_data) {
|
||||||
|
return i_data->transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxr::GfMatrix4d();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 3, "%s, %s", id.GetText(), key.GetText());
|
||||||
|
|
||||||
|
ObjectData *obj_data = object_data(id);
|
||||||
|
if (obj_data) {
|
||||||
|
return obj_data->get_data(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialData *mat_data = material_data(id);
|
||||||
|
if (mat_data) {
|
||||||
|
return mat_data->get_data(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstancerData *i_data = instancer_data(id);
|
||||||
|
if (i_data) {
|
||||||
|
return i_data->get_data(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxr::VtValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
|
||||||
|
pxr::TfToken const &key)
|
||||||
|
{
|
||||||
|
LightData *l_data = light_data(id);
|
||||||
|
if (l_data) {
|
||||||
|
return l_data->get_data(key);
|
||||||
|
}
|
||||||
|
if (id == WorldData::prim_id(this)) {
|
||||||
|
return world_data_->get_data(key);
|
||||||
|
}
|
||||||
|
return pxr::VtValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
|
||||||
|
pxr::SdfPath const &id, pxr::HdInterpolation interpolation)
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 3, "%s, %d", id.GetText(), interpolation);
|
||||||
|
|
||||||
|
MeshData *m_data = mesh_data(id);
|
||||||
|
if (m_data) {
|
||||||
|
return m_data->primvar_descriptors(interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstancerData *i_data = instancer_data(id);
|
||||||
|
if (i_data) {
|
||||||
|
return i_data->instancer_primvar_descriptors(interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxr::HdPrimvarDescriptorVector();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
|
||||||
|
{
|
||||||
|
return mesh_data(rprim_id)->material_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
|
||||||
|
{
|
||||||
|
MaterialData *mat_data = material_data(id);
|
||||||
|
if (mat_data) {
|
||||||
|
return mat_data->get_material_resource();
|
||||||
|
}
|
||||||
|
return pxr::VtValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
|
bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
|
||||||
@ -85,128 +259,10 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &
|
|||||||
return i_data->transform();
|
return i_data->transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
|
|
||||||
{
|
|
||||||
if (visibility) {
|
|
||||||
/* Check and update visibility */
|
|
||||||
for (auto &obj : objects) {
|
|
||||||
obj.second->update_visibility(view3d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export of new visible objects which were not exported before */
|
|
||||||
std::set<pxr::SdfPath> available_objects;
|
|
||||||
pxr::SdfPath id;
|
|
||||||
|
|
||||||
DEGObjectIterSettings settings = {0};
|
|
||||||
settings.depsgraph = depsgraph;
|
|
||||||
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
|
|
||||||
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
|
|
||||||
DEGObjectIterData data = {0};
|
|
||||||
data.settings = &settings;
|
|
||||||
data.graph = settings.depsgraph;
|
|
||||||
data.flag = settings.flags;
|
|
||||||
ITER_BEGIN (DEG_iterator_objects_begin,
|
|
||||||
DEG_iterator_objects_next,
|
|
||||||
DEG_iterator_objects_end,
|
|
||||||
&data,
|
|
||||||
Object *,
|
|
||||||
object) {
|
|
||||||
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "Add %s", ((ID *)object)->name);
|
|
||||||
if (!ObjectData::supported(object)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = ObjectData::prim_id(this, object);
|
|
||||||
if (remove) {
|
|
||||||
available_objects.insert(id);
|
|
||||||
if ((object->transflag & OB_DUPLI) && InstancerData::supported(object)) {
|
|
||||||
available_objects.insert(InstancerData::prim_id(this, object));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!object_data(id)) {
|
|
||||||
add_update_object(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ITER_END;
|
|
||||||
|
|
||||||
if (remove) {
|
|
||||||
/* remove unused objects */
|
|
||||||
for (auto it = objects.begin(); it != objects.end(); ++it) {
|
|
||||||
if (available_objects.find(it->first) != available_objects.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
it->second->remove();
|
|
||||||
objects.erase(it);
|
|
||||||
it = objects.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove unused materials */
|
|
||||||
std::set<pxr::SdfPath> available_materials;
|
|
||||||
for (auto &obj : objects) {
|
|
||||||
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
|
|
||||||
if (!m_data) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pxr::SdfPath mat_id = m_data->material_id();
|
|
||||||
if (!mat_id.IsEmpty()) {
|
|
||||||
available_materials.insert(mat_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto it = materials.begin(); it != materials.end(); ++it) {
|
|
||||||
if (available_materials.find(it->first) != available_materials.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
it->second->remove();
|
|
||||||
materials.erase(it);
|
|
||||||
it = materials.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSceneDelegate::add_update_object(Object *object)
|
|
||||||
{
|
|
||||||
if ((object->transflag & OB_DUPLI) && InstancerData::supported(object)) {
|
|
||||||
add_update_instancer(object);
|
|
||||||
}
|
|
||||||
InstancerData *i_data = instancer_data(object);
|
|
||||||
if (i_data) {
|
|
||||||
i_data->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::SdfPath id = ObjectData::prim_id(this, object);
|
|
||||||
ObjectData *obj_data = object_data(id);
|
|
||||||
if (obj_data) {
|
|
||||||
obj_data->update();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (view3d && !BKE_object_is_visible_in_viewport(view3d, object)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
objects[id] = ObjectData::create(this, object);
|
|
||||||
obj_data = object_data(id);
|
|
||||||
obj_data->update_visibility(view3d);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSceneDelegate::add_update_instancer(Object *object)
|
|
||||||
{
|
|
||||||
pxr::SdfPath id = InstancerData::prim_id(this, object);
|
|
||||||
InstancerData *i_data = instancer_data(id, true);
|
|
||||||
if (i_data) {
|
|
||||||
i_data->update();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
objects[id] = InstancerData::create(this, object);
|
|
||||||
i_data = instancer_data(id, true);
|
|
||||||
i_data->update_visibility(view3d);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id)
|
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id)
|
||||||
{
|
{
|
||||||
auto it = objects.find(id);
|
auto it = objects_.find(id);
|
||||||
if (it == objects.end()) {
|
if (it == objects_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
@ -224,8 +280,8 @@ LightData *BlenderSceneDelegate::light_data(pxr::SdfPath const &id)
|
|||||||
|
|
||||||
MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
|
MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
|
||||||
{
|
{
|
||||||
auto it = materials.find(id);
|
auto it = materials_.find(id);
|
||||||
if (it == materials.end()) {
|
if (it == materials_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
@ -242,7 +298,7 @@ InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool
|
|||||||
InstancerData *BlenderSceneDelegate::instancer_data(Object *object)
|
InstancerData *BlenderSceneDelegate::instancer_data(Object *object)
|
||||||
{
|
{
|
||||||
InstancerData *i_data;
|
InstancerData *i_data;
|
||||||
for (auto &it : objects) {
|
for (auto &it : objects_) {
|
||||||
i_data = dynamic_cast<InstancerData *>(it.second.get());
|
i_data = dynamic_cast<InstancerData *>(it.second.get());
|
||||||
if (i_data && i_data->is_base(object)) {
|
if (i_data && i_data->is_base(object)) {
|
||||||
return i_data;
|
return i_data;
|
||||||
@ -251,201 +307,141 @@ InstancerData *BlenderSceneDelegate::instancer_data(Object *object)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
|
void BlenderSceneDelegate::add_update_object(Object *object)
|
||||||
{
|
{
|
||||||
bool is_populated = depsgraph != nullptr;
|
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
|
||||||
|
add_update_instancer(object);
|
||||||
|
}
|
||||||
|
InstancerData *i_data = instancer_data(object);
|
||||||
|
if (i_data) {
|
||||||
|
i_data->update();
|
||||||
|
}
|
||||||
|
|
||||||
depsgraph = deps;
|
pxr::SdfPath id = ObjectData::prim_id(this, object);
|
||||||
context = cont;
|
ObjectData *obj_data = object_data(id);
|
||||||
scene = DEG_get_input_scene(depsgraph);
|
if (obj_data) {
|
||||||
view3d = CTX_wm_view3d(context);
|
obj_data->update();
|
||||||
|
|
||||||
if (!is_populated) {
|
|
||||||
/* Export initial objects */
|
|
||||||
update_collection(false, false);
|
|
||||||
update_world();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (view3d_ && !BKE_object_is_visible_in_viewport(view3d_, object)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
objects_[id] = ObjectData::create(this, object);
|
||||||
|
obj_data = object_data(id);
|
||||||
|
obj_data->update_visibility(view3d_);
|
||||||
|
}
|
||||||
|
|
||||||
/* Working with updates */
|
void BlenderSceneDelegate::add_update_instancer(Object *object)
|
||||||
bool do_update_collection = false;
|
{
|
||||||
bool do_update_visibility = false;
|
pxr::SdfPath id = InstancerData::prim_id(this, object);
|
||||||
bool do_update_world = false;
|
InstancerData *i_data = instancer_data(id, true);
|
||||||
|
if (i_data) {
|
||||||
|
i_data->update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
objects_[id] = InstancerData::create(this, object);
|
||||||
|
i_data = instancer_data(id, true);
|
||||||
|
i_data->update_visibility(view3d_);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int scene_recalc = ((ID *)scene)->recalc;
|
void BlenderSceneDelegate::update_world()
|
||||||
if (scene_recalc) {
|
{
|
||||||
/* Checking scene updates */
|
World *world = scene_->world;
|
||||||
CLOG_INFO(LOG_BSD,
|
if (!world_data_) {
|
||||||
2,
|
if (world) {
|
||||||
"Update: %s [%s]",
|
world_data_ = WorldData::create(this, world, context_);
|
||||||
((ID *)scene)->name,
|
}
|
||||||
std::bitset<32>(scene_recalc).to_string().c_str());
|
}
|
||||||
|
else {
|
||||||
|
if (world) {
|
||||||
|
world_data_->update(world);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
world_data_->remove();
|
||||||
|
world_data_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (scene_recalc & ID_RECALC_BASE_FLAGS) {
|
void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
|
||||||
do_update_visibility = true;
|
{
|
||||||
}
|
if (visibility) {
|
||||||
if (scene_recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) {
|
/* Check and update visibility */
|
||||||
do_update_collection = true;
|
for (auto &obj : objects_) {
|
||||||
}
|
obj.second->update_visibility(view3d_);
|
||||||
if (scene_recalc & ID_RECALC_AUDIO_VOLUME) {
|
|
||||||
if ((scene->world && !world_data) || (!scene->world && world_data)) {
|
|
||||||
do_update_world = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (do_update_collection || do_update_visibility) {
|
|
||||||
update_collection(do_update_collection, do_update_visibility);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking other objects updates */
|
/* Export of new visible objects which were not exported before */
|
||||||
DEGIDIterData data = {0};
|
std::set<pxr::SdfPath> available_objects;
|
||||||
data.graph = depsgraph;
|
pxr::SdfPath id;
|
||||||
data.only_updated = true;
|
|
||||||
ITER_BEGIN (
|
|
||||||
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) {
|
|
||||||
|
|
||||||
CLOG_INFO(
|
DEGObjectIterSettings settings = {0};
|
||||||
LOG_BSD, 2, "Update: %s [%s]", id->name, std::bitset<32>(id->recalc).to_string().c_str());
|
settings.depsgraph = depsgraph_;
|
||||||
|
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
|
||||||
|
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
|
||||||
|
DEGObjectIterData data = {0};
|
||||||
|
data.settings = &settings;
|
||||||
|
data.graph = settings.depsgraph;
|
||||||
|
data.flag = settings.flags;
|
||||||
|
ITER_BEGIN (DEG_iterator_objects_begin,
|
||||||
|
DEG_iterator_objects_next,
|
||||||
|
DEG_iterator_objects_end,
|
||||||
|
&data,
|
||||||
|
Object *,
|
||||||
|
object) {
|
||||||
|
|
||||||
switch (GS(id->name)) {
|
CLOG_INFO(LOG_BSD, 2, "Add %s", ((ID *)object)->name);
|
||||||
case ID_OB: {
|
if (!ObjectData::is_supported(object)) {
|
||||||
Object *object = (Object *)id;
|
continue;
|
||||||
if (!ObjectData::supported(object)) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id = ObjectData::prim_id(this, object);
|
||||||
|
if (remove) {
|
||||||
|
available_objects.insert(id);
|
||||||
|
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
|
||||||
|
available_objects.insert(InstancerData::prim_id(this, object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!object_data(id)) {
|
||||||
add_update_object(object);
|
add_update_object(object);
|
||||||
} break;
|
|
||||||
|
|
||||||
case ID_MA: {
|
|
||||||
MaterialData *mat_data = material_data(MaterialData::prim_id(this, (Material *)id));
|
|
||||||
if (mat_data) {
|
|
||||||
mat_data->update();
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case ID_WO: {
|
|
||||||
if (id->recalc & ID_RECALC_SHADING) {
|
|
||||||
do_update_world = true;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ITER_END;
|
ITER_END;
|
||||||
|
|
||||||
if (do_update_world) {
|
if (remove) {
|
||||||
update_world();
|
/* remove unused objects */
|
||||||
|
for (auto it = objects_.begin(); it != objects_.end(); ++it) {
|
||||||
|
if (available_objects.find(it->first) != available_objects.end()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
it->second->remove();
|
||||||
|
objects_.erase(it);
|
||||||
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
|
it = objects_.begin();
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s", id.GetText());
|
|
||||||
MeshData *m_data = mesh_data(id);
|
|
||||||
return m_data->mesh_topology();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s, %s", id.GetText(), key.GetText());
|
|
||||||
|
|
||||||
ObjectData *obj_data = object_data(id);
|
|
||||||
if (obj_data) {
|
|
||||||
return obj_data->get_data(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialData *mat_data = material_data(id);
|
/* remove unused materials */
|
||||||
if (mat_data) {
|
std::set<pxr::SdfPath> available_materials;
|
||||||
return mat_data->get_data(key);
|
for (auto &obj : objects_) {
|
||||||
|
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
|
||||||
|
if (!m_data) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
pxr::SdfPath mat_id = m_data->material_id();
|
||||||
InstancerData *i_data = instancer_data(id);
|
if (!mat_id.IsEmpty()) {
|
||||||
if (i_data) {
|
available_materials.insert(mat_id);
|
||||||
return i_data->get_data(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pxr::VtValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
|
|
||||||
pxr::SdfPath const &id, pxr::HdInterpolation interpolation)
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s, %d", id.GetText(), interpolation);
|
|
||||||
|
|
||||||
MeshData *m_data = mesh_data(id);
|
|
||||||
if (m_data) {
|
|
||||||
return m_data->primvar_descriptors(interpolation);
|
|
||||||
}
|
}
|
||||||
|
for (auto it = materials_.begin(); it != materials_.end(); ++it) {
|
||||||
InstancerData *i_data = instancer_data(id);
|
if (available_materials.find(it->first) != available_materials.end()) {
|
||||||
if (i_data) {
|
continue;
|
||||||
return i_data->instancer_primvar_descriptors(interpolation);
|
|
||||||
}
|
}
|
||||||
|
it->second->remove();
|
||||||
return pxr::HdPrimvarDescriptorVector();
|
materials_.erase(it);
|
||||||
}
|
it = materials_.begin();
|
||||||
|
|
||||||
pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
|
|
||||||
{
|
|
||||||
return mesh_data(rprim_id)->material_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
|
|
||||||
{
|
|
||||||
MaterialData *mat_data = material_data(id);
|
|
||||||
if (mat_data) {
|
|
||||||
return mat_data->material_resource();
|
|
||||||
}
|
}
|
||||||
return pxr::VtValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s", id.GetText());
|
|
||||||
ObjectData *obj_data = object_data(id);
|
|
||||||
if (obj_data) {
|
|
||||||
return obj_data->transform();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == WorldData::prim_id(this)) {
|
|
||||||
return world_data->transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstancerData *i_data = instancer_data(id);
|
|
||||||
if (i_data) {
|
|
||||||
return i_data->transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pxr::GfMatrix4d();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
|
|
||||||
pxr::TfToken const &key)
|
|
||||||
{
|
|
||||||
LightData *l_data = light_data(id);
|
|
||||||
if (l_data) {
|
|
||||||
return l_data->get_data(key);
|
|
||||||
}
|
|
||||||
if (id == WorldData::prim_id(this)) {
|
|
||||||
return world_data->get_data(key);
|
|
||||||
}
|
|
||||||
return pxr::VtValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSceneDelegate::clear()
|
|
||||||
{
|
|
||||||
for (auto &it : materials) {
|
|
||||||
it.second->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &it : objects) {
|
|
||||||
it.second->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
materials.clear();
|
|
||||||
objects.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -27,7 +27,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
|||||||
public:
|
public:
|
||||||
enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW };
|
enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW };
|
||||||
|
|
||||||
BlenderSceneDelegate(pxr::HdRenderIndex *render_index,
|
BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
|
||||||
pxr::SdfPath const &delegate_id,
|
pxr::SdfPath const &delegate_id,
|
||||||
BlenderSceneDelegate::EngineType engine_type);
|
BlenderSceneDelegate::EngineType engine_type);
|
||||||
~BlenderSceneDelegate() override = default;
|
~BlenderSceneDelegate() override = default;
|
||||||
@ -35,7 +35,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
|||||||
void populate(Depsgraph *depsgraph, bContext *context);
|
void populate(Depsgraph *depsgraph, bContext *context);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// delegate methods
|
/* Delegate methods */
|
||||||
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
|
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
|
||||||
pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override;
|
pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override;
|
||||||
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
||||||
@ -66,15 +66,14 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
|||||||
void update_world();
|
void update_world();
|
||||||
void update_collection(bool remove, bool visibility);
|
void update_collection(bool remove, bool visibility);
|
||||||
|
|
||||||
private:
|
Depsgraph *depsgraph_ = nullptr;
|
||||||
Depsgraph *depsgraph;
|
bContext *context_ = nullptr;
|
||||||
bContext *context;
|
View3D *view3d_ = nullptr;
|
||||||
Scene *scene;
|
Scene *scene_ = nullptr;
|
||||||
DagerD marked this conversation as resolved
Outdated
|
|||||||
View3D *view3d;
|
|
||||||
|
|
||||||
ObjectDataMap objects;
|
ObjectDataMap objects_;
|
||||||
MaterialDataMap materials;
|
MaterialDataMap materials_;
|
||||||
std::unique_ptr<WorldData> world_data;
|
std::unique_ptr<WorldData> world_data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
IdData::IdData(BlenderSceneDelegate *scene_delegate, ID *id)
|
IdData::IdData(BlenderSceneDelegate *scene_delegate, ID *id)
|
||||||
: scene_delegate(scene_delegate), id(id)
|
: scene_delegate_(scene_delegate), id_(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ class IdData {
|
|||||||
template<class T> const T get_data(pxr::TfToken const &key) const;
|
template<class T> const T get_data(pxr::TfToken const &key) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BlenderSceneDelegate *scene_delegate;
|
BlenderSceneDelegate *scene_delegate_;
|
||||||
ID *id;
|
ID *id_;
|
||||||
pxr::SdfPath p_id;
|
pxr::SdfPath p_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> const T IdData::get_data(pxr::TfToken const &key) const
|
template<class T> const T IdData::get_data(pxr::TfToken const &key) const
|
||||||
|
@ -9,7 +9,16 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
bool InstancerData::supported(Object *object)
|
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object)
|
||||||
|
: MeshData(scene_delegate, object), parent_obj_(object)
|
||||||
|
{
|
||||||
|
id_ = nullptr;
|
||||||
|
p_id_ = prim_id(scene_delegate, object);
|
||||||
|
instancer_id = p_id_.AppendElementString("Instancer");
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s, instancer_id=%s", ((ID *)parent_obj_)->name, instancer_id.GetText());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstancerData::is_supported(Object *object)
|
||||||
{
|
{
|
||||||
switch (object->type) {
|
switch (object->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
@ -43,23 +52,75 @@ pxr::SdfPath InstancerData::prim_id(BlenderSceneDelegate *scene_delegate, Object
|
|||||||
return scene_delegate->GetDelegateID().AppendElementString(str);
|
return scene_delegate->GetDelegateID().AppendElementString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object)
|
|
||||||
: MeshData(scene_delegate, object), parent_obj(object)
|
|
||||||
{
|
|
||||||
id = nullptr;
|
|
||||||
p_id = prim_id(scene_delegate, object);
|
|
||||||
instancer_id = p_id.AppendElementString("Instancer");
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s, instancer_id=%s", ((ID *)parent_obj)->name, instancer_id.GetText());
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstancerData::init()
|
void InstancerData::init()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj)->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj_)->name);
|
||||||
|
|
||||||
set_instances();
|
set_instances();
|
||||||
MeshData::init();
|
MeshData::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstancerData::insert()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj_)->name);
|
||||||
|
MeshData::insert();
|
||||||
|
|
||||||
|
if (face_vertex_counts_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, instancer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstancerData::remove()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj_)->name);
|
||||||
|
|
||||||
|
if (!scene_delegate_->GetRenderIndex().HasInstancer(instancer_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scene_delegate_->GetRenderIndex().RemoveInstancer(instancer_id);
|
||||||
|
|
||||||
|
MeshData::remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstancerData::update()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj_)->name);
|
||||||
|
|
||||||
|
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
||||||
|
unsigned int recalc = ((ID *)parent_obj_)->recalc;
|
||||||
|
|
||||||
|
Object *object = (Object *)id_;
|
||||||
|
if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||||
|
init();
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||||
|
p_id_, pxr::HdChangeTracker::AllDirty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((recalc & ID_RECALC_GEOMETRY) || (((ID *)parent_obj_->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||||
|
init();
|
||||||
|
bits |= pxr::HdChangeTracker::AllDirty;
|
||||||
|
}
|
||||||
|
else if (recalc & ID_RECALC_TRANSFORM || id_->recalc & ID_RECALC_TRANSFORM) {
|
||||||
|
set_instances();
|
||||||
|
bits |= pxr::HdChangeTracker::DirtyTransform;
|
||||||
|
}
|
||||||
|
if (bits != pxr::HdChangeTracker::Clean) {
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(instancer_id, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 3, "%s [%s]", id_->name, key.GetText());
|
||||||
|
|
||||||
|
if (key == pxr::HdInstancerTokens->instanceTransform) {
|
||||||
|
return pxr::VtValue(transforms_);
|
||||||
|
}
|
||||||
|
return MeshData::get_data(key);
|
||||||
|
}
|
||||||
|
|
||||||
pxr::GfMatrix4d InstancerData::transform()
|
pxr::GfMatrix4d InstancerData::transform()
|
||||||
{
|
{
|
||||||
return pxr::GfMatrix4d(1.0);
|
return pxr::GfMatrix4d(1.0);
|
||||||
@ -72,25 +133,15 @@ bool InstancerData::update_visibility(View3D *view3d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool prev_visible = visible;
|
bool prev_visible = visible;
|
||||||
visible = BKE_object_is_visible_in_viewport(view3d, parent_obj);
|
visible = BKE_object_is_visible_in_viewport(view3d, parent_obj_);
|
||||||
bool ret = visible != prev_visible;
|
bool ret = visible != prev_visible;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||||
p_id, pxr::HdChangeTracker::DirtyVisibility);
|
p_id_, pxr::HdChangeTracker::DirtyVisibility);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s [%s]", id->name, key.GetText());
|
|
||||||
|
|
||||||
if (key == pxr::HdInstancerTokens->instanceTransform) {
|
|
||||||
return pxr::VtValue(transforms);
|
|
||||||
}
|
|
||||||
return MeshData::get_data(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
|
pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
|
||||||
pxr::HdInterpolation interpolation)
|
pxr::HdInterpolation interpolation)
|
||||||
{
|
{
|
||||||
@ -104,7 +155,7 @@ pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
|
|||||||
|
|
||||||
pxr::VtIntArray InstancerData::instance_indices()
|
pxr::VtIntArray InstancerData::instance_indices()
|
||||||
{
|
{
|
||||||
pxr::VtIntArray ret(transforms.size());
|
pxr::VtIntArray ret(transforms_.size());
|
||||||
for (size_t i = 0; i < ret.size(); ++i) {
|
for (size_t i = 0; i < ret.size(); ++i) {
|
||||||
ret[i] = i;
|
ret[i] = i;
|
||||||
}
|
}
|
||||||
@ -113,82 +164,32 @@ pxr::VtIntArray InstancerData::instance_indices()
|
|||||||
|
|
||||||
bool InstancerData::is_base(Object *object) const
|
bool InstancerData::is_base(Object *object) const
|
||||||
{
|
{
|
||||||
return (ID *)object == id;
|
return (ID *)object == id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstancerData::set_instances()
|
bool InstancerData::set_instances()
|
||||||
{
|
{
|
||||||
ID *prev_id = id;
|
ID *prev_id = id_;
|
||||||
id = nullptr;
|
id_ = nullptr;
|
||||||
transforms.clear();
|
transforms_.clear();
|
||||||
ListBase *lb = object_duplilist(scene_delegate->depsgraph, scene_delegate->scene, parent_obj);
|
ListBase *lb = object_duplilist(
|
||||||
|
scene_delegate_->depsgraph_, scene_delegate_->scene_, parent_obj_);
|
||||||
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
|
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
|
||||||
if (!id) {
|
if (!id_) {
|
||||||
/* TODO: We create instances only for object in first dupli.
|
/* TODO: We create instances only for object in first dupli.
|
||||||
Instances should be created for all objects */
|
Instances should be created for all objects */
|
||||||
id = (ID *)dupli->ob;
|
id_ = (ID *)dupli->ob;
|
||||||
}
|
}
|
||||||
if (id != (ID *)dupli->ob) {
|
if (id_ != (ID *)dupli->ob) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
transforms.push_back(gf_matrix_from_transform(dupli->mat));
|
transforms_.push_back(gf_matrix_from_transform(dupli->mat));
|
||||||
CLOG_INFO(
|
CLOG_INFO(
|
||||||
LOG_BSD, 2, "Instance %s (%s) %d", id->name, ((ID *)dupli->ob)->name, dupli->random_id);
|
LOG_BSD, 2, "Instance %s (%s) %d", id_->name, ((ID *)dupli->ob)->name, dupli->random_id);
|
||||||
}
|
}
|
||||||
free_object_duplilist(lb);
|
free_object_duplilist(lb);
|
||||||
|
|
||||||
return id != prev_id;
|
return id_ != prev_id;
|
||||||
}
|
|
||||||
|
|
||||||
void InstancerData::insert()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj)->name);
|
|
||||||
MeshData::insert();
|
|
||||||
|
|
||||||
if (face_vertex_counts.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scene_delegate->GetRenderIndex().InsertInstancer(scene_delegate, instancer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstancerData::remove()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj)->name);
|
|
||||||
|
|
||||||
if (!scene_delegate->GetRenderIndex().HasInstancer(instancer_id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scene_delegate->GetRenderIndex().RemoveInstancer(instancer_id);
|
|
||||||
|
|
||||||
MeshData::remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstancerData::update()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", ((ID *)parent_obj)->name);
|
|
||||||
|
|
||||||
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
|
||||||
unsigned int recalc = ((ID *)parent_obj)->recalc;
|
|
||||||
|
|
||||||
Object *object = (Object *)id;
|
|
||||||
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
|
||||||
init();
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
|
||||||
p_id, pxr::HdChangeTracker::AllDirty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((recalc & ID_RECALC_GEOMETRY) || (((ID *)parent_obj->data)->recalc & ID_RECALC_GEOMETRY)) {
|
|
||||||
init();
|
|
||||||
bits |= pxr::HdChangeTracker::AllDirty;
|
|
||||||
}
|
|
||||||
else if (recalc & ID_RECALC_TRANSFORM || id->recalc & ID_RECALC_TRANSFORM) {
|
|
||||||
set_instances();
|
|
||||||
bits |= pxr::HdChangeTracker::DirtyTransform;
|
|
||||||
}
|
|
||||||
if (bits != pxr::HdChangeTracker::Clean) {
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(instancer_id, bits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -11,32 +11,33 @@ namespace blender::render::hydra {
|
|||||||
|
|
||||||
class InstancerData : public MeshData {
|
class InstancerData : public MeshData {
|
||||||
public:
|
public:
|
||||||
static bool supported(Object *object);
|
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
|
static bool is_supported(Object *object);
|
||||||
static std::unique_ptr<InstancerData> create(BlenderSceneDelegate *scene_delegate,
|
static std::unique_ptr<InstancerData> create(BlenderSceneDelegate *scene_delegate,
|
||||||
Object *object);
|
Object *object);
|
||||||
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
|
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
|
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
void insert() override;
|
void insert() override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
||||||
pxr::GfMatrix4d transform() override;
|
pxr::GfMatrix4d transform() override;
|
||||||
bool update_visibility(View3D *view3d) override;
|
bool update_visibility(View3D *view3d) override;
|
||||||
|
|
||||||
pxr::HdPrimvarDescriptorVector instancer_primvar_descriptors(pxr::HdInterpolation interpolation);
|
pxr::HdPrimvarDescriptorVector instancer_primvar_descriptors(pxr::HdInterpolation interpolation);
|
||||||
pxr::VtIntArray instance_indices();
|
pxr::VtIntArray instance_indices();
|
||||||
|
|
||||||
bool is_base(Object *object) const;
|
bool is_base(Object *object) const;
|
||||||
|
|
||||||
pxr::SdfPath instancer_id;
|
pxr::SdfPath instancer_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Object *parent_obj;
|
|
||||||
pxr::VtMatrix4dArray transforms;
|
|
||||||
|
|
||||||
bool set_instances();
|
bool set_instances();
|
||||||
|
|
||||||
|
Object *parent_obj_;
|
||||||
|
pxr::VtMatrix4dArray transforms_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -17,72 +17,138 @@ namespace blender::render::hydra {
|
|||||||
LightData::LightData(BlenderSceneDelegate *scene_delegate, Object *object)
|
LightData::LightData(BlenderSceneDelegate *scene_delegate, Object *object)
|
||||||
: ObjectData(scene_delegate, object)
|
: ObjectData(scene_delegate, object)
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s id=%s", id->name, p_id.GetText());
|
CLOG_INFO(LOG_BSD, 2, "%s id=%s", id_->name, p_id_.GetText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightData::init()
|
void LightData::init()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
|
||||||
Light *light = (Light *)((Object *)id)->data;
|
Light *light = (Light *)((Object *)id_)->data;
|
||||||
data.clear();
|
data_.clear();
|
||||||
|
|
||||||
float intensity = light->energy;
|
float intensity = light->energy;
|
||||||
if (scene_delegate->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) {
|
if (scene_delegate_->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) {
|
||||||
intensity *= 0.001;
|
intensity *= 0.001;
|
||||||
}
|
}
|
||||||
data[pxr::HdLightTokens->intensity] = intensity;
|
data_[pxr::HdLightTokens->intensity] = intensity;
|
||||||
|
|
||||||
data[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
|
data_[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
|
||||||
|
|
||||||
switch (light->type) {
|
switch (light->type) {
|
||||||
case LA_LOCAL:
|
case LA_LOCAL:
|
||||||
data[pxr::HdLightTokens->radius] = light->area_size / 2;
|
data_[pxr::HdLightTokens->radius] = light->area_size / 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_SUN:
|
case LA_SUN:
|
||||||
data[pxr::HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI;
|
data_[pxr::HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_SPOT:
|
case LA_SPOT:
|
||||||
data[pxr::HdLightTokens->shapingConeAngle] = light->spotsize / 2;
|
data_[pxr::HdLightTokens->shapingConeAngle] = light->spotsize / 2;
|
||||||
data[pxr::HdLightTokens->shapingConeSoftness] = light->spotblend;
|
data_[pxr::HdLightTokens->shapingConeSoftness] = light->spotblend;
|
||||||
data[pxr::UsdLuxTokens->treatAsPoint] = true;
|
data_[pxr::UsdLuxTokens->treatAsPoint] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_AREA:
|
case LA_AREA:
|
||||||
switch (light->area_shape) {
|
switch (light->area_shape) {
|
||||||
case LA_AREA_SQUARE:
|
case LA_AREA_SQUARE:
|
||||||
data[pxr::HdLightTokens->width] = light->area_size;
|
data_[pxr::HdLightTokens->width] = light->area_size;
|
||||||
data[pxr::HdLightTokens->height] = light->area_size;
|
data_[pxr::HdLightTokens->height] = light->area_size;
|
||||||
break;
|
break;
|
||||||
case LA_AREA_RECT:
|
case LA_AREA_RECT:
|
||||||
data[pxr::HdLightTokens->width] = light->area_size;
|
data_[pxr::HdLightTokens->width] = light->area_size;
|
||||||
data[pxr::HdLightTokens->height] = light->area_sizey;
|
data_[pxr::HdLightTokens->height] = light->area_sizey;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_AREA_DISK:
|
case LA_AREA_DISK:
|
||||||
data[pxr::HdLightTokens->radius] = light->area_size / 2;
|
data_[pxr::HdLightTokens->radius] = light->area_size / 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_AREA_ELLIPSE:
|
case LA_AREA_ELLIPSE:
|
||||||
data[pxr::HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4;
|
data_[pxr::HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
data[pxr::HdLightTokens->normalize] = true;
|
data_[pxr::HdLightTokens->normalize] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_type = prim_type(light);
|
p_type_ = prim_type(light);
|
||||||
|
|
||||||
/* TODO: temporary value, it should be delivered through Python UI */
|
/* TODO: temporary value, it should be delivered through Python UI */
|
||||||
data[pxr::HdLightTokens->exposure] = 1.0f;
|
data_[pxr::HdLightTokens->exposure] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::insert()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().InsertSprim(p_type_, scene_delegate_, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::remove()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().RemoveSprim(p_type_, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::update()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
|
||||||
|
Light *light = (Light *)((Object *)id_)->data;
|
||||||
|
if (prim_type(light) != p_type_) {
|
||||||
|
remove();
|
||||||
|
init();
|
||||||
|
insert();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
|
||||||
|
if (id_->recalc & ID_RECALC_GEOMETRY) {
|
||||||
|
init();
|
||||||
|
bits = pxr::HdLight::AllDirty;
|
||||||
|
}
|
||||||
|
else if (id_->recalc & ID_RECALC_TRANSFORM) {
|
||||||
|
bits = pxr::HdLight::DirtyTransform;
|
||||||
|
}
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
|
||||||
|
{
|
||||||
|
pxr::VtValue ret;
|
||||||
|
auto it = data_.find(key);
|
||||||
|
if (it != data_.end()) {
|
||||||
|
ret = it->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string n = key.GetString();
|
||||||
|
if (boost::algorithm::contains(n, "object:visibility:")) {
|
||||||
|
if (boost::algorithm::ends_with(n, "camera") || boost::algorithm::ends_with(n, "shadow")) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LightData::update_visibility(View3D *view3d)
|
||||||
|
{
|
||||||
|
bool ret = ObjectData::update_visibility(view3d);
|
||||||
|
if (ret) {
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
|
||||||
|
pxr::HdLight::DirtyParams);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::TfToken LightData::prim_type(Light *light)
|
pxr::TfToken LightData::prim_type(Light *light)
|
||||||
@ -121,70 +187,4 @@ pxr::TfToken LightData::prim_type(Light *light)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
|
|
||||||
{
|
|
||||||
pxr::VtValue ret;
|
|
||||||
auto it = data.find(key);
|
|
||||||
if (it != data.end()) {
|
|
||||||
ret = it->second;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::string n = key.GetString();
|
|
||||||
if (boost::algorithm::contains(n, "object:visibility:")) {
|
|
||||||
if (boost::algorithm::ends_with(n, "camera") || boost::algorithm::ends_with(n, "shadow")) {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LightData::update_visibility(View3D *view3d)
|
|
||||||
{
|
|
||||||
bool ret = ObjectData::update_visibility(view3d);
|
|
||||||
if (ret) {
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id,
|
|
||||||
pxr::HdLight::DirtyParams);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightData::insert()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().InsertSprim(p_type, scene_delegate, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightData::remove()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().RemoveSprim(p_type, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightData::update()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
|
|
||||||
Light *light = (Light *)((Object *)id)->data;
|
|
||||||
if (prim_type(light) != p_type) {
|
|
||||||
remove();
|
|
||||||
init();
|
|
||||||
insert();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
|
|
||||||
if (id->recalc & ID_RECALC_GEOMETRY) {
|
|
||||||
init();
|
|
||||||
bits = pxr::HdLight::AllDirty;
|
|
||||||
}
|
|
||||||
else if (id->recalc & ID_RECALC_TRANSFORM) {
|
|
||||||
bits = pxr::HdLight::DirtyTransform;
|
|
||||||
}
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -21,13 +21,15 @@ class LightData : public ObjectData {
|
|||||||
void insert() override;
|
void insert() override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
||||||
bool update_visibility(View3D *view3d) override;
|
bool update_visibility(View3D *view3d) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<pxr::TfToken, pxr::VtValue> data;
|
|
||||||
pxr::TfToken p_type;
|
|
||||||
pxr::TfToken prim_type(Light *light);
|
pxr::TfToken prim_type(Light *light);
|
||||||
|
|
||||||
|
std::map<pxr::TfToken, pxr::VtValue> data_;
|
||||||
|
pxr::TfToken p_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -20,6 +20,13 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *material)
|
||||||
|
: IdData(scene_delegate, (ID *)material)
|
||||||
|
{
|
||||||
|
p_id_ = prim_id(scene_delegate, material);
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id_->name, p_id_.GetText());
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate,
|
std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate,
|
||||||
Material *material)
|
Material *material)
|
||||||
{
|
{
|
||||||
@ -38,18 +45,11 @@ pxr::SdfPath MaterialData::prim_id(BlenderSceneDelegate *scene_delegate, Materia
|
|||||||
return scene_delegate->GetDelegateID().AppendElementString(str);
|
return scene_delegate->GetDelegateID().AppendElementString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *material)
|
|
||||||
: IdData(scene_delegate, (ID *)material)
|
|
||||||
{
|
|
||||||
p_id = prim_id(scene_delegate, material);
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id->name, p_id.GetText());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::init()
|
void MaterialData::init()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
|
||||||
material_network_map = pxr::VtValue();
|
material_network_map_ = pxr::VtValue();
|
||||||
|
|
||||||
/* Call of python function hydra.export_mtlx() */
|
/* Call of python function hydra.export_mtlx() */
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ void MaterialData::init()
|
|||||||
func = PyDict_GetItemString(dict, "export_mtlx");
|
func = PyDict_GetItemString(dict, "export_mtlx");
|
||||||
|
|
||||||
PointerRNA materialptr;
|
PointerRNA materialptr;
|
||||||
RNA_pointer_create(NULL, &RNA_Material, id, &materialptr);
|
RNA_pointer_create(NULL, &RNA_Material, id_, &materialptr);
|
||||||
PyObject *material = pyrna_struct_CreatePyObject(&materialptr);
|
PyObject *material = pyrna_struct_CreatePyObject(&materialptr);
|
||||||
|
|
||||||
result = PyObject_CallFunction(func, "O", material);
|
result = PyObject_CallFunction(func, "O", material);
|
||||||
@ -76,67 +76,68 @@ void MaterialData::init()
|
|||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CLOG_ERROR(LOG_BSD, "Export error for %s", id->name);
|
CLOG_ERROR(LOG_BSD, "Export error for %s", id_->name);
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
}
|
}
|
||||||
Py_DECREF(module);
|
Py_DECREF(module);
|
||||||
|
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
|
||||||
mtlx_path = pxr::SdfAssetPath(path, path);
|
mtlx_path_ = pxr::SdfAssetPath(path, path);
|
||||||
CLOG_INFO(LOG_BSD, 2, "Export: %s, mtlx=%s", id->name, mtlx_path.GetResolvedPath().c_str());
|
CLOG_INFO(LOG_BSD, 2, "Export: %s, mtlx=%s", id_->name, mtlx_path_.GetResolvedPath().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::insert()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().InsertSprim(
|
||||||
|
pxr::HdPrimTypeTokens->material, scene_delegate_, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::remove()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::update()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
init();
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
|
||||||
|
pxr::HdMaterial::AllDirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
|
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
|
||||||
{
|
{
|
||||||
pxr::VtValue ret;
|
pxr::VtValue ret;
|
||||||
if (key.GetString() == "MaterialXFilename") {
|
if (key.GetString() == "MaterialXFilename") {
|
||||||
if (!mtlx_path.GetResolvedPath().empty()) {
|
if (!mtlx_path_.GetResolvedPath().empty()) {
|
||||||
ret = mtlx_path;
|
ret = mtlx_path_;
|
||||||
}
|
}
|
||||||
CLOG_INFO(LOG_BSD, 3, "%s", key.GetText());
|
CLOG_INFO(LOG_BSD, 3, "%s", key.GetText());
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue MaterialData::material_resource()
|
pxr::VtValue MaterialData::get_material_resource()
|
||||||
{
|
{
|
||||||
if (material_network_map.IsEmpty()) {
|
if (material_network_map_.IsEmpty()) {
|
||||||
const std::string &path = mtlx_path.GetResolvedPath();
|
const std::string &path = mtlx_path_.GetResolvedPath();
|
||||||
if (!path.empty()) {
|
if (!path.empty()) {
|
||||||
pxr::HdRenderDelegate *render_delegate =
|
pxr::HdRenderDelegate *render_delegate =
|
||||||
scene_delegate->GetRenderIndex().GetRenderDelegate();
|
scene_delegate_->GetRenderIndex().GetRenderDelegate();
|
||||||
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
|
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
|
||||||
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
|
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
|
||||||
|
|
||||||
pxr::HdMaterialNetworkMap network_map;
|
pxr::HdMaterialNetworkMap network_map;
|
||||||
HdMtlxConvertToMaterialNetworkMap(path, shader_source_types, render_contexts, &network_map);
|
hdmtlx_convert_to_materialnetworkmap(
|
||||||
|
path, shader_source_types, render_contexts, &network_map);
|
||||||
|
|
||||||
material_network_map = network_map;
|
material_network_map_ = network_map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return material_network_map;
|
return material_network_map_;
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::insert()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().InsertSprim(
|
|
||||||
pxr::HdPrimTypeTokens->material, scene_delegate, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::remove()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::update()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
init();
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id,
|
|
||||||
pxr::HdMaterial::AllDirty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -19,24 +19,23 @@ class MaterialData : IdData {
|
|||||||
friend MeshData;
|
friend MeshData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
MaterialData(BlenderSceneDelegate *scene_delegate, Material *material);
|
||||||
|
|
||||||
static std::unique_ptr<MaterialData> create(BlenderSceneDelegate *scene_delegate,
|
static std::unique_ptr<MaterialData> create(BlenderSceneDelegate *scene_delegate,
|
||||||
Material *material);
|
Material *material);
|
||||||
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Material *material);
|
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Material *material);
|
||||||
|
|
||||||
MaterialData(BlenderSceneDelegate *scene_delegate, Material *material);
|
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
void insert() override;
|
void insert() override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
|
||||||
|
|
||||||
pxr::VtValue material_resource();
|
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
||||||
void export_mtlx();
|
pxr::VtValue get_material_resource();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pxr::SdfAssetPath mtlx_path;
|
pxr::SdfAssetPath mtlx_path_;
|
||||||
pxr::VtValue material_network_map;
|
pxr::VtValue material_network_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using MaterialDataMap =
|
using MaterialDataMap =
|
||||||
|
@ -16,25 +16,102 @@
|
|||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object)
|
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object)
|
||||||
: ObjectData(scene_delegate, object), mat_data(nullptr)
|
: ObjectData(scene_delegate, object), mat_data_(nullptr)
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id->name, p_id.GetText());
|
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id_->name, p_id_.GetText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::init()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
|
||||||
|
Object *object = (Object *)id_;
|
||||||
|
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
|
||||||
|
BLI_listbase_is_empty(&object->modifiers)) {
|
||||||
|
write_mesh((Mesh *)object->data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
||||||
|
if (mesh) {
|
||||||
|
write_mesh(mesh);
|
||||||
|
}
|
||||||
|
BKE_object_to_mesh_clear(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_material();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::insert()
|
||||||
|
{
|
||||||
|
if (face_vertex_counts_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().InsertRprim(
|
||||||
|
pxr::HdPrimTypeTokens->mesh, scene_delegate_, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::remove()
|
||||||
|
{
|
||||||
|
if (!scene_delegate_->GetRenderIndex().HasRprim(p_id_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().RemoveRprim(p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::update()
|
||||||
|
{
|
||||||
|
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
||||||
|
Object *object = (Object *)id_;
|
||||||
|
if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||||
|
init();
|
||||||
|
bits = pxr::HdChangeTracker::AllDirty;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (id_->recalc & ID_RECALC_SHADING) {
|
||||||
|
write_material();
|
||||||
|
bits |= pxr::HdChangeTracker::DirtyMaterialId;
|
||||||
|
}
|
||||||
|
if (id_->recalc & ID_RECALC_TRANSFORM) {
|
||||||
|
bits |= pxr::HdChangeTracker::DirtyTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits == pxr::HdChangeTracker::Clean) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scene_delegate_->GetRenderIndex().HasRprim(p_id_)) {
|
||||||
|
insert();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (face_vertex_counts_.empty()) {
|
||||||
|
/* Remove prim without faces */
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(p_id_, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const
|
pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const
|
||||||
{
|
{
|
||||||
pxr::VtValue ret;
|
pxr::VtValue ret;
|
||||||
if (key == pxr::HdTokens->points) {
|
if (key == pxr::HdTokens->points) {
|
||||||
ret = vertices;
|
ret = vertices_;
|
||||||
}
|
}
|
||||||
else if (key == pxr::HdTokens->normals) {
|
else if (key == pxr::HdTokens->normals) {
|
||||||
ret = normals;
|
ret = normals_;
|
||||||
}
|
}
|
||||||
else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) {
|
else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) {
|
||||||
ret = uvs;
|
ret = uvs_;
|
||||||
}
|
}
|
||||||
else if (key == pxr::HdInstancerTokens->instanceTransform) {
|
else if (key == pxr::HdInstancerTokens->instanceTransform) {
|
||||||
ret = instances;
|
ret = instances_;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -43,8 +120,8 @@ bool MeshData::update_visibility(View3D *view3d)
|
|||||||
{
|
{
|
||||||
bool ret = ObjectData::update_visibility(view3d);
|
bool ret = ObjectData::update_visibility(view3d);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||||
p_id, pxr::HdChangeTracker::DirtyVisibility);
|
p_id_, pxr::HdChangeTracker::DirtyVisibility);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -53,24 +130,24 @@ pxr::HdMeshTopology MeshData::mesh_topology()
|
|||||||
{
|
{
|
||||||
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
|
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
|
||||||
pxr::HdTokens->rightHanded,
|
pxr::HdTokens->rightHanded,
|
||||||
face_vertex_counts,
|
face_vertex_counts_,
|
||||||
face_vertex_indices);
|
face_vertex_indices_);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolation interpolation)
|
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolation interpolation)
|
||||||
{
|
{
|
||||||
pxr::HdPrimvarDescriptorVector primvars;
|
pxr::HdPrimvarDescriptorVector primvars;
|
||||||
if (interpolation == pxr::HdInterpolationVertex) {
|
if (interpolation == pxr::HdInterpolationVertex) {
|
||||||
if (!vertices.empty()) {
|
if (!vertices_.empty()) {
|
||||||
primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point);
|
primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (interpolation == pxr::HdInterpolationFaceVarying) {
|
else if (interpolation == pxr::HdInterpolationFaceVarying) {
|
||||||
if (!normals.empty()) {
|
if (!normals_.empty()) {
|
||||||
primvars.emplace_back(
|
primvars.emplace_back(
|
||||||
pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
|
pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
|
||||||
}
|
}
|
||||||
if (!uvs.empty()) {
|
if (!uvs_.empty()) {
|
||||||
primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate,
|
primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate,
|
||||||
interpolation,
|
interpolation,
|
||||||
pxr::HdPrimvarRoleTokens->textureCoordinate);
|
pxr::HdPrimvarRoleTokens->textureCoordinate);
|
||||||
@ -81,19 +158,19 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolatio
|
|||||||
|
|
||||||
pxr::SdfPath MeshData::material_id()
|
pxr::SdfPath MeshData::material_id()
|
||||||
{
|
{
|
||||||
if (!mat_data) {
|
if (!mat_data_) {
|
||||||
return pxr::SdfPath();
|
return pxr::SdfPath();
|
||||||
}
|
}
|
||||||
return mat_data->p_id;
|
return mat_data_->p_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::set_mesh(Mesh *mesh)
|
void MeshData::write_mesh(Mesh *mesh)
|
||||||
{
|
{
|
||||||
face_vertex_counts.clear();
|
face_vertex_counts_.clear();
|
||||||
face_vertex_indices.clear();
|
face_vertex_indices_.clear();
|
||||||
vertices.clear();
|
vertices_.clear();
|
||||||
normals.clear();
|
normals_.clear();
|
||||||
uvs.clear();
|
uvs_.clear();
|
||||||
|
|
||||||
BKE_mesh_calc_normals_split(mesh);
|
BKE_mesh_calc_normals_split(mesh);
|
||||||
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
||||||
@ -104,141 +181,74 @@ void MeshData::set_mesh(Mesh *mesh)
|
|||||||
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||||
|
|
||||||
/* face_vertex_counts */
|
/* face_vertex_counts */
|
||||||
face_vertex_counts = pxr::VtIntArray(tris_len, 3);
|
face_vertex_counts_ = pxr::VtIntArray(tris_len, 3);
|
||||||
|
|
||||||
/* face_vertex_indices */
|
/* face_vertex_indices */
|
||||||
blender::Span<int> corner_verts = mesh->corner_verts();
|
blender::Span<int> corner_verts = mesh->corner_verts();
|
||||||
face_vertex_indices.reserve(loopTris.size() * 3);
|
face_vertex_indices_.reserve(loopTris.size() * 3);
|
||||||
for (MLoopTri lt : loopTris) {
|
for (MLoopTri lt : loopTris) {
|
||||||
face_vertex_indices.push_back(corner_verts[lt.tri[0]]);
|
face_vertex_indices_.push_back(corner_verts[lt.tri[0]]);
|
||||||
face_vertex_indices.push_back(corner_verts[lt.tri[1]]);
|
face_vertex_indices_.push_back(corner_verts[lt.tri[1]]);
|
||||||
face_vertex_indices.push_back(corner_verts[lt.tri[2]]);
|
face_vertex_indices_.push_back(corner_verts[lt.tri[2]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vertices */
|
/* vertices */
|
||||||
vertices.reserve(mesh->totvert);
|
vertices_.reserve(mesh->totvert);
|
||||||
blender::Span<blender::float3> verts = mesh->vert_positions();
|
blender::Span<blender::float3> verts = mesh->vert_positions();
|
||||||
for (blender::float3 v : verts) {
|
for (blender::float3 v : verts) {
|
||||||
vertices.push_back(pxr::GfVec3f(v.x, v.y, v.z));
|
vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* normals */
|
write_normals(mesh);
|
||||||
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
write_uv_maps(mesh);
|
||||||
if (lnors) {
|
|
||||||
normals.reserve(loopTris.size() * 3);
|
|
||||||
for (MLoopTri lt : loopTris) {
|
|
||||||
normals.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
|
|
||||||
normals.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
|
|
||||||
normals.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* uvs*/
|
|
||||||
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
|
|
||||||
if (luvs) {
|
|
||||||
uvs.reserve(loopTris.size() * 3);
|
|
||||||
for (MLoopTri lt : loopTris) {
|
|
||||||
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
|
|
||||||
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
|
|
||||||
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::set_material()
|
void MeshData::write_material()
|
||||||
{
|
{
|
||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id_;
|
||||||
Material *mat = nullptr;
|
Material *mat = nullptr;
|
||||||
if (BKE_object_material_count_eval(object) > 0) {
|
if (BKE_object_material_count_eval(object) > 0) {
|
||||||
mat = BKE_object_material_get_eval(object, object->actcol);
|
mat = BKE_object_material_get_eval(object, object->actcol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mat) {
|
if (!mat) {
|
||||||
mat_data = nullptr;
|
mat_data_ = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pxr::SdfPath id = MaterialData::prim_id(scene_delegate, mat);
|
pxr::SdfPath id = MaterialData::prim_id(scene_delegate_, mat);
|
||||||
mat_data = scene_delegate->material_data(id);
|
mat_data_ = scene_delegate_->material_data(id);
|
||||||
if (!mat_data) {
|
if (!mat_data_) {
|
||||||
scene_delegate->materials[id] = MaterialData::create(scene_delegate, mat);
|
scene_delegate_->materials_[id] = MaterialData::create(scene_delegate_, mat);
|
||||||
mat_data = scene_delegate->material_data(id);
|
mat_data_ = scene_delegate_->material_data(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::init()
|
void MeshData::write_uv_maps(Mesh *mesh)
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||||
|
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
|
||||||
Object *object = (Object *)id;
|
if (luvs) {
|
||||||
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
|
uvs_.reserve(loopTris.size() * 3);
|
||||||
BLI_listbase_is_empty(&object->modifiers)) {
|
for (MLoopTri lt : loopTris) {
|
||||||
set_mesh((Mesh *)object->data);
|
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
|
||||||
|
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
|
||||||
|
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
|
||||||
if (mesh) {
|
|
||||||
set_mesh(mesh);
|
|
||||||
}
|
}
|
||||||
BKE_object_to_mesh_clear(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_material();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::insert()
|
void MeshData::write_normals(Mesh *mesh)
|
||||||
{
|
{
|
||||||
if (face_vertex_counts.empty()) {
|
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||||
return;
|
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
||||||
}
|
if (lnors) {
|
||||||
|
normals_.reserve(loopTris.size() * 3);
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
for (MLoopTri lt : loopTris) {
|
||||||
scene_delegate->GetRenderIndex().InsertRprim(pxr::HdPrimTypeTokens->mesh, scene_delegate, p_id);
|
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
|
||||||
}
|
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
|
||||||
|
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
|
||||||
void MeshData::remove()
|
|
||||||
{
|
|
||||||
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().RemoveRprim(p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshData::update()
|
|
||||||
{
|
|
||||||
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
|
||||||
Object *object = (Object *)id;
|
|
||||||
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
|
||||||
init();
|
|
||||||
bits = pxr::HdChangeTracker::AllDirty;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (id->recalc & ID_RECALC_SHADING) {
|
|
||||||
set_material();
|
|
||||||
bits |= pxr::HdChangeTracker::DirtyMaterialId;
|
|
||||||
}
|
|
||||||
if (id->recalc & ID_RECALC_TRANSFORM) {
|
|
||||||
bits |= pxr::HdChangeTracker::DirtyTransform;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bits == pxr::HdChangeTracker::Clean) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
|
|
||||||
insert();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (face_vertex_counts.empty()) {
|
|
||||||
/* Remove prim without faces */
|
|
||||||
remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(p_id, bits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -21,6 +21,7 @@ class MeshData : public ObjectData {
|
|||||||
void insert() override;
|
void insert() override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
||||||
bool update_visibility(View3D *view3d) override;
|
bool update_visibility(View3D *view3d) override;
|
||||||
|
|
||||||
@ -29,18 +30,19 @@ class MeshData : public ObjectData {
|
|||||||
pxr::SdfPath material_id();
|
pxr::SdfPath material_id();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_mesh(Mesh *mesh);
|
void write_mesh(Mesh *mesh);
|
||||||
void set_material();
|
void write_material();
|
||||||
|
void write_uv_maps(Mesh *mesh);
|
||||||
|
void write_normals(Mesh *mesh);
|
||||||
|
|
||||||
pxr::VtIntArray face_vertex_counts;
|
pxr::VtIntArray face_vertex_counts_;
|
||||||
pxr::VtIntArray face_vertex_indices;
|
pxr::VtIntArray face_vertex_indices_;
|
||||||
pxr::VtVec3fArray vertices;
|
pxr::VtVec3fArray vertices_;
|
||||||
pxr::VtVec3fArray normals;
|
pxr::VtVec2fArray uvs_;
|
||||||
pxr::VtVec2fArray uvs;
|
pxr::VtVec3fArray normals_;
|
||||||
|
pxr::VtMatrix4dArray instances_;
|
||||||
|
|
||||||
pxr::VtMatrix4dArray instances;
|
MaterialData *mat_data_;
|
||||||
|
|
||||||
MaterialData *mat_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
namespace mx = MaterialX;
|
namespace mx = MaterialX;
|
||||||
|
|
||||||
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlx_path,
|
void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
|
||||||
pxr::TfTokenVector const &shader_source_types,
|
pxr::TfTokenVector const &shader_source_types,
|
||||||
pxr::TfTokenVector const &render_contexts,
|
pxr::TfTokenVector const &render_contexts,
|
||||||
pxr::HdMaterialNetworkMap *out)
|
pxr::HdMaterialNetworkMap *out)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
struct pxr::HdMaterialNetworkMap;
|
struct pxr::HdMaterialNetworkMap;
|
||||||
|
|
||||||
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlx_path,
|
void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
|
||||||
pxr::TfTokenVector const &shader_source_types,
|
pxr::TfTokenVector const &shader_source_types,
|
||||||
pxr::TfTokenVector const &render_contexts,
|
pxr::TfTokenVector const &render_contexts,
|
||||||
pxr::HdMaterialNetworkMap *out);
|
pxr::HdMaterialNetworkMap *out);
|
||||||
|
@ -11,7 +11,13 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
bool ObjectData::supported(Object *object)
|
ObjectData::ObjectData(BlenderSceneDelegate *scene_delegate, Object *object)
|
||||||
|
: IdData(scene_delegate, (ID *)object), visible(true)
|
||||||
|
{
|
||||||
|
p_id_ = prim_id(scene_delegate, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectData::is_supported(Object *object)
|
||||||
{
|
{
|
||||||
switch (object->type) {
|
switch (object->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
@ -65,15 +71,9 @@ pxr::SdfPath ObjectData::prim_id(BlenderSceneDelegate *scene_delegate, Object *o
|
|||||||
return scene_delegate->GetDelegateID().AppendElementString(str);
|
return scene_delegate->GetDelegateID().AppendElementString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectData::ObjectData(BlenderSceneDelegate *scene_delegate, Object *object)
|
|
||||||
: IdData(scene_delegate, (ID *)object), visible(true)
|
|
||||||
{
|
|
||||||
p_id = prim_id(scene_delegate, object);
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::GfMatrix4d ObjectData::transform()
|
pxr::GfMatrix4d ObjectData::transform()
|
||||||
{
|
{
|
||||||
return gf_matrix_from_transform(((Object *)id)->object_to_world);
|
return gf_matrix_from_transform(((Object *)id_)->object_to_world);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectData::update_visibility(View3D *view3d)
|
bool ObjectData::update_visibility(View3D *view3d)
|
||||||
@ -83,7 +83,7 @@ bool ObjectData::update_visibility(View3D *view3d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool prev_visible = visible;
|
bool prev_visible = visible;
|
||||||
visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id);
|
visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id_);
|
||||||
return visible != prev_visible;
|
return visible != prev_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ namespace blender::render::hydra {
|
|||||||
|
|
||||||
class ObjectData : public IdData {
|
class ObjectData : public IdData {
|
||||||
public:
|
public:
|
||||||
static bool supported(Object *object);
|
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
|
static bool is_supported(Object *object);
|
||||||
static std::unique_ptr<ObjectData> create(BlenderSceneDelegate *scene_delegate, Object *object);
|
static std::unique_ptr<ObjectData> create(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
|
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
|
|
||||||
|
|
||||||
virtual pxr::GfMatrix4d transform();
|
virtual pxr::GfMatrix4d transform();
|
||||||
virtual bool update_visibility(View3D *view3d);
|
virtual bool update_visibility(View3D *view3d);
|
||||||
|
|
||||||
|
@ -28,6 +28,13 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
WorldData::WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context)
|
||||||
|
: IdData(scene_delegate, (ID *)world), context_(context)
|
||||||
|
{
|
||||||
|
p_id_ = prim_id(scene_delegate);
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id_->name, p_id_.GetText());
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate,
|
std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate,
|
||||||
World *world,
|
World *world,
|
||||||
bContext *context)
|
bContext *context)
|
||||||
@ -43,21 +50,14 @@ pxr::SdfPath WorldData::prim_id(BlenderSceneDelegate *scene_delegate)
|
|||||||
return scene_delegate->GetDelegateID().AppendElementString("World");
|
return scene_delegate->GetDelegateID().AppendElementString("World");
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldData::WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context)
|
|
||||||
: IdData(scene_delegate, (ID *)world), context(context)
|
|
||||||
{
|
|
||||||
p_id = prim_id(scene_delegate);
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s, id=%s", id->name, p_id.GetText());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldData::init()
|
void WorldData::init()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
|
||||||
World *world = (World *)id;
|
World *world = (World *)id_;
|
||||||
data.clear();
|
data_.clear();
|
||||||
|
|
||||||
data[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
|
data_[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
|
||||||
|
|
||||||
if (world->use_nodes) {
|
if (world->use_nodes) {
|
||||||
/* TODO: Create nodes parsing system */
|
/* TODO: Create nodes parsing system */
|
||||||
@ -90,9 +90,9 @@ void WorldData::init()
|
|||||||
|
|
||||||
float const *strength = strength_input.default_value_typed<float>();
|
float const *strength = strength_input.default_value_typed<float>();
|
||||||
float const *color = color_input.default_value_typed<float>();
|
float const *color = color_input.default_value_typed<float>();
|
||||||
data[pxr::HdLightTokens->intensity] = strength[1];
|
data_[pxr::HdLightTokens->intensity] = strength[1];
|
||||||
data[pxr::HdLightTokens->exposure] = 1.0f;
|
data_[pxr::HdLightTokens->exposure] = 1.0f;
|
||||||
data[pxr::HdLightTokens->color] = pxr::GfVec3f(color[0], color[1], color[2]);
|
data_[pxr::HdLightTokens->color] = pxr::GfVec3f(color[0], color[1], color[2]);
|
||||||
|
|
||||||
if (!color_input.directly_linked_links().is_empty()) {
|
if (!color_input.directly_linked_links().is_empty()) {
|
||||||
bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode;
|
bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode;
|
||||||
@ -101,8 +101,8 @@ void WorldData::init()
|
|||||||
Image *image = (Image *)color_input_node->id;
|
Image *image = (Image *)color_input_node->id;
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
Main *bmain = CTX_data_main(context);
|
Main *bmain = CTX_data_main(context_);
|
||||||
Scene *scene = CTX_data_scene(context);
|
Scene *scene = CTX_data_scene(context_);
|
||||||
|
|
||||||
ReportList reports;
|
ReportList reports;
|
||||||
ImageSaveOptions opts;
|
ImageSaveOptions opts;
|
||||||
@ -110,26 +110,53 @@ void WorldData::init()
|
|||||||
|
|
||||||
std::string image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports);
|
std::string image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports);
|
||||||
if (!image_path.empty()) {
|
if (!image_path.empty()) {
|
||||||
data[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path);
|
data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data[pxr::HdLightTokens->intensity] = 1.0f;
|
data_[pxr::HdLightTokens->intensity] = 1.0f;
|
||||||
data[pxr::HdLightTokens->exposure] = world->exposure;
|
data_[pxr::HdLightTokens->exposure] = world->exposure;
|
||||||
data[pxr::HdLightTokens->color] = pxr::GfVec3f(world->horr, world->horg, world->horb);
|
data_[pxr::HdLightTokens->color] = pxr::GfVec3f(world->horr, world->horg, world->horb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldData::insert()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().InsertSprim(
|
||||||
|
pxr::HdPrimTypeTokens->domeLight, scene_delegate_, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldData::remove()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->domeLight, p_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldData::update()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
|
||||||
|
init();
|
||||||
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
|
||||||
|
pxr::HdLight::AllDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldData::update(World *world)
|
||||||
|
{
|
||||||
|
id_ = (ID *)world;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
pxr::GfMatrix4d WorldData::transform()
|
pxr::GfMatrix4d WorldData::transform()
|
||||||
{
|
{
|
||||||
pxr::GfMatrix4d transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90),
|
pxr::GfMatrix4d transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90),
|
||||||
pxr::GfVec3d());
|
pxr::GfVec3d());
|
||||||
|
|
||||||
/* TODO : do this check via RenderSettings*/
|
/* TODO : do this check via RenderSettings*/
|
||||||
if (scene_delegate->GetRenderIndex().GetRenderDelegate()->GetRendererDisplayName() == "RPR") {
|
if (scene_delegate_->GetRenderIndex().GetRenderDelegate()->GetRendererDisplayName() == "RPR") {
|
||||||
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180),
|
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180),
|
||||||
pxr::GfVec3d());
|
pxr::GfVec3d());
|
||||||
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0),
|
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0),
|
||||||
@ -141,37 +168,11 @@ pxr::GfMatrix4d WorldData::transform()
|
|||||||
pxr::VtValue WorldData::get_data(pxr::TfToken const &key) const
|
pxr::VtValue WorldData::get_data(pxr::TfToken const &key) const
|
||||||
{
|
{
|
||||||
pxr::VtValue ret;
|
pxr::VtValue ret;
|
||||||
auto it = data.find(key);
|
auto it = data_.find(key);
|
||||||
if (it != data.end()) {
|
if (it != data_.end()) {
|
||||||
ret = it->second;
|
ret = it->second;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldData::insert()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().InsertSprim(
|
|
||||||
pxr::HdPrimTypeTokens->domeLight, scene_delegate, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldData::remove()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
scene_delegate->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->domeLight, p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldData::update()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
|
||||||
init();
|
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdLight::AllDirty);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldData::update(World *world)
|
|
||||||
{
|
|
||||||
id = (ID *)world;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -20,13 +20,13 @@ namespace blender::render::hydra {
|
|||||||
|
|
||||||
class WorldData : public IdData {
|
class WorldData : public IdData {
|
||||||
public:
|
public:
|
||||||
|
WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context);
|
||||||
|
|
||||||
static std::unique_ptr<WorldData> create(BlenderSceneDelegate *scene_delegate,
|
static std::unique_ptr<WorldData> create(BlenderSceneDelegate *scene_delegate,
|
||||||
World *world,
|
World *world,
|
||||||
bContext *context);
|
bContext *context);
|
||||||
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate);
|
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate);
|
||||||
|
|
||||||
WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context);
|
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
void insert() override;
|
void insert() override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
@ -34,12 +34,11 @@ class WorldData : public IdData {
|
|||||||
void update(World *world);
|
void update(World *world);
|
||||||
|
|
||||||
pxr::GfMatrix4d transform();
|
pxr::GfMatrix4d transform();
|
||||||
|
|
||||||
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
pxr::VtValue get_data(pxr::TfToken const &key) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<pxr::TfToken, pxr::VtValue> data;
|
std::map<pxr::TfToken, pxr::VtValue> data_;
|
||||||
bContext *context;
|
bContext *context_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -27,13 +27,13 @@ pxr::HdTaskSharedPtr SimpleLightTaskDelegate::get_task()
|
|||||||
|
|
||||||
void SimpleLightTaskDelegate::set_camera_path(pxr::SdfPath const &camera_path)
|
void SimpleLightTaskDelegate::set_camera_path(pxr::SdfPath const &camera_path)
|
||||||
{
|
{
|
||||||
task_params.cameraPath = camera_path;
|
task_params_.cameraPath = camera_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::VtValue SimpleLightTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
pxr::VtValue SimpleLightTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
|
||||||
{
|
{
|
||||||
if (key == pxr::HdTokens->params) {
|
if (key == pxr::HdTokens->params) {
|
||||||
return pxr::VtValue(task_params);
|
return pxr::VtValue(task_params_);
|
||||||
}
|
}
|
||||||
return pxr::VtValue();
|
return pxr::VtValue();
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,11 @@ class SimpleLightTaskDelegate : public pxr::HdSceneDelegate {
|
|||||||
pxr::HdTaskSharedPtr get_task();
|
pxr::HdTaskSharedPtr get_task();
|
||||||
void set_camera_path(pxr::SdfPath const &);
|
void set_camera_path(pxr::SdfPath const &);
|
||||||
|
|
||||||
|
/* Delegate methods */
|
||||||
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pxr::HdxSimpleLightTaskParams task_params;
|
pxr::HdxSimpleLightTaskParams task_params_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -5,15 +5,17 @@
|
|||||||
#include <pxr/imaging/glf/drawTarget.h>
|
#include <pxr/imaging/glf/drawTarget.h>
|
||||||
#include <pxr/usd/usdGeom/camera.h>
|
#include <pxr/usd/usdGeom/camera.h>
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_screen_types.h"
|
#include "DNA_screen_types.h"
|
||||||
#include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */
|
#include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */
|
||||||
|
|
||||||
#include "BKE_camera.h"
|
#include "BKE_camera.h"
|
||||||
|
|
||||||
#include "BLI_math_matrix.h"
|
#include "BLI_math_matrix.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph_query.h"
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
#include "GPU_matrix.h"
|
#include "GPU_matrix.h"
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -47,7 +49,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
|
|||||||
|
|
||||||
Scene *scene = CTX_data_scene(context);
|
Scene *scene = CTX_data_scene(context);
|
||||||
|
|
||||||
// getting render border
|
/* Getting render border. */
|
||||||
int x1 = 0, y1 = 0;
|
int x1 = 0, y1 = 0;
|
||||||
int x2 = screen_width, y2 = screen_height;
|
int x2 = screen_width, y2 = screen_height;
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getting camera view region
|
/* Getting camera view region. */
|
||||||
float x1_f = std::min(
|
float x1_f = std::min(
|
||||||
{screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
|
{screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
|
||||||
float x2_f = std::max(
|
float x2_f = std::max(
|
||||||
@ -83,7 +85,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
|
|||||||
float y2_f = std::max(
|
float y2_f = std::max(
|
||||||
{screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
|
{screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
|
||||||
|
|
||||||
// adjusting region to border
|
/* Adjusting region to border. */
|
||||||
float x = x1_f, y = y1_f;
|
float x = x1_f, y = y1_f;
|
||||||
float dx = x2_f - x1_f, dy = y2_f - y1_f;
|
float dx = x2_f - x1_f, dy = y2_f - y1_f;
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
|
|||||||
y1 = y + scene->r.border.ymin * dy;
|
y1 = y + scene->r.border.ymin * dy;
|
||||||
y2 = y + scene->r.border.ymax * dy;
|
y2 = y + scene->r.border.ymax * dy;
|
||||||
|
|
||||||
// adjusting to region screen resolution
|
/* Adjusting to region screen resolution. */
|
||||||
x1 = std::max(std::min(x1, screen_width), 0);
|
x1 = std::max(std::min(x1, screen_width), 0);
|
||||||
x2 = std::max(std::min(x2, screen_width), 0);
|
x2 = std::max(std::min(x2, screen_width), 0);
|
||||||
y1 = std::max(std::min(y1, screen_height), 0);
|
y1 = std::max(std::min(y1, screen_height), 0);
|
||||||
@ -132,7 +134,7 @@ pxr::GfCamera ViewSettings::gf_camera()
|
|||||||
(float)border[3] / screen_height));
|
(float)border[3] / screen_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTexture::DrawTexture() : texture(nullptr), width(0), height(0), channels(4)
|
DrawTexture::DrawTexture() : texture_(nullptr), width_(0), height_(0), channels_(4)
|
||||||
{
|
{
|
||||||
float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0};
|
float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0};
|
||||||
|
|
||||||
@ -144,92 +146,97 @@ DrawTexture::DrawTexture() : texture(nullptr), width(0), height(0), channels(4)
|
|||||||
GPU_vertbuf_attr_fill(vbo, 0, coords);
|
GPU_vertbuf_attr_fill(vbo, 0, coords);
|
||||||
GPU_vertbuf_attr_fill(vbo, 1, coords);
|
GPU_vertbuf_attr_fill(vbo, 1, coords);
|
||||||
|
|
||||||
batch = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
batch_ = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTexture::~DrawTexture()
|
DrawTexture::~DrawTexture()
|
||||||
{
|
{
|
||||||
if (texture) {
|
if (texture_) {
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
GPU_batch_discard(batch);
|
GPU_batch_discard(batch_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTexture::set_buffer(pxr::HdRenderBuffer *buffer)
|
void DrawTexture::set_buffer(pxr::HdRenderBuffer *buffer)
|
||||||
{
|
{
|
||||||
if (!texture) {
|
if (!texture_) {
|
||||||
create(buffer);
|
create(buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width != buffer->GetWidth() || height != buffer->GetHeight()) {
|
if (width_ != buffer->GetWidth() || height_ != buffer->GetHeight()) {
|
||||||
free();
|
free();
|
||||||
create(buffer);
|
create(buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *data = buffer->Map();
|
void *data = buffer->Map();
|
||||||
GPU_texture_update(texture, GPU_DATA_FLOAT, data);
|
GPU_texture_update(texture_, GPU_DATA_FLOAT, data);
|
||||||
buffer->Unmap();
|
buffer->Unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawTexture::draw(GPUShader *shader, float x, float y)
|
||||||
|
{
|
||||||
|
int slot = GPU_shader_get_sampler_binding(shader, "image");
|
||||||
|
GPU_texture_bind(texture_, slot);
|
||||||
|
GPU_shader_uniform_1i(shader, "image", slot);
|
||||||
|
|
||||||
|
GPU_matrix_push();
|
||||||
|
GPU_matrix_translate_2f(x, y);
|
||||||
|
GPU_matrix_scale_2f(width_, height_);
|
||||||
|
GPU_batch_set_shader(batch_, shader);
|
||||||
|
GPU_batch_draw(batch_);
|
||||||
|
GPU_matrix_pop();
|
||||||
|
}
|
||||||
|
|
||||||
void DrawTexture::create(pxr::HdRenderBuffer *buffer)
|
void DrawTexture::create(pxr::HdRenderBuffer *buffer)
|
||||||
{
|
{
|
||||||
width = buffer->GetWidth();
|
width_ = buffer->GetWidth();
|
||||||
height = buffer->GetHeight();
|
height_ = buffer->GetHeight();
|
||||||
channels = pxr::HdGetComponentCount(buffer->GetFormat());
|
channels_ = pxr::HdGetComponentCount(buffer->GetFormat());
|
||||||
|
|
||||||
void *data = buffer->Map();
|
void *data = buffer->Map();
|
||||||
texture = GPU_texture_create_2d("texHydraRenderViewport",
|
texture_ = GPU_texture_create_2d("tex_hydra_render_viewport",
|
||||||
width,
|
width_,
|
||||||
height,
|
height_,
|
||||||
1,
|
1,
|
||||||
GPU_RGBA16F,
|
GPU_RGBA16F,
|
||||||
GPU_TEXTURE_USAGE_GENERAL,
|
GPU_TEXTURE_USAGE_GENERAL,
|
||||||
(float *)data);
|
(float *)data);
|
||||||
buffer->Unmap();
|
buffer->Unmap();
|
||||||
|
|
||||||
GPU_texture_filter_mode(texture, true);
|
GPU_texture_filter_mode(texture_, true);
|
||||||
GPU_texture_mipmap_mode(texture, true, true);
|
GPU_texture_mipmap_mode(texture_, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTexture::free()
|
void DrawTexture::free()
|
||||||
{
|
{
|
||||||
GPU_texture_free(texture);
|
GPU_texture_free(texture_);
|
||||||
texture = nullptr;
|
texture_ = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
void DrawTexture::draw(GPUShader *shader, float x, float y)
|
|
||||||
{
|
|
||||||
int slot = GPU_shader_get_sampler_binding(shader, "image");
|
|
||||||
GPU_texture_bind(texture, slot);
|
|
||||||
GPU_shader_uniform_1i(shader, "image", slot);
|
|
||||||
|
|
||||||
GPU_matrix_push();
|
|
||||||
GPU_matrix_translate_2f(x, y);
|
|
||||||
GPU_matrix_scale_2f(width, height);
|
|
||||||
GPU_batch_set_shader(batch, shader);
|
|
||||||
GPU_batch_draw(batch);
|
|
||||||
GPU_matrix_pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewportEngine::sync(Depsgraph *depsgraph,
|
void ViewportEngine::sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings)
|
pxr::HdRenderSettingsMap &render_settings)
|
||||||
{
|
{
|
||||||
if (!scene_delegate) {
|
if (!scene_delegate_) {
|
||||||
scene_delegate = std::make_unique<BlenderSceneDelegate>(
|
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
|
||||||
render_index.get(),
|
render_index_.get(),
|
||||||
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
|
||||||
BlenderSceneDelegate::EngineType::VIEWPORT);
|
BlenderSceneDelegate::EngineType::VIEWPORT);
|
||||||
}
|
}
|
||||||
scene_delegate->populate(depsgraph, context);
|
scene_delegate_->populate(depsgraph, context);
|
||||||
|
|
||||||
for (auto const &setting : render_settings) {
|
for (auto const &setting : render_settings) {
|
||||||
render_delegate->SetRenderSetting(setting.first, setting.second);
|
render_delegate_->SetRenderSetting(setting.first, setting.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewportEngine::render(Depsgraph *depsgraph)
|
||||||
|
{
|
||||||
|
/* Empty function */
|
||||||
|
}
|
||||||
|
|
||||||
void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
|
void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
|
||||||
{
|
{
|
||||||
ViewSettings view_settings(context);
|
ViewSettings view_settings(context);
|
||||||
@ -238,41 +245,41 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
|
|||||||
};
|
};
|
||||||
|
|
||||||
pxr::GfCamera gf_camera = view_settings.gf_camera();
|
pxr::GfCamera gf_camera = view_settings.gf_camera();
|
||||||
free_camera_delegate->SetCamera(gf_camera);
|
free_camera_delegate_->SetCamera(gf_camera);
|
||||||
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(),
|
render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
|
||||||
pxr::GfVec4d(view_settings.border[0],
|
pxr::GfVec4d(view_settings.border[0],
|
||||||
view_settings.border[1],
|
view_settings.border[1],
|
||||||
view_settings.border[2],
|
view_settings.border[2],
|
||||||
view_settings.border[3]));
|
view_settings.border[3]));
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId());
|
simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bl_engine->type->flag & RE_USE_GPU_CONTEXT) == 0) {
|
if ((bl_engine_->type->flag & RE_USE_GPU_CONTEXT) == 0) {
|
||||||
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color);
|
render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer_percent_done() == 0.0f) {
|
if (renderer_percent_done() == 0.0f) {
|
||||||
time_begin = std::chrono::steady_clock::now();
|
time_begin_ = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE);
|
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE);
|
||||||
GPU_shader_bind(shader);
|
GPU_shader_bind(shader);
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
pxr::HdTaskSharedPtrVector tasks;
|
||||||
if (simple_light_task_delegate) {
|
if (simple_light_task_delegate_) {
|
||||||
tasks.push_back(simple_light_task_delegate->get_task());
|
tasks.push_back(simple_light_task_delegate_->get_task());
|
||||||
}
|
}
|
||||||
tasks.push_back(render_task_delegate->get_task());
|
tasks.push_back(render_task_delegate_->get_task());
|
||||||
|
|
||||||
{
|
{
|
||||||
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
|
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
|
||||||
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
|
||||||
engine->Execute(render_index.get(), &tasks);
|
engine_->Execute(render_index_.get(), &tasks);
|
||||||
|
|
||||||
if ((bl_engine->type->flag & RE_USE_GPU_CONTEXT) == 0) {
|
if ((bl_engine_->type->flag & RE_USE_GPU_CONTEXT) == 0) {
|
||||||
draw_texture.set_buffer(render_task_delegate->get_renderer_aov(pxr::HdAovTokens->color));
|
draw_texture_.set_buffer(render_task_delegate_->get_renderer_aov(pxr::HdAovTokens->color));
|
||||||
draw_texture.draw(shader, view_settings.border[0], view_settings.border[1]);
|
draw_texture_.draw(shader, view_settings.border[0], view_settings.border[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,29 +288,24 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
|
|||||||
std::chrono::time_point<std::chrono::steady_clock> time_current =
|
std::chrono::time_point<std::chrono::steady_clock> time_current =
|
||||||
std::chrono::steady_clock::now();
|
std::chrono::steady_clock::now();
|
||||||
std::chrono::milliseconds elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
std::chrono::milliseconds elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
time_current - time_begin);
|
time_current - time_begin_);
|
||||||
|
|
||||||
std::string formatted_time = format_duration(elapsed_time);
|
std::string formatted_time = format_duration(elapsed_time);
|
||||||
|
|
||||||
if (!render_task_delegate->is_converged()) {
|
if (!render_task_delegate_->is_converged()) {
|
||||||
notify_status("Time: " + formatted_time +
|
notify_status("Time: " + formatted_time +
|
||||||
" | Done: " + std::to_string(int(renderer_percent_done())) + "%",
|
" | Done: " + std::to_string(int(renderer_percent_done())) + "%",
|
||||||
"Render");
|
"Render");
|
||||||
bl_engine->flag |= RE_ENGINE_DO_DRAW;
|
bl_engine_->flag |= RE_ENGINE_DO_DRAW;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
notify_status(("Time: " + formatted_time).c_str(), "Rendering Done");
|
notify_status(("Time: " + formatted_time).c_str(), "Rendering Done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewportEngine::render(Depsgraph *depsgraph)
|
|
||||||
{
|
|
||||||
/* Empty function */
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewportEngine::notify_status(const std::string &info, const std::string &status)
|
void ViewportEngine::notify_status(const std::string &info, const std::string &status)
|
||||||
{
|
{
|
||||||
RE_engine_update_stats(bl_engine, status.c_str(), info.c_str());
|
RE_engine_update_stats(bl_engine_, status.c_str(), info.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -19,6 +19,7 @@ class DrawTexture {
|
|||||||
public:
|
public:
|
||||||
DrawTexture();
|
DrawTexture();
|
||||||
~DrawTexture();
|
~DrawTexture();
|
||||||
|
|
||||||
void set_buffer(pxr::HdRenderBuffer *buffer);
|
void set_buffer(pxr::HdRenderBuffer *buffer);
|
||||||
void draw(GPUShader *shader, float x, float y);
|
void draw(GPUShader *shader, float x, float y);
|
||||||
|
|
||||||
@ -26,14 +27,15 @@ class DrawTexture {
|
|||||||
void create(pxr::HdRenderBuffer *buffer);
|
void create(pxr::HdRenderBuffer *buffer);
|
||||||
void free();
|
void free();
|
||||||
|
|
||||||
GPUTexture *texture;
|
GPUTexture *texture_;
|
||||||
GPUBatch *batch;
|
GPUBatch *batch_;
|
||||||
int width, height, channels;
|
int width_, height_, channels_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ViewportEngine : public Engine {
|
class ViewportEngine : public Engine {
|
||||||
public:
|
public:
|
||||||
using Engine::Engine;
|
using Engine::Engine;
|
||||||
|
|
||||||
void sync(Depsgraph *depsgraph,
|
void sync(Depsgraph *depsgraph,
|
||||||
bContext *context,
|
bContext *context,
|
||||||
pxr::HdRenderSettingsMap &render_settings) override;
|
pxr::HdRenderSettingsMap &render_settings) override;
|
||||||
@ -44,9 +46,9 @@ class ViewportEngine : public Engine {
|
|||||||
void notify_status(const std::string &title, const std::string &info);
|
void notify_status(const std::string &title, const std::string &info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::chrono::time_point<std::chrono::steady_clock> time_begin;
|
std::chrono::time_point<std::chrono::steady_clock> time_begin_;
|
||||||
|
|
||||||
DrawTexture draw_texture;
|
DrawTexture draw_texture_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
Loading…
Reference in New Issue
Block a user
= nullptr