The goal is to solve confusion of the "All rights reserved" for licensing
code under an open-source license.
The phrase "All rights reserved" comes from a historical convention that
required this phrase for the copyright protection to apply. This convention
is no longer relevant.
However, even though the phrase has no meaning in establishing the copyright
it has not lost meaning in terms of licensing.
This change makes it so code under the Blender Foundation copyright does
not use "all rights reserved". This is also how the GPL license itself
states how to apply it to the source code:
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software ...
This change does not change copyright notice in cases when the copyright
is dual (BF and an author), or just an author of the code. It also does
mot change copyright which is inherited from NaN Holding BV as it needs
some further investigation about what is the proper way to handle it.
265 lines
7.9 KiB
C++
265 lines
7.9 KiB
C++
// Original code copyright 2013 Pixar.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
// with the following modification; you may not use this file except in
|
|
// compliance with the Apache License and the following modification to it:
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
|
//
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
// the License and to reproduce the content of the NOTICE file.
|
|
//
|
|
// You may obtain a copy of the Apache License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the Apache License with the above modification is
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
// language governing permissions and limitations under the Apache License.
|
|
//
|
|
// Modifications copyright 2021 Blender Foundation
|
|
|
|
#ifndef OPENSUBDIV_PATCH_MAP_H_
|
|
#define OPENSUBDIV_PATCH_MAP_H_
|
|
|
|
#include <opensubdiv/far/patchTable.h>
|
|
|
|
namespace blender {
|
|
namespace opensubdiv {
|
|
|
|
/// \brief An quadtree-based map connecting coarse faces to their sub-patches
|
|
///
|
|
/// PatchTable::PatchArrays contain lists of patches that represent the limit
|
|
/// surface of a mesh, sorted by their topological type. These arrays break the
|
|
/// connection between coarse faces and their sub-patches.
|
|
///
|
|
/// The PatchMap provides a quad-tree based lookup structure that, given a singular
|
|
/// parametric location, can efficiently return a handle to the sub-patch that
|
|
/// contains this location.
|
|
///
|
|
class PatchMap {
|
|
public:
|
|
// Quadtree node with 4 children, tree is just a vector of nodes
|
|
struct QuadNode {
|
|
QuadNode()
|
|
{
|
|
std::memset(this, 0, sizeof(QuadNode));
|
|
}
|
|
|
|
struct Child {
|
|
unsigned int isSet : 1; // true if the child has been set
|
|
unsigned int isLeaf : 1; // true if the child is a QuadNode
|
|
unsigned int index : 30; // child index (either QuadNode or Handle)
|
|
};
|
|
|
|
// sets all the children to point to the patch of given index
|
|
void SetChildren(int index);
|
|
|
|
// sets the child in "quadrant" to point to the node or patch of the given index
|
|
void SetChild(int quadrant, int index, bool isLeaf);
|
|
|
|
Child children[4];
|
|
};
|
|
|
|
typedef OpenSubdiv::Far::PatchTable::PatchHandle Handle;
|
|
|
|
/// \brief Constructor
|
|
///
|
|
/// @param patchTable A valid PatchTable
|
|
///
|
|
PatchMap(OpenSubdiv::Far::PatchTable const &patchTable);
|
|
|
|
/// \brief Returns a handle to the sub-patch of the face at the given (u,v).
|
|
/// Note that the patch face ID corresponds to potentially quadrangulated
|
|
/// face indices and not the base face indices (see Far::PtexIndices for more
|
|
/// details).
|
|
///
|
|
/// @param patchFaceId The index of the patch (Ptex) face
|
|
///
|
|
/// @param u Local u parameter
|
|
///
|
|
/// @param v Local v parameter
|
|
///
|
|
/// @return A patch handle or 0 if the face is not supported (index
|
|
/// out of bounds) or is tagged as a hole
|
|
///
|
|
Handle const *FindPatch(int patchFaceId, double u, double v) const;
|
|
|
|
int getMinPatchFace() const
|
|
{
|
|
return _minPatchFace;
|
|
}
|
|
|
|
int getMaxPatchFace() const
|
|
{
|
|
return _maxPatchFace;
|
|
}
|
|
|
|
int getMaxDepth() const
|
|
{
|
|
return _maxDepth;
|
|
}
|
|
|
|
bool getPatchesAreTriangular() const
|
|
{
|
|
return _patchesAreTriangular;
|
|
}
|
|
|
|
const std::vector<Handle> &getHandles()
|
|
{
|
|
return _handles;
|
|
}
|
|
|
|
const std::vector<QuadNode> &nodes()
|
|
{
|
|
return _quadtree;
|
|
}
|
|
|
|
private:
|
|
void initializeHandles(OpenSubdiv::Far::PatchTable const &patchTable);
|
|
void initializeQuadtree(OpenSubdiv::Far::PatchTable const &patchTable);
|
|
|
|
typedef std::vector<QuadNode> QuadTree;
|
|
|
|
// Internal methods supporting quadtree construction and queries
|
|
void assignRootNode(QuadNode *node, int index);
|
|
QuadNode *assignLeafOrChildNode(QuadNode *node, bool isLeaf, int quadrant, int index);
|
|
|
|
template<class T> static int transformUVToQuadQuadrant(T const &median, T &u, T &v);
|
|
template<class T>
|
|
static int transformUVToTriQuadrant(T const &median, T &u, T &v, bool &rotated);
|
|
|
|
private:
|
|
bool _patchesAreTriangular; // tri and quad assembly and search requirements differ
|
|
|
|
int _minPatchFace; // minimum patch face index supported by the map
|
|
int _maxPatchFace; // maximum patch face index supported by the map
|
|
int _maxDepth; // maximum depth of a patch in the tree
|
|
|
|
std::vector<Handle> _handles; // all the patches in the PatchTable
|
|
std::vector<QuadNode> _quadtree; // quadtree nodes
|
|
};
|
|
|
|
//
|
|
// Given a median value for both U and V, these methods transform a (u,v) pair
|
|
// into the quadrant that contains them and returns the quadrant index.
|
|
//
|
|
// Quadrant indexing for tri and quad patches -- consistent with PatchParam's
|
|
// usage of UV bits:
|
|
//
|
|
// (0,1) o-----o-----o (1,1) (0,1) o (1,0) o-----o-----o (0,0)
|
|
// | | | |\ \ 1 |\ 0 |
|
|
// | 2 | 3 | | \ \ | \ |
|
|
// | | | | 2 \ \| 3 \|
|
|
// o-----o-----o o-----o o-----o
|
|
// | | | |\ 3 |\ \ 2 |
|
|
// | 0 | 1 | | \ | \ \ |
|
|
// | | | | 0 \| 1 \ \|
|
|
// (0,0) o-----o-----o (1,0) (0,0) o-----o-----o (1,0) o (0,1)
|
|
//
|
|
// The triangular case also takes and returns/affects the rotation of the
|
|
// quadrant being searched and identified (quadrant 3 imparts a rotation).
|
|
//
|
|
template<class T> inline int PatchMap::transformUVToQuadQuadrant(T const &median, T &u, T &v)
|
|
{
|
|
|
|
int uHalf = (u >= median);
|
|
if (uHalf)
|
|
u -= median;
|
|
|
|
int vHalf = (v >= median);
|
|
if (vHalf)
|
|
v -= median;
|
|
|
|
return (vHalf << 1) | uHalf;
|
|
}
|
|
|
|
template<class T>
|
|
int inline PatchMap::transformUVToTriQuadrant(T const &median, T &u, T &v, bool &rotated)
|
|
{
|
|
|
|
if (!rotated) {
|
|
if (u >= median) {
|
|
u -= median;
|
|
return 1;
|
|
}
|
|
if (v >= median) {
|
|
v -= median;
|
|
return 2;
|
|
}
|
|
if ((u + v) >= median) {
|
|
rotated = true;
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
else {
|
|
if (u < median) {
|
|
v -= median;
|
|
return 1;
|
|
}
|
|
if (v < median) {
|
|
u -= median;
|
|
return 2;
|
|
}
|
|
u -= median;
|
|
v -= median;
|
|
if ((u + v) < median) {
|
|
rotated = false;
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/// Returns a handle to the sub-patch of the face at the given (u,v).
|
|
inline PatchMap::Handle const *PatchMap::FindPatch(int faceid, double u, double v) const
|
|
{
|
|
|
|
//
|
|
// Reject patch faces not supported by this map, or those corresponding
|
|
// to holes or otherwise unassigned (the root node for a patch will
|
|
// have all or no quadrants set):
|
|
//
|
|
if ((faceid < _minPatchFace) || (faceid > _maxPatchFace))
|
|
return 0;
|
|
|
|
QuadNode const *node = &_quadtree[faceid - _minPatchFace];
|
|
|
|
if (!node->children[0].isSet)
|
|
return 0;
|
|
|
|
//
|
|
// Search the tree for the sub-patch containing the given (u,v)
|
|
//
|
|
assert((u >= 0.0) && (u <= 1.0) && (v >= 0.0) && (v <= 1.0));
|
|
|
|
double median = 0.5;
|
|
bool triRotated = false;
|
|
|
|
for (int depth = 0; depth <= _maxDepth; ++depth, median *= 0.5) {
|
|
|
|
int quadrant = _patchesAreTriangular ? transformUVToTriQuadrant(median, u, v, triRotated) :
|
|
transformUVToQuadQuadrant(median, u, v);
|
|
|
|
// holes should have been rejected at the root node of the face
|
|
assert(node->children[quadrant].isSet);
|
|
|
|
if (node->children[quadrant].isLeaf) {
|
|
return &_handles[node->children[quadrant].index];
|
|
}
|
|
else {
|
|
node = &_quadtree[node->children[quadrant].index];
|
|
}
|
|
}
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
} // namespace opensubdiv
|
|
} // namespace blender
|
|
|
|
#endif // OPENSUBDIV_PATCH_MAP_H_
|