The goal is to improve clarity and readability, without introducing big design changes. Follows the recent obmat to object_to_world refactor: the similar naming is used, and it is a run-time only rename, meaning, there is no affect on .blend files. This patch does not touch the redundant inversions. Those can be removed in almost (if not all) cases, but it would be the best to do it as a separate change. Differential Revision: https://developer.blender.org/D16367
207 lines
6.3 KiB
C++
207 lines
6.3 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2022 Blender Foundation. */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup draw
|
|
*
|
|
* Component / Object level resources like object attributes, matrices, visibility etc...
|
|
* Each of them are reference by resource index (#ResourceHandle).
|
|
*/
|
|
|
|
#include "BKE_curve.h"
|
|
#include "BKE_duplilist.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_volume.h"
|
|
#include "BLI_hash.h"
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_layer_types.h"
|
|
#include "DNA_meta_types.h"
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "draw_handle.hh"
|
|
#include "draw_manager.hh"
|
|
#include "draw_shader_shared.h"
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name ObjectMatrices
|
|
* \{ */
|
|
|
|
inline void ObjectMatrices::sync(const Object &object)
|
|
{
|
|
model = object.object_to_world;
|
|
model_inverse = object.world_to_object;
|
|
}
|
|
|
|
inline void ObjectMatrices::sync(const float4x4 &model_matrix)
|
|
{
|
|
model = model_matrix;
|
|
model_inverse = model_matrix.inverted();
|
|
}
|
|
|
|
inline std::ostream &operator<<(std::ostream &stream, const ObjectMatrices &matrices)
|
|
{
|
|
stream << "ObjectMatrices(" << std::endl;
|
|
stream << "model=" << matrices.model << ", " << std::endl;
|
|
stream << "model_inverse=" << matrices.model_inverse << ")" << std::endl;
|
|
return stream;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name ObjectInfos
|
|
* \{ */
|
|
|
|
ENUM_OPERATORS(eObjectInfoFlag, OBJECT_NEGATIVE_SCALE)
|
|
|
|
inline void ObjectInfos::sync()
|
|
{
|
|
object_attrs_len = 0;
|
|
object_attrs_offset = 0;
|
|
|
|
flag = eObjectInfoFlag::OBJECT_NO_INFO;
|
|
}
|
|
|
|
inline void ObjectInfos::sync(const blender::draw::ObjectRef ref, bool is_active_object)
|
|
{
|
|
object_attrs_len = 0;
|
|
object_attrs_offset = 0;
|
|
|
|
color = ref.object->color;
|
|
index = ref.object->index;
|
|
SET_FLAG_FROM_TEST(flag, is_active_object, eObjectInfoFlag::OBJECT_ACTIVE);
|
|
SET_FLAG_FROM_TEST(
|
|
flag, ref.object->base_flag & BASE_SELECTED, eObjectInfoFlag::OBJECT_SELECTED);
|
|
SET_FLAG_FROM_TEST(
|
|
flag, ref.object->base_flag & BASE_FROM_DUPLI, eObjectInfoFlag::OBJECT_FROM_DUPLI);
|
|
SET_FLAG_FROM_TEST(
|
|
flag, ref.object->base_flag & BASE_FROM_SET, eObjectInfoFlag::OBJECT_FROM_SET);
|
|
SET_FLAG_FROM_TEST(
|
|
flag, ref.object->transflag & OB_NEG_SCALE, eObjectInfoFlag::OBJECT_NEGATIVE_SCALE);
|
|
|
|
if (ref.dupli_object == nullptr) {
|
|
/* TODO(fclem): this is rather costly to do at draw time. Maybe we can
|
|
* put it in ob->runtime and make depsgraph ensure it is up to date. */
|
|
random = BLI_hash_int_2d(BLI_hash_string(ref.object->id.name + 2), 0) *
|
|
(1.0f / (float)0xFFFFFFFF);
|
|
}
|
|
else {
|
|
random = ref.dupli_object->random_id * (1.0f / (float)0xFFFFFFFF);
|
|
}
|
|
/* Default values. Set if needed. */
|
|
random = 0.0f;
|
|
|
|
if (ref.object->data == nullptr) {
|
|
orco_add = float3(0.0f);
|
|
orco_mul = float3(1.0f);
|
|
return;
|
|
}
|
|
|
|
switch (GS(reinterpret_cast<ID *>(ref.object->data)->name)) {
|
|
case ID_VO: {
|
|
BoundBox &bbox = *BKE_volume_boundbox_get(ref.object);
|
|
orco_add = (float3(bbox.vec[6]) + float3(bbox.vec[0])) * 0.5f; /* Center. */
|
|
orco_mul = float3(bbox.vec[6]) - float3(bbox.vec[0]); /* Size. */
|
|
break;
|
|
}
|
|
case ID_ME: {
|
|
BKE_mesh_texspace_get(static_cast<Mesh *>(ref.object->data), orco_add, orco_mul);
|
|
break;
|
|
}
|
|
case ID_CU_LEGACY: {
|
|
Curve &cu = *static_cast<Curve *>(ref.object->data);
|
|
BKE_curve_texspace_ensure(&cu);
|
|
orco_add = cu.loc;
|
|
orco_mul = cu.size;
|
|
break;
|
|
}
|
|
case ID_MB: {
|
|
MetaBall &mb = *static_cast<MetaBall *>(ref.object->data);
|
|
orco_add = mb.loc;
|
|
orco_mul = mb.size;
|
|
break;
|
|
}
|
|
default:
|
|
orco_add = float3(0.0f);
|
|
orco_mul = float3(1.0f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
inline std::ostream &operator<<(std::ostream &stream, const ObjectInfos &infos)
|
|
{
|
|
stream << "ObjectInfos(";
|
|
if (infos.flag == eObjectInfoFlag::OBJECT_NO_INFO) {
|
|
stream << "skipped)" << std::endl;
|
|
return stream;
|
|
}
|
|
stream << "orco_add=" << infos.orco_add << ", ";
|
|
stream << "orco_mul=" << infos.orco_mul << ", ";
|
|
stream << "color=" << infos.color << ", ";
|
|
stream << "index=" << infos.index << ", ";
|
|
stream << "random=" << infos.random << ", ";
|
|
stream << "flag=" << infos.flag << ")" << std::endl;
|
|
return stream;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name ObjectBounds
|
|
* \{ */
|
|
|
|
inline void ObjectBounds::sync()
|
|
{
|
|
bounding_sphere.w = -1.0f; /* Disable test. */
|
|
}
|
|
|
|
inline void ObjectBounds::sync(Object &ob)
|
|
{
|
|
const BoundBox *bbox = BKE_object_boundbox_get(&ob);
|
|
if (bbox == nullptr) {
|
|
bounding_sphere.w = -1.0f; /* Disable test. */
|
|
return;
|
|
}
|
|
*reinterpret_cast<float3 *>(&bounding_corners[0]) = bbox->vec[0];
|
|
*reinterpret_cast<float3 *>(&bounding_corners[1]) = bbox->vec[4];
|
|
*reinterpret_cast<float3 *>(&bounding_corners[2]) = bbox->vec[3];
|
|
*reinterpret_cast<float3 *>(&bounding_corners[3]) = bbox->vec[1];
|
|
bounding_sphere.w = 0.0f; /* Enable test. */
|
|
}
|
|
|
|
inline void ObjectBounds::sync(const float3 ¢er, const float3 &size)
|
|
{
|
|
*reinterpret_cast<float3 *>(&bounding_corners[0]) = center - size;
|
|
*reinterpret_cast<float3 *>(&bounding_corners[1]) = center + float3(+size.x, -size.y, -size.z);
|
|
*reinterpret_cast<float3 *>(&bounding_corners[2]) = center + float3(-size.x, +size.y, -size.z);
|
|
*reinterpret_cast<float3 *>(&bounding_corners[3]) = center + float3(-size.x, -size.y, +size.z);
|
|
bounding_sphere.w = 0.0; /* Enable test. */
|
|
}
|
|
|
|
inline std::ostream &operator<<(std::ostream &stream, const ObjectBounds &bounds)
|
|
{
|
|
stream << "ObjectBounds(";
|
|
if (bounds.bounding_sphere.w == -1.0f) {
|
|
stream << "skipped)" << std::endl;
|
|
return stream;
|
|
}
|
|
stream << std::endl;
|
|
stream << ".bounding_corners[0]"
|
|
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[0]) << std::endl;
|
|
stream << ".bounding_corners[1]"
|
|
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[1]) << std::endl;
|
|
stream << ".bounding_corners[2]"
|
|
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[2]) << std::endl;
|
|
stream << ".bounding_corners[3]"
|
|
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[3]) << std::endl;
|
|
stream << ".sphere=(pos=" << float3(bounds.bounding_sphere)
|
|
<< ", rad=" << bounds.bounding_sphere.w << std::endl;
|
|
stream << ")" << std::endl;
|
|
return stream;
|
|
}
|
|
|
|
/** \} */
|