Overlay-Next Camera
Overlay-Next version of Camera. Rel #102179 #109059 was used as a reference. Pull Request: https://projects.blender.org/blender/blender/pulls/124122
This commit is contained in:
committed by
Clément Foucault
parent
4d85c03815
commit
d4ce2dfe60
@@ -292,6 +292,7 @@ set(SRC
|
||||
engines/overlay/overlay_next_background.hh
|
||||
engines/overlay/overlay_next_bounds.hh
|
||||
engines/overlay/overlay_next_empty.hh
|
||||
engines/overlay/overlay_next_camera.hh
|
||||
engines/overlay/overlay_next_grid.hh
|
||||
engines/overlay/overlay_next_instance.hh
|
||||
engines/overlay/overlay_next_lattice.hh
|
||||
|
||||
555
source/blender/draw/engines/overlay/overlay_next_camera.hh
Normal file
555
source/blender/draw/engines/overlay/overlay_next_camera.hh
Normal file
@@ -0,0 +1,555 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_camera.h"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
||||
#include "DNA_camera_types.h"
|
||||
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "draw_manager_text.hh"
|
||||
#include "overlay_next_empty.hh"
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
static float camera_offaxis_shiftx_get(const Scene *scene,
|
||||
const Object *ob,
|
||||
float corner_x,
|
||||
bool right_eye)
|
||||
{
|
||||
const Camera *cam = static_cast<const Camera *>(ob->data);
|
||||
if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
|
||||
const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, viewnames[right_eye]);
|
||||
const float delta_shiftx = shiftx - cam->shiftx;
|
||||
const float width = corner_x * 2.0f;
|
||||
return delta_shiftx * width;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
struct CameraInstanceData : public ExtraInstanceData {
|
||||
public:
|
||||
float &volume_start = color_[2];
|
||||
float &volume_end = color_[3];
|
||||
float &depth = color_[3];
|
||||
float &focus = color_[3];
|
||||
float4x4 &matrix = object_to_world_;
|
||||
float &dist_color_id = matrix[0][3];
|
||||
float &corner_x = matrix[0][3];
|
||||
float &corner_y = matrix[1][3];
|
||||
float ¢er_x = matrix[2][3];
|
||||
float &clip_start = matrix[2][3];
|
||||
float &mist_start = matrix[2][3];
|
||||
float ¢er_y = matrix[3][3];
|
||||
float &clip_end = matrix[3][3];
|
||||
float &mist_end = matrix[3][3];
|
||||
|
||||
CameraInstanceData(const CameraInstanceData &data)
|
||||
: CameraInstanceData(data.object_to_world_, data.color_)
|
||||
{
|
||||
}
|
||||
|
||||
CameraInstanceData(const float4x4 &p_matrix, const float4 &color)
|
||||
: ExtraInstanceData(p_matrix, color, 1.0f){};
|
||||
};
|
||||
|
||||
class Cameras {
|
||||
using CameraInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
|
||||
private:
|
||||
PassSimple ps_ = {"Cameras"};
|
||||
struct CallBuffers {
|
||||
const SelectionType selection_type_;
|
||||
CameraInstanceBuf distances_buf = {selection_type_, "camera_distances_buf"};
|
||||
CameraInstanceBuf frame_buf = {selection_type_, "camera_frame_buf"};
|
||||
CameraInstanceBuf tria_buf = {selection_type_, "camera_tria_buf"};
|
||||
CameraInstanceBuf tria_wire_buf = {selection_type_, "camera_tria_wire_buf"};
|
||||
CameraInstanceBuf volume_buf = {selection_type_, "camera_volume_buf"};
|
||||
CameraInstanceBuf volume_wire_buf = {selection_type_, "camera_volume_wire_buf"};
|
||||
CameraInstanceBuf sphere_solid_buf = {selection_type_, "camera_sphere_solid_buf"};
|
||||
LineInstanceBuf stereo_connect_lines = {selection_type_, "camera_dashed_lines_buf"};
|
||||
LineInstanceBuf tracking_path = {selection_type_, "camera_tracking_path_buf"};
|
||||
Empties::CallBuffers empties{selection_type_};
|
||||
} call_buffers_;
|
||||
|
||||
static void view3d_reconstruction(const select::ID select_id,
|
||||
const Scene *scene,
|
||||
const View3D *v3d,
|
||||
const float4 &color,
|
||||
const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
CallBuffers &call_buffers)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const bool is_select = DRW_state_is_select();
|
||||
Object *ob = ob_ref.object;
|
||||
|
||||
MovieClip *clip = BKE_object_movieclip_get((Scene *)scene, ob, false);
|
||||
if (clip == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool is_solid_bundle = (v3d->bundle_drawtype == OB_EMPTY_SPHERE) &&
|
||||
((v3d->shading.type != OB_SOLID) || !XRAY_FLAG_ENABLED(v3d));
|
||||
|
||||
MovieTracking *tracking = &clip->tracking;
|
||||
/* Index must start in 1, to mimic BKE_tracking_track_get_for_selection_index. */
|
||||
int track_index = 1;
|
||||
|
||||
float4 bundle_color_custom;
|
||||
float *bundle_color_solid = G_draw.block.color_bundle_solid;
|
||||
float *bundle_color_unselected = G_draw.block.color_wire;
|
||||
uchar4 text_color_selected, text_color_unselected;
|
||||
/* Color Management: Exception here as texts are drawn in sRGB space directly. */
|
||||
UI_GetThemeColor4ubv(TH_SELECT, text_color_selected);
|
||||
UI_GetThemeColor4ubv(TH_TEXT, text_color_unselected);
|
||||
|
||||
float4x4 camera_mat;
|
||||
BKE_tracking_get_camera_object_matrix(ob, camera_mat.ptr());
|
||||
|
||||
const float4x4 object_to_world{ob->object_to_world().ptr()};
|
||||
|
||||
LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
|
||||
float4x4 tracking_object_mat;
|
||||
|
||||
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
||||
tracking_object_mat = camera_mat;
|
||||
}
|
||||
else {
|
||||
const int framenr = BKE_movieclip_remap_scene_to_clip_frame(
|
||||
clip, DEG_get_ctime(draw_ctx->depsgraph));
|
||||
|
||||
float4x4 object_mat;
|
||||
BKE_tracking_camera_get_reconstructed_interpolate(
|
||||
tracking, tracking_object, framenr, object_mat.ptr());
|
||||
|
||||
tracking_object_mat = object_to_world * math::invert(object_mat);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
||||
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
bool is_selected = TRACK_SELECTED(track);
|
||||
|
||||
float4x4 bundle_mat = math::translate(tracking_object_mat, float3{track->bundle_pos});
|
||||
|
||||
const float *bundle_color;
|
||||
if (track->flag & TRACK_CUSTOMCOLOR) {
|
||||
/* Meh, hardcoded srgb transform here. */
|
||||
/* TODO: change the actual DNA color to be linear. */
|
||||
srgb_to_linearrgb_v3_v3(bundle_color_custom, track->color);
|
||||
bundle_color_custom[3] = 1.0;
|
||||
|
||||
bundle_color = bundle_color_custom;
|
||||
}
|
||||
else if (is_solid_bundle) {
|
||||
bundle_color = bundle_color_solid;
|
||||
}
|
||||
else if (is_selected) {
|
||||
bundle_color = color;
|
||||
}
|
||||
else {
|
||||
bundle_color = bundle_color_unselected;
|
||||
}
|
||||
|
||||
const select::ID track_select_id = is_select ? res.select_id(ob_ref, track_index++ << 16) :
|
||||
select_id;
|
||||
if (is_solid_bundle) {
|
||||
if (is_selected) {
|
||||
Empties::object_sync(track_select_id,
|
||||
bundle_mat,
|
||||
v3d->bundle_size,
|
||||
v3d->bundle_drawtype,
|
||||
color,
|
||||
call_buffers.empties);
|
||||
}
|
||||
|
||||
call_buffers.sphere_solid_buf.append(
|
||||
ExtraInstanceData{bundle_mat, {float3{bundle_color}, 1.0f}, v3d->bundle_size},
|
||||
track_select_id);
|
||||
}
|
||||
else {
|
||||
Empties::object_sync(track_select_id,
|
||||
bundle_mat,
|
||||
v3d->bundle_size,
|
||||
v3d->bundle_drawtype,
|
||||
bundle_color,
|
||||
call_buffers.empties);
|
||||
}
|
||||
|
||||
if ((v3d->flag2 & V3D_SHOW_BUNDLENAME) && !is_select) {
|
||||
DRWTextStore *dt = DRW_text_cache_ensure();
|
||||
|
||||
DRW_text_cache_add(dt,
|
||||
bundle_mat[3],
|
||||
track->name,
|
||||
strlen(track->name),
|
||||
10,
|
||||
0,
|
||||
DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
|
||||
is_selected ? text_color_selected : text_color_unselected);
|
||||
}
|
||||
}
|
||||
|
||||
if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA) &&
|
||||
!is_select)
|
||||
{
|
||||
const MovieTrackingReconstruction *reconstruction = &tracking_object->reconstruction;
|
||||
|
||||
if (reconstruction->camnr) {
|
||||
const MovieReconstructedCamera *camera = reconstruction->cameras;
|
||||
float3 v0, v1;
|
||||
for (int a = 0; a < reconstruction->camnr; a++, camera++) {
|
||||
v0 = v1;
|
||||
v1 = math::transform_point(camera_mat, float3(camera->mat[3]));
|
||||
if (a > 0) {
|
||||
/* This one is suboptimal (gl_lines instead of gl_line_strip)
|
||||
* but we keep this for simplicity */
|
||||
call_buffers.tracking_path.append(v0, v1, TH_CAMERA_PATH, select_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the stereo 3d support elements (cameras, plane, volume).
|
||||
* They are only visible when not looking through the camera:
|
||||
*/
|
||||
static void stereoscopy_extra(const CameraInstanceData &instdata,
|
||||
const select::ID select_id,
|
||||
const Scene *scene,
|
||||
const View3D *v3d,
|
||||
Resources &res,
|
||||
Object *ob,
|
||||
CallBuffers &call_buffers)
|
||||
{
|
||||
CameraInstanceData stereodata = instdata;
|
||||
|
||||
const Camera *cam = static_cast<const Camera *>(ob->data);
|
||||
const bool is_select = DRW_state_is_select();
|
||||
const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
|
||||
const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) != 0;
|
||||
const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) != 0;
|
||||
const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME) != 0;
|
||||
|
||||
if (!is_stereo3d_cameras) {
|
||||
/* Draw single camera. */
|
||||
call_buffers.frame_buf.append(instdata, select_id);
|
||||
}
|
||||
|
||||
for (const int eye : IndexRange(2)) {
|
||||
ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]);
|
||||
BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[eye], stereodata.matrix.ptr());
|
||||
|
||||
stereodata.corner_x = instdata.corner_x;
|
||||
stereodata.corner_y = instdata.corner_y;
|
||||
stereodata.center_x = instdata.center_x +
|
||||
camera_offaxis_shiftx_get(scene, ob, instdata.corner_x, eye);
|
||||
stereodata.center_y = instdata.center_y;
|
||||
stereodata.depth = instdata.depth;
|
||||
|
||||
if (is_stereo3d_cameras) {
|
||||
call_buffers.frame_buf.append(stereodata, select_id);
|
||||
|
||||
/* Connecting line between cameras. */
|
||||
call_buffers.stereo_connect_lines.append(stereodata.matrix.location(),
|
||||
instdata.object_to_world_.location(),
|
||||
res.theme_settings.color_wire,
|
||||
select_id);
|
||||
}
|
||||
|
||||
if (is_stereo3d_volume && !is_select) {
|
||||
float r = (eye == 1) ? 2.0f : 1.0f;
|
||||
|
||||
stereodata.volume_start = -cam->clip_start;
|
||||
stereodata.volume_end = -cam->clip_end;
|
||||
/* Encode eye + intensity and alpha (see shader) */
|
||||
copy_v2_fl2(stereodata.color_, r + 0.15f, 1.0f);
|
||||
call_buffers.volume_wire_buf.append(stereodata, select_id);
|
||||
|
||||
if (v3d->stereo3d_volume_alpha > 0.0f) {
|
||||
/* Encode eye + intensity and alpha (see shader) */
|
||||
copy_v2_fl2(stereodata.color_, r + 0.999f, v3d->stereo3d_volume_alpha);
|
||||
call_buffers.volume_buf.append(stereodata, select_id);
|
||||
}
|
||||
/* restore */
|
||||
copy_v3_v3(stereodata.color_, instdata.color_);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_stereo3d_plane && !is_select) {
|
||||
if (cam->stereo.convergence_mode == CAM_S3D_TOE) {
|
||||
/* There is no real convergence plane but we highlight the center
|
||||
* point where the views are pointing at. */
|
||||
// zero_v3(stereodata.mat[0]); /* We reconstruct from Z and Y */
|
||||
// zero_v3(stereodata.mat[1]); /* Y doesn't change */
|
||||
stereodata.matrix.z_axis() = float3(0.0f);
|
||||
stereodata.matrix.location() = float3(0.0f);
|
||||
for (int i : IndexRange(2)) {
|
||||
float4x4 mat;
|
||||
/* Need normalized version here. */
|
||||
BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[i], mat.ptr());
|
||||
stereodata.matrix.z_axis() += mat.z_axis();
|
||||
stereodata.matrix.location() += mat.location() * 0.5f;
|
||||
}
|
||||
stereodata.matrix.z_axis() = math::normalize(stereodata.matrix.z_axis());
|
||||
stereodata.matrix.x_axis() = math::cross(stereodata.matrix.y_axis(),
|
||||
stereodata.matrix.z_axis());
|
||||
}
|
||||
else if (cam->stereo.convergence_mode == CAM_S3D_PARALLEL) {
|
||||
/* Show plane at the given distance between the views even if it makes no sense. */
|
||||
stereodata.matrix.location() = float3(0.0f);
|
||||
for (int i : IndexRange(2)) {
|
||||
float4x4 mat;
|
||||
BKE_camera_multiview_model_matrix_scaled(&scene->r, ob, viewnames[i], mat.ptr());
|
||||
stereodata.matrix.location() += mat.location() * 0.5f;
|
||||
}
|
||||
}
|
||||
else if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
|
||||
/* Nothing to do. Everything is already setup. */
|
||||
}
|
||||
stereodata.volume_start = -cam->stereo.convergence_distance;
|
||||
stereodata.volume_end = -cam->stereo.convergence_distance;
|
||||
/* Encode eye + intensity and alpha (see shader) */
|
||||
copy_v2_fl2(stereodata.color_, 0.1f, 1.0f);
|
||||
call_buffers.volume_wire_buf.append(stereodata, select_id);
|
||||
|
||||
if (v3d->stereo3d_convergence_alpha > 0.0f) {
|
||||
/* Encode eye + intensity and alpha (see shader) */
|
||||
copy_v2_fl2(stereodata.color_, 0.0f, v3d->stereo3d_convergence_alpha);
|
||||
call_buffers.volume_buf.append(stereodata, select_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Cameras(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
||||
|
||||
void begin_sync()
|
||||
{
|
||||
call_buffers_.distances_buf.clear();
|
||||
call_buffers_.frame_buf.clear();
|
||||
call_buffers_.tria_buf.clear();
|
||||
call_buffers_.tria_wire_buf.clear();
|
||||
call_buffers_.volume_buf.clear();
|
||||
call_buffers_.volume_wire_buf.clear();
|
||||
call_buffers_.sphere_solid_buf.clear();
|
||||
call_buffers_.stereo_connect_lines.clear();
|
||||
call_buffers_.tracking_path.clear();
|
||||
Empties::begin_sync(call_buffers_.empties);
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, Resources &res, State &state)
|
||||
{
|
||||
Object *ob = ob_ref.object;
|
||||
const select::ID select_id = res.select_id(ob_ref);
|
||||
CameraInstanceData data(ob->object_to_world(), res.object_wire_color(ob_ref, state));
|
||||
|
||||
const View3D *v3d = state.v3d;
|
||||
const Scene *scene = state.scene;
|
||||
const RegionView3D *rv3d = state.rv3d;
|
||||
|
||||
const Camera *cam = static_cast<Camera *>(ob->data);
|
||||
const Object *camera_object = DEG_get_evaluated_object(state.depsgraph, v3d->camera);
|
||||
const bool is_select = DRW_state_is_select();
|
||||
const bool is_active = (ob == camera_object);
|
||||
const bool is_camera_view = (is_active && (rv3d->persp == RV3D_CAMOB));
|
||||
|
||||
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||
const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
|
||||
const bool is_stereo3d_display_extra = is_active && is_multiview && (!is_camera_view) &&
|
||||
((v3d->stereo3d_flag) != 0);
|
||||
const bool is_selection_camera_stereo = is_select && is_camera_view && is_multiview &&
|
||||
is_stereo3d_view;
|
||||
|
||||
float3 scale = math::to_scale(data.matrix);
|
||||
/* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */
|
||||
if (is_selection_camera_stereo) {
|
||||
scale = float3(1.0f);
|
||||
}
|
||||
else if (ELEM(0.0f, scale.x, scale.y, scale.z)) {
|
||||
/* Avoid division by 0. */
|
||||
return;
|
||||
}
|
||||
float4x3 vecs;
|
||||
float2 aspect_ratio;
|
||||
float2 shift;
|
||||
float drawsize;
|
||||
|
||||
BKE_camera_view_frame_ex(scene,
|
||||
cam,
|
||||
cam->drawsize,
|
||||
is_camera_view,
|
||||
1.0f / scale,
|
||||
aspect_ratio,
|
||||
shift,
|
||||
&drawsize,
|
||||
vecs.ptr());
|
||||
|
||||
/* Apply scale to simplify the rest of the drawing. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vecs[i] *= scale;
|
||||
/* Project to z=-1 plane. Makes positioning / scaling easier. (see shader) */
|
||||
mul_v2_fl(vecs[i], 1.0f / std::abs(vecs[i].z));
|
||||
}
|
||||
|
||||
/* Frame coords */
|
||||
const float2 center = (vecs[0].xy() + vecs[2].xy()) * 0.5f;
|
||||
const float2 corner = vecs[0].xy() - center.xy();
|
||||
data.corner_x = corner.x;
|
||||
data.corner_y = corner.y;
|
||||
data.center_x = center.x;
|
||||
data.center_y = center.y;
|
||||
data.depth = vecs[0].z;
|
||||
|
||||
if (is_camera_view) {
|
||||
/* TODO(Miguel Pozo) */
|
||||
if (!DRW_state_is_image_render()) {
|
||||
/* Only draw the frame. */
|
||||
if (is_multiview) {
|
||||
float4x4 mat;
|
||||
const bool is_right = v3d->multiview_eye == STEREO_RIGHT_ID;
|
||||
const char *view_name = is_right ? STEREO_RIGHT_NAME : STEREO_LEFT_NAME;
|
||||
BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat.ptr());
|
||||
data.center_x += camera_offaxis_shiftx_get(scene, ob, data.corner_x, is_right);
|
||||
for (int i : IndexRange(4)) {
|
||||
/* Partial copy to avoid overriding packed data. */
|
||||
copy_v3_v3(data.matrix[i], mat[i].xyz());
|
||||
}
|
||||
}
|
||||
data.depth *= -1.0f; /* Hides the back of the camera wires (see shader). */
|
||||
call_buffers_.frame_buf.append(data, select_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Stereo cameras, volumes, plane drawing. */
|
||||
if (is_stereo3d_display_extra) {
|
||||
stereoscopy_extra(data, select_id, scene, v3d, res, ob, call_buffers_);
|
||||
}
|
||||
else {
|
||||
call_buffers_.frame_buf.append(data, select_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_camera_view) {
|
||||
/* Triangle. */
|
||||
float tria_size = 0.7f * drawsize / fabsf(data.depth);
|
||||
float tria_margin = 0.1f * drawsize / fabsf(data.depth);
|
||||
data.center_x = center.x;
|
||||
data.center_y = center.y + data.corner_y + tria_margin + tria_size;
|
||||
data.corner_x = data.corner_y = -tria_size;
|
||||
(is_active ? call_buffers_.tria_buf : call_buffers_.tria_wire_buf).append(data, select_id);
|
||||
}
|
||||
|
||||
if (cam->flag & CAM_SHOWLIMITS) {
|
||||
/* Scale focus point. */
|
||||
data.matrix.x_axis() *= cam->drawsize;
|
||||
data.matrix.y_axis() *= cam->drawsize;
|
||||
|
||||
data.dist_color_id = (is_active) ? 3 : 2;
|
||||
data.focus = -BKE_camera_object_dof_distance(ob);
|
||||
data.clip_start = cam->clip_start;
|
||||
data.clip_end = cam->clip_end;
|
||||
call_buffers_.distances_buf.append(data, select_id);
|
||||
}
|
||||
|
||||
if (cam->flag & CAM_SHOWMIST) {
|
||||
World *world = scene->world;
|
||||
if (world) {
|
||||
data.dist_color_id = (is_active) ? 1 : 0;
|
||||
data.focus = 1.0f; /* Disable */
|
||||
data.mist_start = world->miststa;
|
||||
data.mist_end = world->miststa + world->mistdist;
|
||||
call_buffers_.distances_buf.append(data, select_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Motion Tracking. */
|
||||
if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) != 0) {
|
||||
view3d_reconstruction(
|
||||
select_id, scene, v3d, res.object_wire_color(ob_ref, state), ob_ref, res, call_buffers_);
|
||||
}
|
||||
|
||||
// TODO: /* Background images. */
|
||||
// if (look_through && (cam->flag & CAM_SHOW_BG_IMAGE) &&
|
||||
// !BLI_listbase_is_empty(&cam->bg_images))
|
||||
// {
|
||||
// OVERLAY_image_camera_cache_populate(vedata, ob);
|
||||
// }
|
||||
}
|
||||
|
||||
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
|
||||
{
|
||||
ps_.init();
|
||||
res.select_bind(ps_);
|
||||
|
||||
{
|
||||
PassSimple::Sub &sub_pass = ps_.sub("volume");
|
||||
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK | state.clipping_state);
|
||||
sub_pass.shader_set(res.shaders.extra_shape.get());
|
||||
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
call_buffers_.volume_buf.end_sync(sub_pass, shapes.camera_volume.get());
|
||||
}
|
||||
{
|
||||
PassSimple::Sub &sub_pass = ps_.sub("volume_wire");
|
||||
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK | state.clipping_state);
|
||||
sub_pass.shader_set(res.shaders.extra_shape.get());
|
||||
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
call_buffers_.volume_wire_buf.end_sync(sub_pass, shapes.camera_volume_wire.get());
|
||||
}
|
||||
|
||||
{
|
||||
PassSimple::Sub &sub_pass = ps_.sub("camera_shapes");
|
||||
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL | state.clipping_state);
|
||||
sub_pass.shader_set(res.shaders.extra_shape.get());
|
||||
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
call_buffers_.distances_buf.end_sync(sub_pass, shapes.camera_distances.get());
|
||||
call_buffers_.frame_buf.end_sync(sub_pass, shapes.camera_frame.get());
|
||||
call_buffers_.tria_buf.end_sync(sub_pass, shapes.camera_tria.get());
|
||||
call_buffers_.tria_wire_buf.end_sync(sub_pass, shapes.camera_tria_wire.get());
|
||||
call_buffers_.sphere_solid_buf.end_sync(sub_pass, shapes.sphere_low_detail.get());
|
||||
}
|
||||
{
|
||||
PassSimple::Sub &sub_pass = ps_.sub("camera_extra_wire");
|
||||
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL | state.clipping_state);
|
||||
sub_pass.shader_set(res.shaders.extra_wire.get());
|
||||
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
call_buffers_.stereo_connect_lines.end_sync(sub_pass);
|
||||
call_buffers_.tracking_path.end_sync(sub_pass);
|
||||
}
|
||||
{
|
||||
PassSimple::Sub &sub_pass = ps_.sub("empties");
|
||||
Empties::end_sync(res, shapes, state, sub_pass, call_buffers_.empties);
|
||||
}
|
||||
}
|
||||
|
||||
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
@@ -13,13 +13,11 @@
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
class Empties {
|
||||
friend class Cameras;
|
||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
|
||||
private:
|
||||
const SelectionType selection_type_;
|
||||
|
||||
PassSimple empty_ps_ = {"Empties"};
|
||||
PassSimple empty_in_front_ps_ = {"Empties_In_front"};
|
||||
PassSimple ps_ = {"Empties"};
|
||||
|
||||
struct CallBuffers {
|
||||
const SelectionType selection_type_;
|
||||
@@ -31,97 +29,110 @@ class Empties {
|
||||
EmptyInstanceBuf cone_buf = {selection_type_, "cone_buf"};
|
||||
EmptyInstanceBuf arrows_buf = {selection_type_, "arrows_buf"};
|
||||
EmptyInstanceBuf image_buf = {selection_type_, "image_buf"};
|
||||
} call_buffers_[2] = {{selection_type_}, {selection_type_}};
|
||||
} call_buffers_;
|
||||
|
||||
public:
|
||||
Empties(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||
Empties(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
||||
|
||||
void begin_sync()
|
||||
{
|
||||
for (int i = 0; i < 2; i++) {
|
||||
call_buffers_[i].plain_axes_buf.clear();
|
||||
call_buffers_[i].single_arrow_buf.clear();
|
||||
call_buffers_[i].cube_buf.clear();
|
||||
call_buffers_[i].circle_buf.clear();
|
||||
call_buffers_[i].sphere_buf.clear();
|
||||
call_buffers_[i].cone_buf.clear();
|
||||
call_buffers_[i].arrows_buf.clear();
|
||||
call_buffers_[i].image_buf.clear();
|
||||
}
|
||||
begin_sync(call_buffers_);
|
||||
}
|
||||
|
||||
static void begin_sync(CallBuffers &call_buffers)
|
||||
{
|
||||
call_buffers.plain_axes_buf.clear();
|
||||
call_buffers.single_arrow_buf.clear();
|
||||
call_buffers.cube_buf.clear();
|
||||
call_buffers.circle_buf.clear();
|
||||
call_buffers.sphere_buf.clear();
|
||||
call_buffers.cone_buf.clear();
|
||||
call_buffers.arrows_buf.clear();
|
||||
call_buffers.image_buf.clear();
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
||||
{
|
||||
CallBuffers &call_bufs = call_buffers_[int((ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0)];
|
||||
|
||||
float4 color = res.object_wire_color(ob_ref, state);
|
||||
ExtraInstanceData data(ob_ref.object->object_to_world(), color, ob_ref.object->empty_drawsize);
|
||||
|
||||
const float4 color = res.object_wire_color(ob_ref, state);
|
||||
const select::ID select_id = res.select_id(ob_ref);
|
||||
object_sync(select_id,
|
||||
ob_ref.object->object_to_world(),
|
||||
ob_ref.object->empty_drawsize,
|
||||
ob_ref.object->empty_drawtype,
|
||||
color,
|
||||
call_buffers_);
|
||||
}
|
||||
|
||||
switch (ob_ref.object->empty_drawtype) {
|
||||
static void object_sync(const select::ID select_id,
|
||||
const float4x4 &matrix,
|
||||
const float draw_size,
|
||||
const char empty_drawtype,
|
||||
const float4 &color,
|
||||
CallBuffers &call_buffers)
|
||||
{
|
||||
ExtraInstanceData data(matrix, color, draw_size);
|
||||
|
||||
switch (empty_drawtype) {
|
||||
case OB_PLAINAXES:
|
||||
call_bufs.plain_axes_buf.append(data, select_id);
|
||||
call_buffers.plain_axes_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_SINGLE_ARROW:
|
||||
call_bufs.single_arrow_buf.append(data, select_id);
|
||||
call_buffers.single_arrow_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_CUBE:
|
||||
call_bufs.cube_buf.append(data, select_id);
|
||||
call_buffers.cube_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_CIRCLE:
|
||||
call_bufs.circle_buf.append(data, select_id);
|
||||
call_buffers.circle_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_SPHERE:
|
||||
call_bufs.sphere_buf.append(data, select_id);
|
||||
call_buffers.sphere_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_CONE:
|
||||
call_bufs.cone_buf.append(data, select_id);
|
||||
call_buffers.cone_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_ARROWS:
|
||||
call_bufs.arrows_buf.append(data, select_id);
|
||||
call_buffers.arrows_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_IMAGE:
|
||||
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
|
||||
call_bufs.image_buf.append(data, select_id);
|
||||
call_buffers.image_buf.append(data, select_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
|
||||
{
|
||||
auto init_pass = [&](PassSimple &pass, CallBuffers &call_bufs) {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
pass.shader_set(res.shaders.extra_shape.get());
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
res.select_bind(pass);
|
||||
|
||||
call_bufs.plain_axes_buf.end_sync(pass, shapes.plain_axes.get());
|
||||
call_bufs.single_arrow_buf.end_sync(pass, shapes.single_arrow.get());
|
||||
call_bufs.cube_buf.end_sync(pass, shapes.cube.get());
|
||||
call_bufs.circle_buf.end_sync(pass, shapes.circle.get());
|
||||
call_bufs.sphere_buf.end_sync(pass, shapes.empty_sphere.get());
|
||||
call_bufs.cone_buf.end_sync(pass, shapes.empty_cone.get());
|
||||
call_bufs.arrows_buf.end_sync(pass, shapes.arrows.get());
|
||||
call_bufs.image_buf.end_sync(pass, shapes.quad_wire.get());
|
||||
};
|
||||
|
||||
init_pass(empty_ps_, call_buffers_[0]);
|
||||
init_pass(empty_in_front_ps_, call_buffers_[1]);
|
||||
ps_.init();
|
||||
res.select_bind(ps_);
|
||||
end_sync(res, shapes, state, ps_, call_buffers_);
|
||||
}
|
||||
|
||||
void draw(Resources &res, Manager &manager, View &view)
|
||||
static void end_sync(Resources &res,
|
||||
ShapeCache &shapes,
|
||||
const State &state,
|
||||
PassSimple::Sub &ps,
|
||||
CallBuffers &call_buffers)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_fb);
|
||||
manager.submit(empty_ps_, view);
|
||||
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
ps.shader_set(res.shaders.extra_shape.get());
|
||||
ps.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
|
||||
call_buffers.plain_axes_buf.end_sync(ps, shapes.plain_axes.get());
|
||||
call_buffers.single_arrow_buf.end_sync(ps, shapes.single_arrow.get());
|
||||
call_buffers.cube_buf.end_sync(ps, shapes.cube.get());
|
||||
call_buffers.circle_buf.end_sync(ps, shapes.circle.get());
|
||||
call_buffers.sphere_buf.end_sync(ps, shapes.empty_sphere.get());
|
||||
call_buffers.cone_buf.end_sync(ps, shapes.empty_cone.get());
|
||||
call_buffers.arrows_buf.end_sync(ps, shapes.arrows.get());
|
||||
call_buffers.image_buf.end_sync(ps, shapes.quad_wire.get());
|
||||
}
|
||||
|
||||
void draw_in_front(Resources &res, Manager &manager, View &view)
|
||||
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_in_front_fb);
|
||||
manager.submit(empty_in_front_ps_, view);
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -78,11 +78,12 @@ void Instance::begin_sync()
|
||||
|
||||
background.begin_sync(resources, state);
|
||||
prepass.begin_sync(resources, state);
|
||||
empties.begin_sync();
|
||||
lattices.begin_sync(resources, state);
|
||||
|
||||
auto begin_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.bounds.begin_sync();
|
||||
layer.cameras.begin_sync();
|
||||
layer.empties.begin_sync();
|
||||
layer.lights.begin_sync();
|
||||
};
|
||||
begin_sync_layer(regular);
|
||||
@@ -138,7 +139,10 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
if (!state.hide_overlays) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_EMPTY:
|
||||
empties.object_sync(ob_ref, resources, state);
|
||||
layer.empties.object_sync(ob_ref, resources, state);
|
||||
break;
|
||||
case OB_CAMERA:
|
||||
layer.cameras.object_sync(ob_ref, resources, state);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
break;
|
||||
@@ -161,7 +165,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
speakers.object_sync(ob_ref, resources, state);
|
||||
break;
|
||||
}
|
||||
regular.bounds.object_sync(ob_ref, resources, state);
|
||||
layer.bounds.object_sync(ob_ref, resources, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,13 +175,14 @@ void Instance::end_sync()
|
||||
|
||||
auto end_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.bounds.end_sync(resources, shapes, state);
|
||||
layer.cameras.end_sync(resources, shapes, state);
|
||||
layer.empties.end_sync(resources, shapes, state);
|
||||
layer.lights.end_sync(resources, shapes, state);
|
||||
};
|
||||
end_sync_layer(regular);
|
||||
end_sync_layer(infront);
|
||||
|
||||
metaballs.end_sync(resources, shapes, state);
|
||||
empties.end_sync(resources, shapes, state);
|
||||
speakers.end_sync(resources, shapes, state);
|
||||
}
|
||||
|
||||
@@ -243,15 +248,15 @@ void Instance::draw(Manager &manager)
|
||||
|
||||
background.draw(resources, manager);
|
||||
regular.bounds.draw(resources.overlay_line_fb, manager, view);
|
||||
regular.cameras.draw(resources.overlay_line_fb, manager, view);
|
||||
regular.empties.draw(resources.overlay_line_fb, manager, view);
|
||||
regular.lights.draw(resources.overlay_line_fb, manager, view);
|
||||
empties.draw(resources, manager, view);
|
||||
lattices.draw(resources, manager, view);
|
||||
metaballs.draw(resources, manager, view);
|
||||
speakers.draw(resources, manager, view);
|
||||
|
||||
grid.draw(resources, manager, view);
|
||||
|
||||
empties.draw_in_front(resources, manager, view);
|
||||
/* TODO(: Breaks selection on M1 Max. */
|
||||
// lattices.draw_in_front(resources, manager, view);
|
||||
metaballs.draw_in_front(resources, manager, view);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "overlay_next_background.hh"
|
||||
#include "overlay_next_bounds.hh"
|
||||
#include "overlay_next_camera.hh"
|
||||
#include "overlay_next_empty.hh"
|
||||
#include "overlay_next_grid.hh"
|
||||
#include "overlay_next_lattice.hh"
|
||||
@@ -47,11 +48,12 @@ class Instance {
|
||||
struct OverlayLayer {
|
||||
const SelectionType selection_type_;
|
||||
Bounds bounds = {selection_type_};
|
||||
Cameras cameras = {selection_type_};
|
||||
Empties empties = {selection_type_};
|
||||
Lights lights = {selection_type_};
|
||||
} regular{selection_type_}, infront{selection_type_};
|
||||
|
||||
Metaballs metaballs = {selection_type_};
|
||||
Empties empties = {selection_type_};
|
||||
Lattices lattices;
|
||||
Speakers speakers = {selection_type_};
|
||||
Grid grid;
|
||||
|
||||
@@ -87,6 +87,16 @@ class ShapeCache {
|
||||
|
||||
BatchPtr speaker;
|
||||
|
||||
BatchPtr camera_distances;
|
||||
BatchPtr camera_frame;
|
||||
BatchPtr camera_tria_wire;
|
||||
BatchPtr camera_tria;
|
||||
|
||||
BatchPtr camera_volume;
|
||||
BatchPtr camera_volume_wire;
|
||||
|
||||
BatchPtr sphere_low_detail;
|
||||
|
||||
BatchPtr ground_line;
|
||||
|
||||
BatchPtr light_icon_outer_lines;
|
||||
@@ -134,6 +144,7 @@ class ShaderModule {
|
||||
ShaderPtr depth_mesh;
|
||||
ShaderPtr extra_shape;
|
||||
ShaderPtr extra_wire_object;
|
||||
ShaderPtr extra_wire;
|
||||
ShaderPtr extra_ground_line;
|
||||
ShaderPtr lattice_points;
|
||||
ShaderPtr lattice_wire;
|
||||
@@ -290,4 +301,49 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
||||
}
|
||||
};
|
||||
|
||||
struct LineInstanceBuf : private select::SelectBuf {
|
||||
|
||||
StorageVectorBuffer<PointData> data_buf;
|
||||
int color_id = 0;
|
||||
|
||||
LineInstanceBuf(const SelectionType selection_type, const char *name = nullptr)
|
||||
: select::SelectBuf(selection_type), data_buf(name){};
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->select_clear();
|
||||
data_buf.clear();
|
||||
color_id = 0;
|
||||
}
|
||||
|
||||
void append(const float3 &start, const float3 &end, const float4 &color, select::ID select_id)
|
||||
{
|
||||
this->select_append(select_id);
|
||||
data_buf.append({float4{start}, color});
|
||||
data_buf.append({float4{end}, color});
|
||||
}
|
||||
|
||||
void append(const float3 &start, const float3 &end, const int color_id, select::ID select_id)
|
||||
{
|
||||
this->color_id = color_id;
|
||||
this->select_append(select_id);
|
||||
data_buf.append({float4{start}, float4{}});
|
||||
data_buf.append({float4{end}, float4{}});
|
||||
}
|
||||
|
||||
void end_sync(PassSimple::Sub &pass)
|
||||
{
|
||||
if (data_buf.is_empty()) {
|
||||
return;
|
||||
}
|
||||
this->select_bind(pass);
|
||||
data_buf.push_update();
|
||||
pass.bind_ssbo("data_buf", &data_buf);
|
||||
if (color_id) {
|
||||
pass.push_constant("colorid", color_id);
|
||||
}
|
||||
pass.draw_procedural(GPU_PRIM_LINES, 1, data_buf.size());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
@@ -82,6 +82,20 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
extra_wire = selectable_shader("overlay_extra_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.typedef_source("overlay_shader_shared.h");
|
||||
info.storage_buf(0, Qualifier::READ, "PointData", "data_buf[]");
|
||||
info.push_constant(gpu::shader::Type::INT, "colorid");
|
||||
info.define("pos", "data_buf[gl_InstanceID * 2 + gl_VertexID].pos_.xyz");
|
||||
info.define("color", "data_buf[gl_InstanceID * 2 + gl_VertexID].color_");
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info(
|
||||
"draw_view", "draw_modelmat_new", "draw_resource_handle_new", "draw_globals");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
extra_wire_object = selectable_shader(
|
||||
"overlay_extra_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.define("OBJECT_WIRE");
|
||||
|
||||
@@ -16,6 +16,12 @@ struct Vertex {
|
||||
int vclass;
|
||||
};
|
||||
|
||||
struct VertShaded {
|
||||
float3 pos;
|
||||
int v_class;
|
||||
float3 nor;
|
||||
};
|
||||
|
||||
/* Caller gets ownership of the #gpu::VertBuf. */
|
||||
static gpu::VertBuf *vbo_from_vector(const Vector<Vertex> &vector)
|
||||
{
|
||||
@@ -31,6 +37,21 @@ static gpu::VertBuf *vbo_from_vector(const Vector<Vertex> &vector)
|
||||
return vbo;
|
||||
}
|
||||
|
||||
static gpu::VertBuf *vbo_from_vector(Vector<VertShaded> &vector)
|
||||
{
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "vclass", GPU_COMP_I32, 1, GPU_FETCH_INT);
|
||||
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
||||
GPU_vertbuf_data_alloc(*vbo, vector.size());
|
||||
vbo->data<VertShaded>().copy_from(vector);
|
||||
return vbo;
|
||||
}
|
||||
|
||||
enum VertexClass {
|
||||
VCLASS_NONE = 0,
|
||||
|
||||
@@ -74,6 +95,26 @@ static constexpr std::array<uint, 24> bone_box_wire = {
|
||||
0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7,
|
||||
};
|
||||
|
||||
static const std::array<uint3, 12> bone_box_solid_tris{
|
||||
uint3{0, 2, 1}, /* bottom */
|
||||
{0, 3, 2},
|
||||
|
||||
{0, 1, 5}, /* sides */
|
||||
{0, 5, 4},
|
||||
|
||||
{1, 2, 6},
|
||||
{1, 6, 5},
|
||||
|
||||
{2, 3, 7},
|
||||
{2, 7, 6},
|
||||
|
||||
{3, 0, 4},
|
||||
{3, 4, 7},
|
||||
|
||||
{4, 5, 6}, /* top */
|
||||
{4, 6, 7},
|
||||
};
|
||||
|
||||
static void append_line_loop(
|
||||
Vector<Vertex> &dest, Span<float2> verts, float z, int flag, bool dashed = false)
|
||||
{
|
||||
@@ -106,11 +147,14 @@ static float light_distance_z_get(char axis, const bool start)
|
||||
}
|
||||
|
||||
/* A single ring of vertices. */
|
||||
static Vector<float2> ring_vertices(const float radius, const int segments)
|
||||
static Vector<float2> ring_vertices(const float radius,
|
||||
const int segments,
|
||||
const bool half = false)
|
||||
{
|
||||
Vector<float2> verts;
|
||||
for (int i : IndexRange(segments)) {
|
||||
float angle = (2 * math::numbers::pi * i) / segments;
|
||||
const float full = (half ? 1.0f : 2.0f) * math::numbers::pi;
|
||||
for (const int angle_i : IndexRange(segments + (half ? 1 : 0))) {
|
||||
const float angle = (full * angle_i) / segments;
|
||||
verts.append(radius * float2(math::cos(angle), math::sin(angle)));
|
||||
}
|
||||
return verts;
|
||||
@@ -154,6 +198,60 @@ static void light_append_direction_line(Vector<Vertex> &verts)
|
||||
append_line_loop(verts, diamond, zend, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
||||
}
|
||||
|
||||
static VertShaded sphere_lat_lon_vert(const float2 &lat_pt, const float2 &lon_pt)
|
||||
{
|
||||
const float x = lon_pt.y * lat_pt.x;
|
||||
const float y = lon_pt.x;
|
||||
const float z = lon_pt.y * lat_pt.y;
|
||||
return VertShaded{{x, y, z}, VCLASS_EMPTY_SCALED, {x, y, z}};
|
||||
}
|
||||
|
||||
static void append_sphere(Vector<VertShaded> &dest, const eDRWLevelOfDetail level_of_detail)
|
||||
{
|
||||
/* Sphere shape resolution */
|
||||
/* Low */
|
||||
constexpr int drw_sphere_shape_latitude_low = 32;
|
||||
constexpr int drw_sphere_shape_longitude_low = 24;
|
||||
/* Medium */
|
||||
constexpr int drw_sphere_shape_latitude_medium = 64;
|
||||
constexpr int drw_sphere_shape_longitude_medium = 48;
|
||||
/* High */
|
||||
constexpr int drw_sphere_shape_latitude_high = 80;
|
||||
constexpr int drw_sphere_shape_longitude_high = 60;
|
||||
|
||||
BLI_assert(level_of_detail >= DRW_LOD_LOW && level_of_detail < DRW_LOD_MAX);
|
||||
const std::array<Vector<float2>, DRW_LOD_MAX> latitude_rings = {
|
||||
ring_vertices(1.0f, drw_sphere_shape_latitude_low),
|
||||
ring_vertices(1.0f, drw_sphere_shape_latitude_medium),
|
||||
ring_vertices(1.0f, drw_sphere_shape_latitude_high)};
|
||||
const std::array<Vector<float2>, DRW_LOD_MAX> longitude_half_rings = {
|
||||
ring_vertices(1.0f, drw_sphere_shape_longitude_low, true),
|
||||
ring_vertices(1.0f, drw_sphere_shape_longitude_medium, true),
|
||||
ring_vertices(1.0f, drw_sphere_shape_longitude_high, true)};
|
||||
|
||||
const Vector<float2> &latitude_ring = latitude_rings[level_of_detail];
|
||||
const Vector<float2> &longitude_half_ring = longitude_half_rings[level_of_detail];
|
||||
|
||||
for (const int i : latitude_ring.index_range()) {
|
||||
const float2 lat_pt = latitude_ring[i];
|
||||
const float2 next_lat_pt = latitude_ring[(i + 1) % latitude_ring.size()];
|
||||
for (const int j : IndexRange(longitude_half_ring.size() - 1)) {
|
||||
const float2 lon_pt = longitude_half_ring[j];
|
||||
const float2 next_lon_pt = longitude_half_ring[j + 1];
|
||||
if (j != 0) { /* Pole */
|
||||
dest.append(sphere_lat_lon_vert(next_lat_pt, next_lon_pt));
|
||||
dest.append(sphere_lat_lon_vert(next_lat_pt, lon_pt));
|
||||
dest.append(sphere_lat_lon_vert(lat_pt, lon_pt));
|
||||
}
|
||||
if (j != longitude_half_ring.index_range().last(1)) { /* Pole */
|
||||
dest.append(sphere_lat_lon_vert(lat_pt, next_lon_pt));
|
||||
dest.append(sphere_lat_lon_vert(next_lat_pt, next_lon_pt));
|
||||
dest.append(sphere_lat_lon_vert(lat_pt, lon_pt));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapeCache::ShapeCache()
|
||||
{
|
||||
/* quad_wire */
|
||||
@@ -455,6 +553,90 @@ ShapeCache::ShapeCache()
|
||||
speaker = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* camera distances */
|
||||
{
|
||||
const Vector<float2> diamond = ring_vertices(1.5f, 5);
|
||||
const Vector<float2> cross = {{1.0f, 0.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, -1.0f}};
|
||||
|
||||
Vector<Vertex> verts;
|
||||
verts.append({{0.0f, 0.0f, 0.0f}, VCLASS_CAMERA_DIST});
|
||||
verts.append({{0.0f, 0.0f, 1.0f}, VCLASS_CAMERA_DIST});
|
||||
|
||||
append_line_loop(verts, diamond, 0.0f, VCLASS_CAMERA_DIST | VCLASS_SCREENSPACE);
|
||||
append_line_loop(verts, diamond, 1.0f, VCLASS_CAMERA_DIST | VCLASS_SCREENSPACE);
|
||||
|
||||
/* Focus cross */
|
||||
for (const float2 &point : cross) {
|
||||
verts.append({{point.x, point.y, 2.0f}, VCLASS_CAMERA_DIST});
|
||||
}
|
||||
camera_distances = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* camera frame */
|
||||
{
|
||||
const Vector<float2> rect{{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
|
||||
Vector<Vertex> verts;
|
||||
/* Frame */
|
||||
append_line_loop(verts, rect, 1.0f, VCLASS_CAMERA_FRAME);
|
||||
/* Wires to origin. */
|
||||
for (const float2 &point : rect) {
|
||||
verts.append({{point.x, point.y, 1.0f}, VCLASS_CAMERA_FRAME});
|
||||
verts.append({{point.x, point.y, 0.0f}, VCLASS_CAMERA_FRAME});
|
||||
}
|
||||
camera_frame = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* camera tria */
|
||||
{
|
||||
const Vector<float2> triangle = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}};
|
||||
Vector<Vertex> verts(2 * 3);
|
||||
/* Wire */
|
||||
append_line_loop(verts, triangle, 1.0f, VCLASS_CAMERA_FRAME);
|
||||
camera_tria_wire = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
|
||||
verts.clear();
|
||||
/* Triangle */
|
||||
for (const float2 &point : triangle) {
|
||||
verts.append({{point.x, point.y, 1.0f}, VCLASS_CAMERA_FRAME});
|
||||
}
|
||||
camera_tria = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* camera volume */
|
||||
{
|
||||
Vector<Vertex> verts;
|
||||
for (const uint3 &tri : bone_box_solid_tris) {
|
||||
for (const int i : IndexRange(tri.type_length)) {
|
||||
const int v = tri[i];
|
||||
const float x = bone_box_verts[v][2];
|
||||
const float y = bone_box_verts[v][0];
|
||||
const float z = bone_box_verts[v][1];
|
||||
verts.append({{x, y, z}, VCLASS_CAMERA_FRAME | VCLASS_CAMERA_VOLUME});
|
||||
}
|
||||
}
|
||||
camera_volume = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* camera volume wire */
|
||||
{
|
||||
Vector<Vertex> verts(bone_box_wire.size());
|
||||
for (int i : bone_box_wire) {
|
||||
const float x = bone_box_verts[i][2];
|
||||
const float y = bone_box_verts[i][0];
|
||||
const float z = bone_box_verts[i][1];
|
||||
verts.append({{x, y, z}, VCLASS_CAMERA_FRAME | VCLASS_CAMERA_VOLUME});
|
||||
}
|
||||
camera_volume_wire = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* spheres */
|
||||
{
|
||||
Vector<VertShaded> verts;
|
||||
append_sphere(verts, DRW_LOD_LOW);
|
||||
sphere_low_detail = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* ground line */
|
||||
{
|
||||
const Vector<float2> ring = ring_vertices(1.35f, diamond_nsegments);
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef enum OVERLAY_GridBits OVERLAY_GridBits;
|
||||
typedef struct OVERLAY_GridData OVERLAY_GridData;
|
||||
typedef struct ThemeColorData ThemeColorData;
|
||||
typedef struct ExtraInstanceData ExtraInstanceData;
|
||||
typedef struct PointData PointData;
|
||||
#endif
|
||||
|
||||
/* TODO(fclem): Should eventually become OVERLAY_BackgroundType.
|
||||
@@ -231,6 +232,12 @@ struct ExtraInstanceData {
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(ExtraInstanceData, 16)
|
||||
|
||||
struct PointData {
|
||||
float4 pos_;
|
||||
float4 color_;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(PointData, 16)
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user