/* 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; namespace blender { 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 float3 &CCG_elem_co(const CCGKey & /*key*/, CCGElem *elem) { return *reinterpret_cast(elem); } inline float3 &CCG_elem_no(const CCGKey &key, CCGElem *elem) { BLI_assert(key.has_normals); return *reinterpret_cast(reinterpret_cast(elem) + key.normal_offset); } inline float &CCG_elem_mask(const CCGKey &key, CCGElem *elem) { BLI_assert(key.has_mask); return *reinterpret_cast(reinterpret_cast(elem) + (key.mask_offset)); } inline CCGElem *CCG_elem_offset(const CCGKey &key, CCGElem *elem, int offset) { return reinterpret_cast((reinterpret_cast(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 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 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 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); } } // namespace blender