blender/intern/cycles/subd/osd.h
Brecht Van Lommel 0baa98866c Refactor: Cycles: Mesh positions include motion, store kernel attribute
Motion is now part of the position attribute. On the kernel side, this
position is now stored as an attribute as well, replacing the previous
motion only attribute.

Pull Request: https://projects.blender.org/blender/blender/pulls/158728
2026-05-27 22:01:25 +02:00

104 lines
2.4 KiB
C++

/* SPDX-FileCopyrightText: 2011-2024 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#ifdef WITH_OPENSUBDIV
/* OpenSubdiv headers use M_PI. */
# if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
# define _USE_MATH_DEFINES
# endif
# include <opensubdiv/far/patchMap.h>
# include <opensubdiv/far/patchTableFactory.h>
# include <opensubdiv/far/primvarRefiner.h>
# include <opensubdiv/far/topologyRefinerFactory.h>
# include "subd/patch.h"
# include "util/types.h"
# include "util/unique_ptr.h"
# include "util/vector.h"
CCL_NAMESPACE_BEGIN
/* Directly use some OpenSubdiv namespaces for brevity. */
namespace Far = OpenSubdiv::Far;
namespace Sdc = OpenSubdiv::Sdc;
class Attribute;
class Mesh;
/* OpenSubdiv interface for vertex and attribute values. */
template<typename T> struct OsdValue {
T value;
OsdValue() = default;
void Clear(void *unused = nullptr)
{
(void)unused;
memset((void *)&value, 0, sizeof(T));
}
void AddWithWeight(OsdValue<T> const &src, float weight)
{
if constexpr (std::is_same_v<T, packed_float3>) {
value = float3(value) + float3(src.value) * weight;
}
else {
value += src.value * weight;
}
}
};
/* Wrapper around Mesh for TopologyRefinerFactory. */
class OsdMesh {
public:
/* Face-varying attribute that requires merging of corners with the same value, typically a UV
* map. The resulting topology after merging is stored in a topology refiner fvar channel. The
* merged attribute values are stored here, in a generic buffer used for different data types. */
struct MergedFVar {
const Attribute &attr;
int channel = -1;
vector<char> values;
};
Mesh &mesh;
vector<MergedFVar> merged_fvars;
explicit OsdMesh(Mesh &mesh) : mesh(mesh) {}
Sdc::Options sdc_options();
bool use_smooth_fvar(const Attribute &attr) const;
bool use_smooth_fvar() const;
};
/* OpenSubdiv refiner and patch data structures. */
struct OsdData {
unique_ptr<Far::TopologyRefiner> refiner;
unique_ptr<Far::PatchTable> patch_table;
unique_ptr<Far::PatchMap> patch_map;
vector<OsdValue<packed_float3>> refined_verts;
void build(OsdMesh &osd_mesh);
};
/* Patch with OpenSubdiv evaluation. */
struct OsdPatch final : Patch {
OsdData &osd_data;
explicit OsdPatch(OsdData &data) : osd_data(data) {}
void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, const float u, const float v)
const override;
};
CCL_NAMESPACE_END
#endif