Files
test/intern/cycles/scene/mesh.h
Brecht Van Lommel 47f9b7a98e Fix #142022: Cycles undisplaced normal not available
Previously with adaptive subdivision this happened to work with the N
attribute, but that was not meant to be undisplaced. This adds a new
undisplaced_N attribute specifically for this purpose.

For backwards compatibility in Blender 4.5, this also keeps N undisplaced.
But that will be changed in 5.0.

Pull Request: https://projects.blender.org/blender/blender/pulls/142090
2025-07-24 18:16:25 +02:00

247 lines
6.3 KiB
C++

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "graph/node.h"
#include "scene/attribute.h"
#include "scene/geometry.h"
#include "scene/shader.h"
#include "subd/dice.h"
#include "util/array.h"
#include "util/boundbox.h"
#include "util/param.h"
#include "util/set.h"
#include "util/types.h"
#include "util/unique_ptr.h"
CCL_NAMESPACE_BEGIN
class Attribute;
class BVH;
class Device;
class DeviceScene;
class Mesh;
class Progress;
class RenderStats;
class Scene;
class SceneParams;
class AttributeRequest;
struct SubdParams;
class DiagSplit;
/* Mesh */
class Mesh : public Geometry {
protected:
Mesh(const NodeType *node_type_, Type geom_type_);
public:
NODE_DECLARE
/* Mesh Triangle */
struct Triangle {
int v[3];
void bounds_grow(const float3 *verts, BoundBox &bounds) const;
void motion_verts(const float3 *verts,
const float3 *vert_steps,
const size_t num_verts,
const size_t num_steps,
const float time,
float3 r_verts[3]) const;
void verts_for_step(const float3 *verts,
const float3 *vert_steps,
const size_t num_verts,
const size_t num_steps,
const size_t step,
float3 r_verts[3]) const;
float3 compute_normal(const float3 *verts) const;
bool valid(const float3 *verts) const;
};
Triangle get_triangle(const size_t i) const
{
Triangle tri = {{triangles[i * 3 + 0], triangles[i * 3 + 1], triangles[i * 3 + 2]}};
return tri;
}
size_t num_triangles() const
{
return triangles.size() / 3;
}
/* Mesh SubdFace */
struct SubdFace {
int start_corner;
int num_corners;
int shader;
bool smooth;
int ptex_offset;
bool is_quad()
{
return num_corners == 4;
}
float3 normal(const Mesh *mesh) const;
int num_ptex_faces() const
{
return num_corners == 4 ? 1 : num_corners;
}
};
struct SubdEdgeCrease {
int v[2];
float crease;
};
SubdEdgeCrease get_subd_crease(const size_t i) const
{
SubdEdgeCrease s;
s.v[0] = subd_creases_edge[i * 2];
s.v[1] = subd_creases_edge[i * 2 + 1];
s.crease = subd_creases_weight[i];
return s;
}
bool need_tesselation();
enum SubdivisionType {
SUBDIVISION_NONE,
SUBDIVISION_LINEAR,
SUBDIVISION_CATMULL_CLARK,
};
enum SubdivisionBoundaryInterpolation {
SUBDIVISION_BOUNDARY_NONE,
SUBDIVISION_BOUNDARY_EDGE_ONLY,
SUBDIVISION_BOUNDARY_EDGE_AND_CORNER,
};
enum SubdivisionFVarInterpolation {
SUBDIVISION_FVAR_LINEAR_NONE,
SUBDIVISION_FVAR_LINEAR_CORNERS_ONLY,
SUBDIVISION_FVAR_LINEAR_CORNERS_PLUS1,
SUBDIVISION_FVAR_LINEAR_CORNERS_PLUS2,
SUBDIVISION_FVAR_LINEAR_BOUNDARIES,
SUBDIVISION_FVAR_LINEAR_ALL,
};
NODE_SOCKET_API(SubdivisionType, subdivision_type)
NODE_SOCKET_API(SubdivisionBoundaryInterpolation, subdivision_boundary_interpolation)
NODE_SOCKET_API(SubdivisionFVarInterpolation, subdivision_fvar_interpolation)
/* Mesh Data */
NODE_SOCKET_API_ARRAY(array<int>, triangles)
NODE_SOCKET_API_ARRAY(array<float3>, verts)
NODE_SOCKET_API_ARRAY(array<int>, shader)
NODE_SOCKET_API_ARRAY(array<bool>, smooth)
/* SubdFaces */
NODE_SOCKET_API_ARRAY(array<int>, subd_start_corner)
NODE_SOCKET_API_ARRAY(array<int>, subd_num_corners)
NODE_SOCKET_API_ARRAY(array<int>, subd_shader)
NODE_SOCKET_API_ARRAY(array<bool>, subd_smooth)
NODE_SOCKET_API_ARRAY(array<int>, subd_ptex_offset)
NODE_SOCKET_API_ARRAY(array<int>, subd_face_corners)
NODE_SOCKET_API_ARRAY(array<int>, subd_creases_edge)
NODE_SOCKET_API_ARRAY(array<float>, subd_creases_weight)
NODE_SOCKET_API_ARRAY(array<int>, subd_vert_creases)
NODE_SOCKET_API_ARRAY(array<float>, subd_vert_creases_weight)
/* Subdivisions parameters */
NODE_SOCKET_API(float, subd_dicing_rate)
NODE_SOCKET_API(int, subd_max_level)
NODE_SOCKET_API(Transform, subd_objecttoworld)
AttributeSet subd_attributes;
/* BVH */
size_t vert_offset;
size_t face_offset;
size_t corner_offset;
private:
size_t num_subd_added_verts;
size_t num_subd_faces;
friend class BVH2;
friend class BVHBuild;
friend class BVHSpatialSplit;
friend class DiagSplit;
friend class EdgeDice;
friend class GeometryManager;
friend class ObjectManager;
unique_ptr<SubdParams> subd_params;
public:
/* Functions */
Mesh();
void resize_mesh(const int numverts, const int numtris);
void reserve_mesh(const int numverts, const int numtris);
void resize_subd_faces(const int numfaces, const int numcorners);
void reserve_subd_faces(const int numfaces, const int numcorners);
void reserve_subd_creases(const size_t num_creases);
void clear_non_sockets();
void clear(bool preserve_shaders = false) override;
void add_vertex(const float3 P);
void add_vertex_slow(const float3 P);
void add_triangle(const int v0, const int v1, const int v2, const int shader, bool smooth);
void add_subd_face(const int *corners, const int num_corners, const int shader_, bool smooth_);
void add_edge_crease(const int v0, const int v1, const float weight);
void add_vertex_crease(const int v, const float weight);
void copy_center_to_motion_step(const int motion_step);
void compute_bounds() override;
void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
void add_vertex_normals();
void add_undisplaced(Scene *scene);
void update_generated(Scene *scene);
void update_tangents(Scene *scene);
void get_uv_tiles(ustring map, unordered_set<int> &tiles) override;
void pack_shaders(Scene *scene, uint *shader);
void pack_normals(packed_float3 *vnormal);
void pack_verts(packed_float3 *tri_verts, packed_uint3 *tri_vindex);
bool has_motion_blur() const override;
PrimitiveType primitive_type() const override;
void tessellate(SubdParams &params);
SubdFace get_subd_face(const size_t index) const;
size_t get_num_subd_faces() const
{
return num_subd_faces;
}
void set_num_subd_faces(const size_t num_subd_faces_)
{
num_subd_faces = num_subd_faces_;
}
size_t get_num_subd_base_verts() const
{
return verts.size() - num_subd_added_verts;
}
protected:
void clear(bool preserve_shaders, bool preserve_voxel_data);
};
CCL_NAMESPACE_END