The main idea is to switch Bake from Multires from legacy DerivedMesh to Subdiv. On the development side of things this change removes a lot of code, also making it easier easier to rework CustomData and related topics, without being pulled down by the DerivedMesh. On the user level switch to Subdiv means: - Much more closer handling of the multi-resolution data: the derived mesh code was close, but not exactly the same when it comes to the final look of mesh. Other than less obvious cases (like old DerivedMesh approach doing recursive subdivision instead of pushing subdivided vertices on the limit surface) there are more obvious ones like difference in edge creases, and non-supported vertex creases by the DerivedMesh. - UV interpolation is done correctly now when baking to non-base level (baking to multi-resolution level >= 1). Previously in this case the old derived mesh interpolation was used to interpolate face-varying data, which gives different results from the OpenSubdiv interpolation. - Ngon faces are properly supported now. A possible remaining issue is the fact that getting normal from CCG always uses smooth interpolation. Based on the code it always has been the case, so while it is something to look into it might be considered a separate topic to dig into.
116 lines
3.1 KiB
C++
116 lines
3.1 KiB
C++
/* SPDX-FileCopyrightText: 2012 by Nicholas Bishop. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup bke
|
|
*/
|
|
|
|
#include "BLI_assert.h"
|
|
#include "BLI_math_vector_types.hh"
|
|
|
|
struct CCGSubSurf;
|
|
|
|
/* Each CCGElem is CCGSubSurf's representation of a subdivided
|
|
* vertex. All CCGElems in a particular CCGSubSurf have the same
|
|
* layout, but the layout can vary from one CCGSubSurf to another. For
|
|
* this reason, CCGElem is presented as an opaque pointer, and
|
|
* elements should always be accompanied by a CCGKey, which provides
|
|
* the necessary offsets to access components of a CCGElem.
|
|
*/
|
|
struct CCGElem;
|
|
|
|
struct CCGKey {
|
|
int level;
|
|
|
|
/* number of bytes in each element (one float per layer, plus
|
|
* three floats for normals if enabled) */
|
|
int elem_size;
|
|
|
|
/* number of elements along each side of grid */
|
|
int grid_size;
|
|
/* number of elements in the grid (grid size squared) */
|
|
int grid_area;
|
|
/* number of bytes in each grid (grid_area * elem_size) */
|
|
int grid_bytes;
|
|
|
|
/* currently always the last three floats, unless normals are
|
|
* disabled */
|
|
int normal_offset;
|
|
|
|
/* offset in bytes of mask value; only valid if 'has_mask' is
|
|
* true */
|
|
int mask_offset;
|
|
|
|
int has_normals;
|
|
int has_mask;
|
|
};
|
|
|
|
inline blender::float3 &CCG_elem_co(const CCGKey & /*key*/, CCGElem *elem)
|
|
{
|
|
return *reinterpret_cast<blender::float3 *>(elem);
|
|
}
|
|
|
|
inline blender::float3 &CCG_elem_no(const CCGKey &key, CCGElem *elem)
|
|
{
|
|
BLI_assert(key.has_normals);
|
|
return *reinterpret_cast<blender::float3 *>(reinterpret_cast<char *>(elem) + key.normal_offset);
|
|
}
|
|
|
|
inline float &CCG_elem_mask(const CCGKey &key, CCGElem *elem)
|
|
{
|
|
BLI_assert(key.has_mask);
|
|
return *reinterpret_cast<float *>(reinterpret_cast<char *>(elem) + (key.mask_offset));
|
|
}
|
|
|
|
inline CCGElem *CCG_elem_offset(const CCGKey &key, CCGElem *elem, int offset)
|
|
{
|
|
return reinterpret_cast<CCGElem *>((reinterpret_cast<char *>(elem)) + key.elem_size * offset);
|
|
}
|
|
|
|
inline int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
|
|
{
|
|
return y * grid_size + x;
|
|
}
|
|
|
|
inline CCGElem *CCG_grid_elem(const CCGKey &key, CCGElem *elem, int x, int y)
|
|
{
|
|
// BLI_assert(x < key.grid_size && y < key.grid_size);
|
|
return CCG_elem_offset(key, elem, CCG_grid_xy_to_index(key.grid_size, x, y));
|
|
}
|
|
|
|
inline blender::float3 &CCG_grid_elem_co(const CCGKey &key, CCGElem *elem, int x, int y)
|
|
{
|
|
return CCG_elem_co(key, CCG_grid_elem(key, elem, x, y));
|
|
}
|
|
|
|
inline blender::float3 &CCG_grid_elem_no(const CCGKey &key, CCGElem *elem, int x, int y)
|
|
{
|
|
return CCG_elem_no(key, CCG_grid_elem(key, elem, x, y));
|
|
}
|
|
|
|
inline float &CCG_grid_elem_mask(const CCGKey &key, CCGElem *elem, int x, int y)
|
|
{
|
|
return CCG_elem_mask(key, CCG_grid_elem(key, elem, x, y));
|
|
}
|
|
|
|
inline blender::float3 &CCG_elem_offset_co(const CCGKey &key, CCGElem *elem, int offset)
|
|
{
|
|
return CCG_elem_co(key, CCG_elem_offset(key, elem, offset));
|
|
}
|
|
|
|
inline int CCG_grid_size(const int level)
|
|
{
|
|
BLI_assert(level > 0);
|
|
return (1 << (level - 1)) + 1;
|
|
}
|
|
|
|
inline int CCG_grid_factor(int low_level, int high_level)
|
|
{
|
|
BLI_assert(low_level > 0 && high_level > 0);
|
|
BLI_assert(low_level <= high_level);
|
|
return 1 << (high_level - low_level);
|
|
}
|