Add Chromium-only Blender WebEngine parity work
This commit is contained in:
37
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/CMakeLists.txt
vendored
Normal file
37
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright 2021 Pixar
|
||||
#
|
||||
# Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
# https://opensubdiv.org/license.
|
||||
#
|
||||
|
||||
include_directories("${OPENSUBDIV_INCLUDE_DIR}")
|
||||
|
||||
set(SOURCE_FILES
|
||||
main.cpp
|
||||
bfrSurfaceEvaluator.cpp
|
||||
farPatchEvaluator.cpp
|
||||
)
|
||||
|
||||
set(PLATFORM_LIBRARIES
|
||||
"${OSD_LINK_TARGET}"
|
||||
)
|
||||
|
||||
osd_add_executable(bfr_evaluate "regression"
|
||||
${SOURCE_FILES}
|
||||
$<TARGET_OBJECTS:sdc_obj>
|
||||
$<TARGET_OBJECTS:vtr_obj>
|
||||
$<TARGET_OBJECTS:far_obj>
|
||||
$<TARGET_OBJECTS:bfr_obj>
|
||||
$<TARGET_OBJECTS:regression_common_obj>
|
||||
)
|
||||
|
||||
install(TARGETS bfr_evaluate DESTINATION "${CMAKE_BINDIR_BASE}")
|
||||
|
||||
add_test(bfr_evaluate_pos ${EXECUTABLE_OUTPUT_PATH}/bfr_evaluate
|
||||
-all -silent -l 3 -pass 2 -d1)
|
||||
add_test(bfr_evaluate_uv1 ${EXECUTABLE_OUTPUT_PATH}/bfr_evaluate
|
||||
-all -silent -l 3 -pass 0 -skippos -uv -uvint 1)
|
||||
add_test(bfr_evaluate_uv5 ${EXECUTABLE_OUTPUT_PATH}/bfr_evaluate
|
||||
-all -silent -l 3 -pass 0 -skippos -uv -uvint 5)
|
||||
|
||||
191
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/bfrSurfaceEvaluator.cpp
vendored
Normal file
191
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/bfrSurfaceEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "bfrSurfaceEvaluator.h"
|
||||
|
||||
|
||||
template <typename REAL>
|
||||
BfrSurfaceEvaluator<REAL>::BfrSurfaceEvaluator(
|
||||
Far::TopologyRefiner const & baseMesh,
|
||||
Vec3Vector const & basePos,
|
||||
Vec3Vector const & baseUVs,
|
||||
FactoryOptions const & factoryOptions) :
|
||||
_baseMesh(baseMesh),
|
||||
_baseMeshPos(basePos),
|
||||
_baseMeshUVs(baseUVs),
|
||||
_factory(baseMesh, factoryOptions) {
|
||||
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
bool
|
||||
BfrSurfaceEvaluator<REAL>::FaceHasLimit(IndexType baseFace) const {
|
||||
|
||||
return _factory.FaceHasLimitSurface(baseFace);
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
void
|
||||
BfrSurfaceEvaluator<REAL>::Evaluate(IndexType baseFace,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const {
|
||||
|
||||
// Allocate vectors for the properties to be evaluated:
|
||||
int numCoords = (int) tessCoords.size() / 2;
|
||||
|
||||
results.Resize(numCoords);
|
||||
|
||||
// Create the Surfaces for position and UV (optional) and assert if
|
||||
// not valid, since a limit surface is expected here. (Note we may
|
||||
// create the position surface but not actually evaluate it.)
|
||||
SurfaceType pSurface;
|
||||
SurfaceType uvSurface;
|
||||
|
||||
// Figure out how to get a command line arg here to run both
|
||||
bool initSeparate = false;
|
||||
if (initSeparate || !results.evalUV) {
|
||||
_factory.InitVertexSurface(baseFace, &pSurface);
|
||||
if (results.evalUV) {
|
||||
_factory.InitFaceVaryingSurface(baseFace, &uvSurface);
|
||||
}
|
||||
} else {
|
||||
_factory.InitSurfaces(baseFace, &pSurface, &uvSurface);
|
||||
}
|
||||
|
||||
assert(pSurface.IsValid());
|
||||
assert(uvSurface.IsValid() == results.evalUV);
|
||||
|
||||
// Evaluate directly or using stencils:
|
||||
if (results.useStencils) {
|
||||
evaluateByStencils(pSurface, uvSurface, tessCoords, results);
|
||||
} else {
|
||||
evaluateDirectly(pSurface, uvSurface, tessCoords, results);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
void
|
||||
BfrSurfaceEvaluator<REAL>::evaluateDirectly(
|
||||
SurfaceType const & pSurface, SurfaceType const & uvSurface,
|
||||
TessCoordVector const & tessCoords, EvalResults<REAL> & results) const {
|
||||
|
||||
int numCoords = (int) tessCoords.size() / 2;
|
||||
|
||||
if (results.evalPosition) {
|
||||
Vec3Vector baseFacePos(pSurface.GetNumPatchPoints());
|
||||
|
||||
REAL const * meshPoints = &_baseMeshPos[0][0];
|
||||
REAL * patchPoints = &baseFacePos[0][0];
|
||||
|
||||
pSurface.PreparePatchPoints(meshPoints, 3, patchPoints, 3);
|
||||
|
||||
REAL const * st = &tessCoords[0];
|
||||
for (int i = 0; i < numCoords; ++i, st += 2) {
|
||||
if (!results.eval1stDeriv) {
|
||||
pSurface.Evaluate(st, patchPoints, 3, &results.p[i][0]);
|
||||
} else if (!results.eval2ndDeriv) {
|
||||
pSurface.Evaluate(st, patchPoints, 3,
|
||||
&results.p[i][0], &results.du[i][0], &results.dv[i][0]);
|
||||
} else {
|
||||
pSurface.Evaluate(st, patchPoints, 3,
|
||||
&results.p[i][0], &results.du[i][0], &results.dv[i][0],
|
||||
&results.duu[i][0], &results.duv[i][0], &results.dvv[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results.evalUV) {
|
||||
Vec3Vector baseFaceUVs(uvSurface.GetNumPatchPoints());
|
||||
|
||||
REAL const * meshPoints = &_baseMeshUVs[0][0];
|
||||
REAL * patchPoints = &baseFaceUVs[0][0];
|
||||
|
||||
uvSurface.PreparePatchPoints(meshPoints, 3, patchPoints, 3);
|
||||
|
||||
REAL const * st = &tessCoords[0];
|
||||
for (int i = 0; i < numCoords; ++i, st += 2) {
|
||||
uvSurface.Evaluate(st, patchPoints, 3, &results.uv[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
void
|
||||
BfrSurfaceEvaluator<REAL>::evaluateByStencils(
|
||||
SurfaceType const & pSurface, SurfaceType const & uvSurface,
|
||||
TessCoordVector const & tessCoords, EvalResults<REAL> & results) const {
|
||||
|
||||
std::vector<REAL> stencilWeights;
|
||||
|
||||
int numCoords = (int) tessCoords.size() / 2;
|
||||
|
||||
if (results.evalPosition) {
|
||||
stencilWeights.resize(6 * pSurface.GetNumControlPoints());
|
||||
|
||||
REAL * sP = &stencilWeights[0];
|
||||
REAL * sDu = sP + pSurface.GetNumControlPoints();
|
||||
REAL * sDv = sDu + pSurface.GetNumControlPoints();
|
||||
REAL * sDuu = sDv + pSurface.GetNumControlPoints();
|
||||
REAL * sDuv = sDuu + pSurface.GetNumControlPoints();
|
||||
REAL * sDvv = sDuv + pSurface.GetNumControlPoints();
|
||||
|
||||
REAL const * st = &tessCoords[0];
|
||||
for (int i = 0; i < numCoords; ++i, st += 2) {
|
||||
REAL const * meshPos = &_baseMeshPos[0][0];
|
||||
|
||||
if (!results.eval1stDeriv) {
|
||||
pSurface.EvaluateStencil(st, &sP[0]);
|
||||
} else if (!results.eval2ndDeriv) {
|
||||
pSurface.EvaluateStencil(st, &sP[0], &sDu[0], &sDv[0]);
|
||||
} else {
|
||||
pSurface.EvaluateStencil(st, &sP[0], &sDu[0], &sDv[0],
|
||||
&sDuu[0], &sDuv[0], &sDvv[0]);
|
||||
}
|
||||
|
||||
if (results.evalPosition) {
|
||||
pSurface.ApplyStencilFromMesh(&sP[0], meshPos, 3,
|
||||
&results.p[i][0]);
|
||||
}
|
||||
if (results.eval1stDeriv) {
|
||||
pSurface.ApplyStencilFromMesh(&sDu[0], meshPos, 3,
|
||||
&results.du[i][0]);
|
||||
pSurface.ApplyStencilFromMesh(&sDv[0], meshPos, 3,
|
||||
&results.dv[i][0]);
|
||||
}
|
||||
if (results.eval2ndDeriv) {
|
||||
pSurface.ApplyStencilFromMesh(&sDuu[0], meshPos, 3,
|
||||
&results.duu[i][0]);
|
||||
pSurface.ApplyStencilFromMesh(&sDuv[0], meshPos, 3,
|
||||
&results.duv[i][0]);
|
||||
pSurface.ApplyStencilFromMesh(&sDvv[0], meshPos, 3,
|
||||
&results.dvv[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results.evalUV) {
|
||||
REAL const * meshUVs = &_baseMeshUVs[0][0];
|
||||
|
||||
stencilWeights.resize(uvSurface.GetNumControlPoints());
|
||||
|
||||
REAL * sUV = &stencilWeights[0];
|
||||
|
||||
REAL const * st = &tessCoords[0];
|
||||
for (int i = 0; i < numCoords; ++i, st += 2) {
|
||||
uvSurface.EvaluateStencil(st, &sUV[0]);
|
||||
|
||||
uvSurface.ApplyStencilFromMesh(&sUV[0], meshUVs, 3,
|
||||
&results.uv[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Explicit instantiation for float and double:
|
||||
//
|
||||
template class BfrSurfaceEvaluator<float>;
|
||||
template class BfrSurfaceEvaluator<double>;
|
||||
|
||||
65
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/bfrSurfaceEvaluator.h
vendored
Normal file
65
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/bfrSurfaceEvaluator.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "./types.h"
|
||||
|
||||
#include <opensubdiv/far/topologyRefiner.h>
|
||||
|
||||
#include <opensubdiv/bfr/refinerSurfaceFactory.h>
|
||||
#include <opensubdiv/bfr/tessellation.h>
|
||||
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
|
||||
|
||||
|
||||
template <typename REAL>
|
||||
class BfrSurfaceEvaluator {
|
||||
public:
|
||||
typedef Bfr::Surface<REAL> SurfaceType;
|
||||
|
||||
typedef Bfr::RefinerSurfaceFactory<> SurfaceFactory;
|
||||
typedef Bfr::SurfaceFactory::Options FactoryOptions;
|
||||
typedef Bfr::SurfaceFactory::Index IndexType;
|
||||
|
||||
typedef std::vector<REAL> TessCoordVector;
|
||||
|
||||
typedef std::vector< Vec3<REAL> > Vec3Vector;
|
||||
|
||||
public:
|
||||
BfrSurfaceEvaluator(Far::TopologyRefiner const & baseMesh,
|
||||
Vec3Vector const & basePos,
|
||||
Vec3Vector const & baseUVs,
|
||||
FactoryOptions const & factoryOptions);
|
||||
~BfrSurfaceEvaluator() { }
|
||||
|
||||
public:
|
||||
bool FaceHasLimit(IndexType baseFace) const;
|
||||
|
||||
void Evaluate(IndexType baseface,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const;
|
||||
|
||||
private:
|
||||
void evaluateDirectly(SurfaceType const & posSurface,
|
||||
SurfaceType const & uvSurface,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const;
|
||||
|
||||
void evaluateByStencils(SurfaceType const & posSurface,
|
||||
SurfaceType const & uvSurface,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const;
|
||||
|
||||
private:
|
||||
Far::TopologyRefiner const & _baseMesh;
|
||||
Vec3Vector const & _baseMeshPos;
|
||||
Vec3Vector const & _baseMeshUVs;
|
||||
|
||||
SurfaceFactory _factory;
|
||||
};
|
||||
274
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/farPatchEvaluator.cpp
vendored
Normal file
274
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/farPatchEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "farPatchEvaluator.h"
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/topologyDescriptor.h>
|
||||
#include <opensubdiv/far/primvarRefiner.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
|
||||
|
||||
template <typename REAL>
|
||||
FarPatchEvaluator<REAL>::FarPatchEvaluator(
|
||||
Far::TopologyRefiner const & baseMesh,
|
||||
Vec3RealVector const & basePos,
|
||||
Vec3RealVector const & baseUVs,
|
||||
BfrSurfaceOptions const & bfrSurfaceOptions) :
|
||||
_baseMesh(baseMesh),
|
||||
_baseMeshPos(basePos),
|
||||
_baseMeshUVs(baseUVs) {
|
||||
|
||||
//
|
||||
// Initialize simple members first:
|
||||
//
|
||||
_regFaceSize = Sdc::SchemeTypeTraits::GetRegularFaceSize(
|
||||
baseMesh.GetSchemeType());
|
||||
|
||||
//
|
||||
// Declare options to use in construction of PatchTable et al:
|
||||
//
|
||||
int primaryLevel = bfrSurfaceOptions.GetApproxLevelSharp();
|
||||
int secondaryLevel = bfrSurfaceOptions.GetApproxLevelSmooth();
|
||||
|
||||
Far::PatchTableFactory::Options patchOptions(primaryLevel);
|
||||
patchOptions.SetPatchPrecision<REAL>();
|
||||
patchOptions.SetFVarPatchPrecision<REAL>();
|
||||
patchOptions.useInfSharpPatch = true;
|
||||
patchOptions.generateLegacySharpCornerPatches = false;
|
||||
patchOptions.shareEndCapPatchPoints = false;
|
||||
patchOptions.endCapType =
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
|
||||
|
||||
bool hasUVs = !baseUVs.empty();
|
||||
int fvarChannel = 0;
|
||||
|
||||
patchOptions.generateFVarTables = hasUVs;
|
||||
patchOptions.numFVarChannels = hasUVs ? 1 : 0;
|
||||
patchOptions.fvarChannelIndices = &fvarChannel;
|
||||
patchOptions.generateFVarLegacyLinearPatches = false;
|
||||
|
||||
patchOptions.generateVaryingTables = false;
|
||||
|
||||
Far::TopologyRefiner::AdaptiveOptions refineOptions =
|
||||
patchOptions.GetRefineAdaptiveOptions();
|
||||
refineOptions.SetIsolationLevel(primaryLevel);
|
||||
refineOptions.SetSecondaryLevel(secondaryLevel);
|
||||
|
||||
//
|
||||
// Create a TopologyRefiner (sharing the base) to adaptively refine
|
||||
// and create the associated PatchTable:
|
||||
//
|
||||
Far::TopologyRefiner *patchRefiner =
|
||||
Far::TopologyRefinerFactory<Far::TopologyDescriptor>::Create(
|
||||
baseMesh);
|
||||
|
||||
patchRefiner->RefineAdaptive(refineOptions);
|
||||
|
||||
_patchTable = Far::PatchTableFactory::Create(*patchRefiner, patchOptions);
|
||||
|
||||
_patchFaces = new Far::PtexIndices(baseMesh);
|
||||
|
||||
_patchMap = new Far::PatchMap(*_patchTable);
|
||||
|
||||
|
||||
//
|
||||
// Declare buffers/vectors for refined/patch points:
|
||||
//
|
||||
Far::TopologyLevel const & baseLevel = baseMesh.GetLevel(0);
|
||||
|
||||
int numBasePoints = baseLevel.GetNumVertices();
|
||||
int numRefinedPoints = patchRefiner->GetNumVerticesTotal() - numBasePoints;
|
||||
int numLocalPoints = _patchTable->GetNumLocalPoints();
|
||||
|
||||
_patchPos.resize(numBasePoints + numRefinedPoints + numLocalPoints);
|
||||
|
||||
std::memcpy(&_patchPos[0], &basePos[0], numBasePoints * sizeof(Vec3Real));
|
||||
|
||||
//
|
||||
// Similarly declare buffers/vectors for refined/patch UVs:
|
||||
//
|
||||
int numBaseUVs = 0;
|
||||
int numRefinedUVs = 0;
|
||||
int numLocalUVs = 0;
|
||||
|
||||
if (hasUVs) {
|
||||
numBaseUVs = baseLevel.GetNumFVarValues();
|
||||
numRefinedUVs = patchRefiner->GetNumFVarValuesTotal() - numBaseUVs;
|
||||
numLocalUVs = _patchTable->GetNumLocalPointsFaceVarying();
|
||||
|
||||
_patchUVs.resize(numBaseUVs + numRefinedUVs + numLocalUVs);
|
||||
|
||||
std::memcpy(&_patchUVs[0], &baseUVs[0], numBaseUVs * sizeof(Vec3Real));
|
||||
}
|
||||
|
||||
//
|
||||
// Compute refined and local patch points and UVs:
|
||||
//
|
||||
if (numRefinedPoints) {
|
||||
Far::PrimvarRefinerReal<REAL> primvarRefiner(*patchRefiner);
|
||||
|
||||
Vec3Real const * srcP = &_patchPos[0];
|
||||
Vec3Real * dstP = &_patchPos[numBasePoints];
|
||||
|
||||
Vec3Real const * srcUV = hasUVs ? &_patchUVs[0] : 0;
|
||||
Vec3Real * dstUV = hasUVs ? &_patchUVs[numBaseUVs] : 0;
|
||||
|
||||
for (int level = 1; level < patchRefiner->GetNumLevels(); ++level) {
|
||||
primvarRefiner.Interpolate(level, srcP, dstP);
|
||||
srcP = dstP;
|
||||
dstP += patchRefiner->GetLevel(level).GetNumVertices();
|
||||
|
||||
if (hasUVs) {
|
||||
primvarRefiner.InterpolateFaceVarying(level, srcUV, dstUV);
|
||||
srcUV = dstUV;
|
||||
dstUV += patchRefiner->GetLevel(level).GetNumFVarValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numLocalPoints) {
|
||||
_patchTable->GetLocalPointStencilTable<REAL>()->UpdateValues(
|
||||
&_patchPos[0], &_patchPos[numBasePoints + numRefinedPoints]);
|
||||
}
|
||||
if (hasUVs && numLocalUVs) {
|
||||
_patchTable->GetLocalPointFaceVaryingStencilTable<REAL>()->UpdateValues(
|
||||
&_patchUVs[0], &_patchUVs[numBaseUVs + numRefinedUVs]);
|
||||
}
|
||||
|
||||
delete patchRefiner;
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
bool
|
||||
FarPatchEvaluator<REAL>::FaceHasLimit(Far::Index baseFace) const {
|
||||
|
||||
return ! _baseMesh.GetLevel(0).IsFaceHole(baseFace);
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
void
|
||||
FarPatchEvaluator<REAL>::Evaluate(Far::Index baseFace,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const {
|
||||
|
||||
assert(FaceHasLimit(baseFace));
|
||||
|
||||
int numCoords = (int) tessCoords.size() / 2;
|
||||
|
||||
// Allocate vectors for the properties to be evaluated:
|
||||
results.Resize(numCoords);
|
||||
|
||||
//
|
||||
// Identify the patch face and see if it needs to be re-parameterized:
|
||||
//
|
||||
int patchFace = _patchFaces->GetFaceId(baseFace);
|
||||
|
||||
int faceSize = _baseMesh.GetLevel(0).GetFaceVertices(baseFace).size();
|
||||
|
||||
Bfr::Parameterization faceParam(_baseMesh.GetSchemeType(), faceSize);
|
||||
|
||||
bool reparameterize = faceParam.HasSubFaces();
|
||||
|
||||
//
|
||||
// Evaluate at each of the given coordinates:
|
||||
//
|
||||
REAL const * stPair = &tessCoords[0];
|
||||
for (int i = 0; i < numCoords; ++i, stPair += 2) {
|
||||
REAL st[2] = { stPair[0], stPair[1] };
|
||||
|
||||
int patchIndex = patchFace;
|
||||
if (reparameterize) {
|
||||
patchIndex += faceParam.ConvertCoordToNormalizedSubFace(st, st);
|
||||
}
|
||||
|
||||
REAL s = st[0];
|
||||
REAL t = st[1];
|
||||
|
||||
Far::PatchTable::PatchHandle const * patchHandle =
|
||||
_patchMap->FindPatch(patchIndex, s, t);
|
||||
assert(patchHandle);
|
||||
|
||||
// Evaluate position and derivatives:
|
||||
if (results.evalPosition) {
|
||||
REAL wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
|
||||
if (!results.eval1stDeriv) {
|
||||
_patchTable->EvaluateBasis(*patchHandle, s, t, wP);
|
||||
} else if (!results.eval2ndDeriv) {
|
||||
_patchTable->EvaluateBasis(*patchHandle, s, t, wP,
|
||||
wDu, wDv);
|
||||
} else {
|
||||
_patchTable->EvaluateBasis(*patchHandle, s, t, wP,
|
||||
wDu, wDv, wDuu, wDuv, wDvv);
|
||||
}
|
||||
|
||||
Vec3Real * P = results.evalPosition ? &results.p[i] : 0;
|
||||
Vec3Real * Du = results.eval1stDeriv ? &results.du[i] : 0;
|
||||
Vec3Real * Dv = results.eval1stDeriv ? &results.dv[i] : 0;
|
||||
Vec3Real * Duu = results.eval2ndDeriv ? &results.duu[i] : 0;
|
||||
Vec3Real * Duv = results.eval2ndDeriv ? &results.duv[i] : 0;
|
||||
Vec3Real * Dvv = results.eval2ndDeriv ? &results.dvv[i] : 0;
|
||||
|
||||
Far::ConstIndexArray cvIndices =
|
||||
_patchTable->GetPatchVertices(*patchHandle);
|
||||
|
||||
P->Clear();
|
||||
if (results.eval1stDeriv) {
|
||||
Du->Clear();
|
||||
Dv->Clear();
|
||||
if (results.eval2ndDeriv) {
|
||||
Duu->Clear();
|
||||
Duv->Clear();
|
||||
Dvv->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (int cv = 0; cv < cvIndices.size(); ++cv) {
|
||||
P->AddWithWeight(_patchPos[cvIndices[cv]], wP[cv]);
|
||||
if (results.eval1stDeriv) {
|
||||
Du->AddWithWeight(_patchPos[cvIndices[cv]], wDu[cv]);
|
||||
Dv->AddWithWeight(_patchPos[cvIndices[cv]], wDv[cv]);
|
||||
if (results.eval2ndDeriv) {
|
||||
Duu->AddWithWeight(_patchPos[cvIndices[cv]], wDuu[cv]);
|
||||
Duv->AddWithWeight(_patchPos[cvIndices[cv]], wDuv[cv]);
|
||||
Dvv->AddWithWeight(_patchPos[cvIndices[cv]], wDvv[cv]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results.evalUV) {
|
||||
REAL wUV[20];
|
||||
_patchTable->EvaluateBasisFaceVarying(*patchHandle, s, t, wUV);
|
||||
|
||||
Vec3Real & UV = results.uv[i];
|
||||
|
||||
UV.Clear();
|
||||
|
||||
Far::ConstIndexArray cvIndices =
|
||||
_patchTable->GetPatchFVarValues(*patchHandle);
|
||||
|
||||
for (int cv = 0; cv < cvIndices.size(); ++cv) {
|
||||
UV.AddWithWeight(_patchUVs[cvIndices[cv]], wUV[cv]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename REAL>
|
||||
FarPatchEvaluator<REAL>::~FarPatchEvaluator() {
|
||||
|
||||
delete _patchTable;
|
||||
delete _patchFaces;
|
||||
delete _patchMap;
|
||||
}
|
||||
|
||||
//
|
||||
// Explicit instantiation for float and double:
|
||||
//
|
||||
template class FarPatchEvaluator<float>;
|
||||
template class FarPatchEvaluator<double>;
|
||||
|
||||
66
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/farPatchEvaluator.h
vendored
Normal file
66
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/farPatchEvaluator.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "./types.h"
|
||||
|
||||
#include <opensubdiv/far/topologyRefiner.h>
|
||||
#include <opensubdiv/far/patchTable.h>
|
||||
#include <opensubdiv/far/patchTableFactory.h>
|
||||
#include <opensubdiv/far/patchMap.h>
|
||||
#include <opensubdiv/far/ptexIndices.h>
|
||||
|
||||
#include <opensubdiv/bfr/refinerSurfaceFactory.h>
|
||||
#include <opensubdiv/bfr/tessellation.h>
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
|
||||
|
||||
//
|
||||
// FarPatchEvaluator bundles the Far::PatchTable and its ecosystem of
|
||||
// related class to provide an evaluation interface targeted towards
|
||||
// evaluation of the base faces of a mesh.
|
||||
//
|
||||
template <typename REAL>
|
||||
class FarPatchEvaluator {
|
||||
public:
|
||||
typedef Far::PatchTableFactory PatchFactory;
|
||||
typedef Bfr::SurfaceFactory::Options BfrSurfaceOptions;
|
||||
|
||||
typedef std::vector<REAL> TessCoordVector;
|
||||
|
||||
typedef Vec3<REAL> Vec3Real;
|
||||
typedef std::vector<Vec3Real> Vec3RealVector;
|
||||
|
||||
public:
|
||||
FarPatchEvaluator(Far::TopologyRefiner const & baseMesh,
|
||||
Vec3RealVector const & basePos,
|
||||
Vec3RealVector const & baseUVs,
|
||||
BfrSurfaceOptions const & bfrSurfaceOptions);
|
||||
~FarPatchEvaluator();
|
||||
|
||||
public:
|
||||
bool FaceHasLimit(Far::Index baseFace) const;
|
||||
|
||||
void Evaluate(Far::Index baseface,
|
||||
TessCoordVector const & tessCoords,
|
||||
EvalResults<REAL> & results) const;
|
||||
|
||||
private:
|
||||
Far::TopologyRefiner const & _baseMesh;
|
||||
Vec3RealVector const & _baseMeshPos;
|
||||
Vec3RealVector const & _baseMeshUVs;
|
||||
|
||||
Far::PatchTable * _patchTable;
|
||||
Far::PatchMap * _patchMap;
|
||||
Far::PtexIndices * _patchFaces;
|
||||
|
||||
Vec3RealVector _patchPos;
|
||||
Vec3RealVector _patchUVs;
|
||||
|
||||
int _regFaceSize;
|
||||
};
|
||||
81
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/init_shapes.h
vendored
Normal file
81
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/init_shapes.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include <regression/common/shape_utils.h>
|
||||
#include <regression/shapes/all.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
initShapes(std::vector<ShapeDesc> & shapes) {
|
||||
|
||||
shapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgenone", catmark_edgenone, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
|
||||
// shapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_quadpole64",catmark_nonman_quadpole64,kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
// shapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
shapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_triangle_edgenone", loop_triangle_edgenone, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
// shapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
|
||||
shapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
133
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/init_shapes_all.h
vendored
Normal file
133
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/init_shapes_all.h
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include <regression/common/shape_utils.h>
|
||||
#include <regression/shapes/all.h>
|
||||
|
||||
static void
|
||||
initShapesAll(std::vector<ShapeDesc> & shapes) {
|
||||
|
||||
shapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_edgenone", catmark_edgenone, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fan", catmark_fan, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_flap", catmark_flap, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_flap2", catmark_flap2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_bound3", catmark_fvar_bound3, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_bound4", catmark_fvar_bound4, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_fvar_project0", catmark_fvar_project0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_gregory_test8", catmark_gregory_test8, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_bareverts", catmark_nonman_bareverts, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonman_creases", catmark_nonman_creases, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid_creases2", catmark_pyramid_creases2, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_tent_creases1", catmark_tent_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_tent", catmark_tent, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_val2_back2back", catmark_val2_back2back, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_val2_foldover", catmark_val2_foldover, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_val2_nonman", catmark_val2_nonman, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
shapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
shapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
shapes.push_back(ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_fvar_bound0", loop_fvar_bound0, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_fvar_bound1", loop_fvar_bound1, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_fvar_bound2", loop_fvar_bound2, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_fvar_bound3", loop_fvar_bound3, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_pole8", loop_pole8, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
shapes.push_back(ShapeDesc("loop_val2_interior", loop_val2_interior, kLoop));
|
||||
|
||||
// More complicated shapes with longer execution times:
|
||||
shapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
shapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
// shapes.push_back(ShapeDesc("catmark_pole360", catmark_pole360, kCatmark));
|
||||
// shapes.push_back(ShapeDesc("loop_pole360", loop_pole360, kLoop));
|
||||
}
|
||||
937
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/main.cpp
vendored
Normal file
937
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/main.cpp
vendored
Normal file
@@ -0,0 +1,937 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "./types.h"
|
||||
#include "./bfrSurfaceEvaluator.h"
|
||||
#include "./farPatchEvaluator.h"
|
||||
|
||||
#include "../../regression/common/far_utils.h"
|
||||
|
||||
#include "init_shapes.h"
|
||||
#include "init_shapes_all.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
|
||||
//
|
||||
// Global set of shapes -- populated by variants of initShapes() that
|
||||
// include explicit lists:
|
||||
//
|
||||
std::vector<ShapeDesc> g_shapes;
|
||||
|
||||
|
||||
//
|
||||
// Command line arguments and their parsing:
|
||||
//
|
||||
class Args {
|
||||
public:
|
||||
// options related to testing and reporting:
|
||||
unsigned int posEvaluate : 1;
|
||||
unsigned int d1Evaluate : 1;
|
||||
unsigned int d2Evaluate : 1;
|
||||
unsigned int uvEvaluate : 1;
|
||||
unsigned int posIgnore : 1;
|
||||
unsigned int d1Ignore : 1;
|
||||
unsigned int d2Ignore : 1;
|
||||
unsigned int uvIgnore : 1;
|
||||
unsigned int printArgs : 1;
|
||||
unsigned int printProgress : 1;
|
||||
unsigned int printFaceDiffs : 1;
|
||||
unsigned int printSummary : 1;
|
||||
unsigned int printWarnings : 1;
|
||||
unsigned int ptexConvert : 1;
|
||||
|
||||
// options affecting configuration and execution:
|
||||
unsigned int evalByStencils : 1;
|
||||
unsigned int doublePrecision : 1;
|
||||
unsigned int noCacheFlag : 1;
|
||||
|
||||
// options affecting the shape of the limit surface:
|
||||
int depthSharp;
|
||||
int depthSmooth;
|
||||
int bndInterp;
|
||||
int uvInterp;
|
||||
|
||||
// options related to tessellation and comparison:
|
||||
int uniformRes;
|
||||
float relTolerance;
|
||||
float absTolerance;
|
||||
float uvTolerance;
|
||||
|
||||
// options affecting the list of shapes to be tested:
|
||||
int shapeCount;
|
||||
Scheme shapeScheme;
|
||||
bool shapesCat2Loop;
|
||||
bool shapesAll;
|
||||
|
||||
std::vector<ShapeDesc> shapes;
|
||||
|
||||
// options determining overall success/failure:
|
||||
int passCount;
|
||||
|
||||
public:
|
||||
Args(int argc, char **argv) :
|
||||
posEvaluate(true),
|
||||
d1Evaluate(false),
|
||||
d2Evaluate(false),
|
||||
uvEvaluate(false),
|
||||
posIgnore(false),
|
||||
d1Ignore(false),
|
||||
d2Ignore(false),
|
||||
uvIgnore(false),
|
||||
printArgs(true),
|
||||
printProgress(true),
|
||||
printFaceDiffs(false),
|
||||
printSummary(true),
|
||||
printWarnings(true),
|
||||
ptexConvert(false),
|
||||
evalByStencils(false),
|
||||
doublePrecision(false),
|
||||
noCacheFlag(false),
|
||||
depthSharp(-1),
|
||||
depthSmooth(-1),
|
||||
bndInterp(-1),
|
||||
uvInterp(-1),
|
||||
uniformRes(3),
|
||||
relTolerance(0.00005f),
|
||||
absTolerance(0.0f),
|
||||
uvTolerance(0.0001f),
|
||||
shapeCount(0),
|
||||
shapeScheme(kCatmark),
|
||||
shapesCat2Loop(false),
|
||||
shapesAll(false),
|
||||
shapes(),
|
||||
passCount(0) {
|
||||
|
||||
std::string fileString;
|
||||
|
||||
std::vector<std::string> shapeNames;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
char * arg = argv[i];
|
||||
|
||||
// Options related to input .obj files:
|
||||
if (strstr(arg, ".obj")) {
|
||||
if (readString(arg, fileString)) {
|
||||
// Use the scheme declared at the time so that multiple
|
||||
// shape/scheme pairs can be specified
|
||||
shapes.push_back(
|
||||
ShapeDesc(arg, fileString.c_str(), shapeScheme));
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: Unable to open/read .obj file '%s'\n", arg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Options affecting the limit surface shapes:
|
||||
} else if (!strcmp(arg, "-l")) {
|
||||
if (++i < argc) {
|
||||
int maxLevel = atoi(argv[i]);
|
||||
depthSharp = maxLevel;
|
||||
depthSmooth = maxLevel;
|
||||
}
|
||||
} else if (!strcmp(arg, "-lsharp")) {
|
||||
if (++i < argc) depthSharp = atoi(argv[i]);
|
||||
} else if (!strcmp(arg, "-lsmooth")) {
|
||||
if (++i < argc) depthSmooth = atoi(argv[i]);
|
||||
} else if (!strcmp(argv[i], "-bint")) {
|
||||
if (++i < argc) bndInterp = atoi(argv[i]);
|
||||
} else if (!strcmp(argv[i], "-uvint")) {
|
||||
if (++i < argc) uvInterp = atoi(argv[i]);
|
||||
|
||||
// Options affecting what gets evaluated:
|
||||
} else if (!strcmp(arg, "-res")) {
|
||||
if (++i < argc) uniformRes = atoi(argv[i]);
|
||||
} else if (!strcmp(arg, "-pos")) {
|
||||
posEvaluate = true;
|
||||
} else if (!strcmp(arg, "-nopos")) {
|
||||
posEvaluate = false;
|
||||
} else if (!strcmp(arg, "-d1")) {
|
||||
d1Evaluate = true;
|
||||
} else if (!strcmp(arg, "-nod1")) {
|
||||
d1Evaluate = false;
|
||||
} else if (!strcmp(arg, "-d2")) {
|
||||
d2Evaluate = true;
|
||||
} else if (!strcmp(arg, "-nod2")) {
|
||||
d2Evaluate = false;
|
||||
} else if (!strcmp(arg, "-uv")) {
|
||||
uvEvaluate = true;
|
||||
} else if (!strcmp(arg, "-nouv")) {
|
||||
uvEvaluate = false;
|
||||
} else if (!strcmp(arg, "-ptex")) {
|
||||
ptexConvert = true;
|
||||
} else if (!strcmp(arg, "-noptex")) {
|
||||
ptexConvert = false;
|
||||
|
||||
// Options affecting what gets compared and reported:
|
||||
} else if (!strcmp(arg, "-skippos")) {
|
||||
posIgnore = true;
|
||||
} else if (!strcmp(arg, "-skipd1")) {
|
||||
d1Ignore = true;
|
||||
} else if (!strcmp(arg, "-skipd2")) {
|
||||
d2Ignore = true;
|
||||
} else if (!strcmp(arg, "-skipuv")) {
|
||||
uvIgnore = true;
|
||||
} else if (!strcmp(arg, "-faces")) {
|
||||
printFaceDiffs = true;
|
||||
|
||||
// Options affecting comparison tolerances:
|
||||
} else if (!strcmp(argv[i], "-reltol")) {
|
||||
if (++i < argc) relTolerance = (float)atof(argv[i]);
|
||||
} else if (!strcmp(argv[i], "-abstol")) {
|
||||
if (++i < argc) absTolerance = (float)atof(argv[i]);
|
||||
} else if (!strcmp(argv[i], "-uvtol")) {
|
||||
if (++i < argc) uvTolerance = (float)atof(argv[i]);
|
||||
|
||||
// Options controlling other internal processing:
|
||||
} else if (!strcmp(arg, "-stencils")) {
|
||||
evalByStencils = true;
|
||||
} else if (!strcmp(arg, "-double")) {
|
||||
doublePrecision = true;
|
||||
} else if (!strcmp(arg, "-nocache")) {
|
||||
noCacheFlag = true;
|
||||
|
||||
// Options affecting the shapes to be included:
|
||||
} else if (!strcmp(arg, "-bilinear")) {
|
||||
shapeScheme = kBilinear;
|
||||
} else if (!strcmp(arg, "-catmark")) {
|
||||
shapeScheme = kCatmark;
|
||||
} else if (!strcmp(arg, "-loop")) {
|
||||
shapeScheme = kLoop;
|
||||
} else if (!strcmp(arg, "-cat2loop")) {
|
||||
shapesCat2Loop = true;
|
||||
} else if (!strcmp(arg, "-count")) {
|
||||
if (++i < argc) shapeCount = atoi(argv[i]);
|
||||
} else if (!strcmp(arg, "-shape")) {
|
||||
if (++i < argc) {
|
||||
shapeNames.push_back(std::string(argv[i]));
|
||||
}
|
||||
} else if (!strcmp(arg, "-all")) {
|
||||
shapesAll = true;
|
||||
|
||||
// Printing and reporting:
|
||||
} else if (!strcmp(arg, "-args")) {
|
||||
printArgs = true;
|
||||
} else if (!strcmp(arg, "-noargs")) {
|
||||
printArgs = false;
|
||||
} else if (!strcmp(arg, "-prog")) {
|
||||
printProgress = true;
|
||||
} else if (!strcmp(arg, "-noprog")) {
|
||||
printProgress = false;
|
||||
} else if (!strcmp(arg, "-sum")) {
|
||||
printSummary = true;
|
||||
} else if (!strcmp(arg, "-nosum")) {
|
||||
printSummary = false;
|
||||
} else if (!strcmp(arg, "-quiet")) {
|
||||
printWarnings = false;
|
||||
} else if (!strcmp(arg, "-silent")) {
|
||||
printArgs = false;
|
||||
printProgress = false;
|
||||
printSummary = false;
|
||||
printWarnings = false;
|
||||
|
||||
// Success/failure of the entire test:
|
||||
} else if (!strcmp(argv[i], "-pass")) {
|
||||
if (++i < argc) passCount = atoi(argv[i]);
|
||||
|
||||
// Unrecognized...
|
||||
} else {
|
||||
fprintf(stderr, "Error: Unrecognized argument '%s'\n", arg);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Validation -- possible conflicting options, values, etc.
|
||||
if (bndInterp > 2) {
|
||||
fprintf(stderr, "Warning: Ignoring bad value to -bint (%d)\n",
|
||||
bndInterp);
|
||||
bndInterp = -1;
|
||||
}
|
||||
if (uvInterp > 5) {
|
||||
fprintf(stderr, "Warning: Ignoring bad value to -uvint (%d)\n",
|
||||
uvInterp);
|
||||
uvInterp = -1;
|
||||
}
|
||||
|
||||
if (d2Evaluate) {
|
||||
if (!d1Evaluate) {
|
||||
fprintf(stderr, "Warning: 2nd deriv evaluation forces 1st.\n");
|
||||
d1Evaluate = true;
|
||||
}
|
||||
if (!posEvaluate) {
|
||||
fprintf(stderr, "Warning: 2nd deriv evaluation forces pos.\n");
|
||||
posEvaluate = true;
|
||||
}
|
||||
} else if (d1Evaluate) {
|
||||
if (!posEvaluate) {
|
||||
fprintf(stderr, "Warning: 1st deriv evaluation forces pos.\n");
|
||||
posEvaluate = true;
|
||||
}
|
||||
}
|
||||
if (!posEvaluate && !uvEvaluate) {
|
||||
fprintf(stderr, "Error: All pos and UV evaluation disabled.\n");
|
||||
exit(0);
|
||||
}
|
||||
if (posIgnore && d1Ignore && d2Ignore && uvIgnore) {
|
||||
fprintf(stderr, "Error: All pos and UV comparisons disabled.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((depthSmooth == 0) || (depthSharp == 0)) {
|
||||
fprintf(stderr,
|
||||
"Warning: Far evaluation unstable with refinement level 0.\n");
|
||||
}
|
||||
|
||||
// Managing the list of shapes:
|
||||
assert(g_shapes.empty());
|
||||
if (!shapeNames.empty()) {
|
||||
if (shapesAll) {
|
||||
initShapesAll(g_shapes);
|
||||
} else {
|
||||
initShapes(g_shapes);
|
||||
}
|
||||
// Maybe worth building a map -- for this and more...
|
||||
for (size_t i = 0; i < shapeNames.size(); ++i) {
|
||||
std::string & shapeName = shapeNames[i];
|
||||
bool found = false;
|
||||
for (size_t j = 0; !found && (j < g_shapes.size()); ++j) {
|
||||
if (g_shapes[j].name == shapeName) {
|
||||
shapes.push_back(g_shapes[j]);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr,
|
||||
"Error: Specified shape '%s' not found.\n",
|
||||
shapeName.c_str());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
~Args() { }
|
||||
|
||||
void
|
||||
Print() const {
|
||||
|
||||
char const * boolStrings[2] = { "false", "true" };
|
||||
char const * bIntStrings[3] = { "BOUNDARY_NONE",
|
||||
"BOUNDARY_EDGE_ONLY",
|
||||
"BOUNDARY_EDGE_AND_CORNER" };
|
||||
char const * fvIntStrings[6] = { "LINEAR_NONE",
|
||||
"LINEAR_CORNERS_ONLY",
|
||||
"LINEAR_CORNERS_PLUS1",
|
||||
"LINEAR_CORNERS_PLUS2",
|
||||
"LINEAR_BOUNDARIES",
|
||||
"LINEAR_ALL" };
|
||||
|
||||
printf("\n");
|
||||
printf("Shape options:\n");
|
||||
if (depthSharp >= 0) {
|
||||
printf(" - max level sharp = %d\n", depthSharp);
|
||||
} else {
|
||||
printf(" - max level sharp = %d (dflt)\n",
|
||||
(Bfr::SurfaceFactory::Options()).GetApproxLevelSharp());
|
||||
}
|
||||
if (depthSmooth >= 0) {
|
||||
printf(" - max level smooth = %d\n", depthSmooth);
|
||||
} else {
|
||||
printf(" - max level smooth = %d (dflt)\n",
|
||||
(Bfr::SurfaceFactory::Options()).GetApproxLevelSmooth());
|
||||
}
|
||||
if (bndInterp < 0) {
|
||||
printf(" - boundary interp = (as assigned)\n");
|
||||
} else {
|
||||
printf(" - boundary interp = %s\n", bIntStrings[bndInterp]);
|
||||
}
|
||||
if (uvEvaluate) {
|
||||
if (uvInterp < 0) {
|
||||
printf(" - UV linear interp = (as assigned)\n");
|
||||
} else {
|
||||
printf(" - UV linear interp = %s\n", fvIntStrings[uvInterp]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Evaluation options:\n");
|
||||
printf(" - tessellation res = %d\n", uniformRes);
|
||||
printf(" - position = %s\n", boolStrings[posEvaluate]);
|
||||
printf(" - 1st derivative = %s\n", boolStrings[d1Evaluate]);
|
||||
printf(" - 2nd derivative = %s\n", boolStrings[d2Evaluate]);
|
||||
printf(" - UV = %s\n", boolStrings[uvEvaluate]);
|
||||
|
||||
printf("Comparison options:\n");
|
||||
if (absTolerance > 0.0f) {
|
||||
printf(" - tolerance (abs) = %g\n", absTolerance);
|
||||
} else {
|
||||
printf(" - tolerance (rel) = %g\n", relTolerance);
|
||||
}
|
||||
if (uvEvaluate) {
|
||||
printf(" - tolerance UV = %g\n", uvTolerance);
|
||||
}
|
||||
if (posEvaluate && posIgnore) {
|
||||
printf(" - ignore pos = %s\n", boolStrings[posIgnore]);
|
||||
}
|
||||
if (d1Evaluate && d1Ignore) {
|
||||
printf(" - ignore 1st deriv = %s\n", boolStrings[d1Ignore]);
|
||||
}
|
||||
if (d2Evaluate && d2Ignore) {
|
||||
printf(" - ignore 2nd deriv = %s\n", boolStrings[d2Ignore]);
|
||||
}
|
||||
if (uvEvaluate && uvIgnore) {
|
||||
printf(" - ignore UV = %s\n", boolStrings[uvIgnore]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
private:
|
||||
Args() { }
|
||||
|
||||
bool
|
||||
readString(const char *fileName, std::string& fileString) {
|
||||
std::ifstream ifs(fileName);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
|
||||
fileString = ss.str();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Create a TopologyRefiner from a Shape:
|
||||
//
|
||||
template <typename REAL>
|
||||
Far::TopologyRefiner *
|
||||
createTopologyRefiner(ShapeDesc const & shapeDesc,
|
||||
std::vector< Vec3<REAL> > & shapePos,
|
||||
std::vector< Vec3<REAL> > & shapeUVs,
|
||||
Args const & args) {
|
||||
|
||||
typedef Vec3<REAL> Vec3Real;
|
||||
|
||||
//
|
||||
// Load the Shape -- skip with a warning on failure:
|
||||
//
|
||||
Shape * shape = Shape::parseObj(shapeDesc.data.c_str(),
|
||||
shapeDesc.scheme,
|
||||
shapeDesc.isLeftHanded);
|
||||
if (shape == 0) {
|
||||
if (args.printWarnings) {
|
||||
fprintf(stderr, "Warning: Failed to parse shape '%s'\n",
|
||||
shapeDesc.name.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify UVs before continuing:
|
||||
if (args.uvEvaluate) {
|
||||
if (shape->uvs.empty() != shape->faceuvs.empty()) {
|
||||
if (args.printWarnings) {
|
||||
fprintf(stderr,
|
||||
"Warning: Incomplete UVs assigned to Shape '%s'\n",
|
||||
shapeDesc.name.c_str());
|
||||
}
|
||||
delete shape;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a TopologyRefiner and load position and UVs:
|
||||
//
|
||||
Sdc::SchemeType sdcType = GetSdcType(*shape);
|
||||
|
||||
if (args.shapesCat2Loop && (sdcType == Sdc::SCHEME_LOOP)) {
|
||||
if (args.printWarnings) {
|
||||
fprintf(stderr,
|
||||
"\t\tWarning: Applying Catmark to Loop shape '%s'\n",
|
||||
shapeDesc.name.c_str());
|
||||
}
|
||||
sdcType = Sdc::SCHEME_CATMARK;
|
||||
}
|
||||
|
||||
Sdc::Options sdcOptions = GetSdcOptions(*shape);
|
||||
if (args.bndInterp >= 0) {
|
||||
sdcOptions.SetVtxBoundaryInterpolation(
|
||||
(Sdc::Options::VtxBoundaryInterpolation) args.bndInterp);
|
||||
}
|
||||
if (args.uvInterp >= 0) {
|
||||
sdcOptions.SetFVarLinearInterpolation(
|
||||
(Sdc::Options::FVarLinearInterpolation) args.uvInterp);
|
||||
}
|
||||
|
||||
Far::TopologyRefiner * refiner =
|
||||
Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
Far::TopologyRefinerFactory<Shape>::Options(sdcType, sdcOptions));
|
||||
|
||||
if (refiner == 0) {
|
||||
if (args.printWarnings) {
|
||||
fprintf(stderr, "Warning: Unable to interpret Shape '%s'\n",
|
||||
shapeDesc.name.c_str());
|
||||
}
|
||||
delete shape;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int numVertices = refiner->GetNumVerticesTotal();
|
||||
shapePos.resize(numVertices);
|
||||
for (int i = 0; i < numVertices; ++i) {
|
||||
shapePos[i] = Vec3Real(shape->verts[i*3],
|
||||
shape->verts[i*3+1],
|
||||
shape->verts[i*3+2]);
|
||||
}
|
||||
|
||||
shapeUVs.resize(0);
|
||||
if (args.uvEvaluate) {
|
||||
if (refiner->GetNumFVarChannels()) {
|
||||
int numUVs = refiner->GetNumFVarValuesTotal(0);
|
||||
shapeUVs.resize(numUVs);
|
||||
for (int i = 0; i < numUVs; ++i) {
|
||||
shapeUVs[i] = Vec3Real(shape->uvs[i*2],
|
||||
shape->uvs[i*2+1],
|
||||
0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete shape;
|
||||
return refiner;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Compute the bounding box of a Vec3 vector and a relative tolerance:
|
||||
//
|
||||
template <typename REAL>
|
||||
REAL
|
||||
GetRelativeTolerance(std::vector< Vec3<REAL> > const & p, REAL fraction) {
|
||||
|
||||
Vec3<REAL> pMin = p[0];
|
||||
Vec3<REAL> pMax = p[0];
|
||||
|
||||
for (size_t i = 1; i < p.size(); ++i) {
|
||||
Vec3<REAL> const & pi = p[i];
|
||||
|
||||
pMin[0] = std::min(pMin[0], pi[0]);
|
||||
pMin[1] = std::min(pMin[1], pi[1]);
|
||||
pMin[2] = std::min(pMin[2], pi[2]);
|
||||
|
||||
pMax[0] = std::max(pMax[0], pi[0]);
|
||||
pMax[1] = std::max(pMax[1], pi[1]);
|
||||
pMax[2] = std::max(pMax[2], pi[2]);
|
||||
}
|
||||
|
||||
Vec3<REAL> pDelta = pMax - pMin;
|
||||
|
||||
REAL maxSize = std::max(std::abs(pDelta[0]), std::abs(pDelta[1]));
|
||||
maxSize = std::max(maxSize, std::abs(pDelta[2]));
|
||||
|
||||
return fraction * maxSize;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// An independent test from limit surface evaluation: comparing the
|
||||
// conversion of (u,v) coordinates for Bfr::Parameterization to Ptex
|
||||
// and back (subject to a given tolerance):
|
||||
//
|
||||
template <typename REAL>
|
||||
void
|
||||
ValidatePtexConversion(Bfr::Parameterization const & param,
|
||||
REAL const givenCoord[2], REAL tol = 0.0001f) {
|
||||
|
||||
if (!param.HasSubFaces()) return;
|
||||
|
||||
//
|
||||
// Convert the given (u,v) coordinate to Ptex and back and
|
||||
// compare the final result to the original:
|
||||
//
|
||||
REAL ptexCoord[2];
|
||||
REAL finalCoord[2];
|
||||
|
||||
int ptexFace = param.ConvertCoordToNormalizedSubFace(givenCoord, ptexCoord);
|
||||
param.ConvertNormalizedSubFaceToCoord(ptexFace, ptexCoord, finalCoord);
|
||||
|
||||
bool subFaceDiff = (ptexFace != param.GetSubFace(givenCoord));
|
||||
bool uCoordDiff = (std::abs(finalCoord[0] - givenCoord[0]) > tol);
|
||||
bool vCoordDiff = (std::abs(finalCoord[1] - givenCoord[1]) > tol);
|
||||
|
||||
if (subFaceDiff || uCoordDiff || vCoordDiff) {
|
||||
fprintf(stderr,
|
||||
"Warning: Mismatch in sub-face Parameterization conversion:\n");
|
||||
if (subFaceDiff ) {
|
||||
fprintf(stderr,
|
||||
" converted sub-face (%d) != original (%d)\n",
|
||||
ptexFace, param.GetSubFace(givenCoord));
|
||||
}
|
||||
if (uCoordDiff || vCoordDiff) {
|
||||
fprintf(stderr,
|
||||
" converted coord (%f,%f) != original (%f,%f)\n",
|
||||
finalCoord[0], finalCoord[1], givenCoord[0], givenCoord[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Compare two meshes using Bfr::Surfaces and a Far::PatchTable:
|
||||
//
|
||||
template <typename REAL>
|
||||
int
|
||||
testMesh(Far::TopologyRefiner const & mesh,
|
||||
std::string const & meshName,
|
||||
std::vector< Vec3<REAL> > const & meshPos,
|
||||
std::vector< Vec3<REAL> > const & meshUVs,
|
||||
Args const & args) {
|
||||
|
||||
//
|
||||
// Determine what to evaluate/compare based on args and mesh content
|
||||
// (remember that these are not completely independent -- position
|
||||
// evaluation will have been set if evaluating any derivatives):
|
||||
//
|
||||
bool evalPos = args.posEvaluate;
|
||||
bool evalD1 = args.d1Evaluate;
|
||||
bool evalD2 = args.d2Evaluate;
|
||||
bool evalUV = args.uvEvaluate && (meshUVs.size() > 0);
|
||||
|
||||
bool comparePos = evalPos && !args.posIgnore;
|
||||
bool compareD1 = evalD1 && !args.d1Ignore;
|
||||
bool compareD2 = evalD2 && !args.d2Ignore;
|
||||
bool compareUV = evalUV && !args.uvIgnore;
|
||||
|
||||
// If nothing to compare, return 0 failures:
|
||||
if ((comparePos + compareD1 + compareD2 + compareUV) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Declare/allocate output evaluation buffers for both Bfr and Far:
|
||||
std::vector<REAL> evalCoords;
|
||||
|
||||
EvalResults<REAL> bfrResults;
|
||||
bfrResults.evalPosition = evalPos;
|
||||
bfrResults.eval1stDeriv = evalD1;
|
||||
bfrResults.eval2ndDeriv = evalD2;
|
||||
bfrResults.evalUV = evalUV;
|
||||
bfrResults.useStencils = args.evalByStencils;
|
||||
|
||||
EvalResults<REAL> farResults;
|
||||
farResults.evalPosition = evalPos;
|
||||
farResults.eval1stDeriv = evalD1;
|
||||
farResults.eval2ndDeriv = evalD2;
|
||||
farResults.evalUV = evalUV;
|
||||
|
||||
//
|
||||
// Create evaluators for Bfr and Far -- using the same set of Bfr
|
||||
// options to ensure consistency (the Far evaluator needs to interpret
|
||||
// them appropriate to Far::PatchTable and associated refinement)
|
||||
//
|
||||
Bfr::SurfaceFactory::Options surfaceOptions;
|
||||
|
||||
// Leave approximation defaults in place unless explicitly overridden:
|
||||
if (args.depthSharp >= 0) {
|
||||
surfaceOptions.SetApproxLevelSharp(args.depthSharp);
|
||||
}
|
||||
if (args.depthSmooth >= 0) {
|
||||
surfaceOptions.SetApproxLevelSmooth(args.depthSmooth);
|
||||
}
|
||||
surfaceOptions.SetDefaultFVarID(0);
|
||||
surfaceOptions.EnableCaching(!args.noCacheFlag);
|
||||
|
||||
BfrSurfaceEvaluator<REAL> bfrEval(mesh, meshPos, meshUVs, surfaceOptions);
|
||||
FarPatchEvaluator<REAL> farEval(mesh, meshPos, meshUVs, surfaceOptions);
|
||||
|
||||
//
|
||||
// Initialize tolerances and variables to track differences:
|
||||
//
|
||||
REAL pTol = (args.absTolerance > 0.0f) ? args.absTolerance :
|
||||
GetRelativeTolerance<REAL>(meshPos, args.relTolerance);
|
||||
REAL d1Tol = pTol * 5.0f;
|
||||
REAL d2Tol = d1Tol * 5.0f;
|
||||
REAL uvTol = args.uvTolerance;
|
||||
|
||||
VectorDelta<REAL> pDelta(pTol);
|
||||
VectorDelta<REAL> duDelta(d1Tol);
|
||||
VectorDelta<REAL> dvDelta(d1Tol);
|
||||
VectorDelta<REAL> duuDelta(d2Tol);
|
||||
VectorDelta<REAL> duvDelta(d2Tol);
|
||||
VectorDelta<REAL> dvvDelta(d2Tol);
|
||||
VectorDelta<REAL> uvDelta(uvTol);
|
||||
|
||||
FaceDelta<REAL> faceDelta;
|
||||
|
||||
MeshDelta<REAL> meshDelta;
|
||||
|
||||
bool meshHasBeenLabeled = false;
|
||||
|
||||
int numFaces = mesh.GetNumFacesTotal();
|
||||
for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
|
||||
//
|
||||
// Make sure both match in terms of identifying a limit surface:
|
||||
//
|
||||
assert(bfrEval.FaceHasLimit(faceIndex) ==
|
||||
farEval.FaceHasLimit(faceIndex));
|
||||
|
||||
if (!farEval.FaceHasLimit(faceIndex)) continue;
|
||||
|
||||
//
|
||||
// Declare/define a Tessellation to generate a consistent set of
|
||||
// (u,v) locations to compare and evaluate:
|
||||
//
|
||||
int faceSize = mesh.GetLevel(0).GetFaceVertices(faceIndex).size();
|
||||
|
||||
Bfr::Parameterization faceParam(mesh.GetSchemeType(), faceSize);
|
||||
assert(faceParam.IsValid());
|
||||
|
||||
Bfr::Tessellation faceTess(faceParam, args.uniformRes);
|
||||
assert(faceTess.IsValid());
|
||||
|
||||
evalCoords.resize(2 * faceTess.GetNumCoords());
|
||||
faceTess.GetCoords(&evalCoords[0]);
|
||||
|
||||
//
|
||||
// Before evaluating and comparing, run the test to convert the
|
||||
// parametric coords to Ptex and back:
|
||||
//
|
||||
if (args.ptexConvert) {
|
||||
for (int i = 0; i < faceTess.GetNumCoords(); ++i) {
|
||||
ValidatePtexConversion<REAL>(faceParam, &evalCoords[2*i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Evaluate and capture results of comparisons between results:
|
||||
//
|
||||
bfrEval.Evaluate(faceIndex, evalCoords, bfrResults);
|
||||
farEval.Evaluate(faceIndex, evalCoords, farResults);
|
||||
|
||||
if (comparePos) {
|
||||
pDelta.Compare(bfrResults.p, farResults.p);
|
||||
}
|
||||
if (compareD1) {
|
||||
duDelta.Compare(bfrResults.du, farResults.du);
|
||||
dvDelta.Compare(bfrResults.dv, farResults.dv);
|
||||
}
|
||||
if (compareD2) {
|
||||
duuDelta.Compare(bfrResults.duu, farResults.duu);
|
||||
duvDelta.Compare(bfrResults.duv, farResults.duv);
|
||||
dvvDelta.Compare(bfrResults.dvv, farResults.dvv);
|
||||
}
|
||||
if (compareUV) {
|
||||
uvDelta.Compare(bfrResults.uv, farResults.uv);
|
||||
}
|
||||
|
||||
//
|
||||
// Note collective differences for this face and report:
|
||||
//
|
||||
faceDelta.Clear();
|
||||
faceDelta.AddPDelta(pDelta);
|
||||
faceDelta.AddDuDelta(duDelta);
|
||||
faceDelta.AddDvDelta(dvDelta);
|
||||
faceDelta.AddDuuDelta(duuDelta);
|
||||
faceDelta.AddDuvDelta(duvDelta);
|
||||
faceDelta.AddDvvDelta(dvvDelta);
|
||||
faceDelta.AddUVDelta(uvDelta);
|
||||
|
||||
if (args.printFaceDiffs && faceDelta.hasDeltas) {
|
||||
if (!meshHasBeenLabeled) {
|
||||
meshHasBeenLabeled = true;
|
||||
printf("'%s':\n", meshName.c_str());
|
||||
}
|
||||
printf("\t Face %d:\n", faceIndex);
|
||||
|
||||
if (comparePos && faceDelta.numPDeltas) {
|
||||
printf("\t\t POS:%6d diffs, max delta P = %g\n",
|
||||
faceDelta.numPDeltas, (float) faceDelta.maxPDelta);
|
||||
}
|
||||
if (compareD1 && faceDelta.numD1Deltas) {
|
||||
printf("\t\t D1:%6d diffs, max delta D1 = %g\n",
|
||||
faceDelta.numD1Deltas, (float) faceDelta.maxD1Delta);
|
||||
}
|
||||
if (compareD2 && faceDelta.numD2Deltas) {
|
||||
printf("\t\t D2:%6d diffs, max delta D2 = %g\n",
|
||||
faceDelta.numD2Deltas, (float) faceDelta.maxD2Delta);
|
||||
}
|
||||
if (compareUV && faceDelta.hasUVDeltas) {
|
||||
printf("\t\t UV:%6d diffs, max delta UV = %g\n",
|
||||
uvDelta.numDeltas, (float) uvDelta.maxDelta);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the results for this face to the collective mesh delta:
|
||||
meshDelta.AddFace(faceDelta);
|
||||
}
|
||||
|
||||
//
|
||||
// Report the differences for this mesh:
|
||||
//
|
||||
if (meshDelta.numFacesWithDeltas) {
|
||||
if (args.printFaceDiffs) {
|
||||
printf("\t Total:\n");
|
||||
} else {
|
||||
printf("'%s':\n", meshName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (comparePos && meshDelta.numFacesWithPDeltas) {
|
||||
printf("\t\tPOS diffs:%6d faces, max delta P = %g\n",
|
||||
meshDelta.numFacesWithPDeltas, (float) meshDelta.maxPDelta);
|
||||
}
|
||||
if (compareD1 && meshDelta.numFacesWithD1Deltas) {
|
||||
printf("\t\t D1 diffs:%6d faces, max delta D1 = %g\n",
|
||||
meshDelta.numFacesWithD1Deltas, (float) meshDelta.maxD1Delta);
|
||||
}
|
||||
if (compareD2 && meshDelta.numFacesWithD2Deltas) {
|
||||
printf("\t\t D2 diffs:%6d faces, max delta D2 = %g\n",
|
||||
meshDelta.numFacesWithD2Deltas, (float) meshDelta.maxD2Delta);
|
||||
}
|
||||
if (compareUV && meshDelta.numFacesWithUVDeltas) {
|
||||
printf("\t\t UV diffs:%6d faces, max delta UV = %g\n",
|
||||
meshDelta.numFacesWithUVDeltas, (float) meshDelta.maxUVDelta);
|
||||
}
|
||||
return meshDelta.numFacesWithDeltas;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Run the comparison for a given Shape in single or double precision:
|
||||
//
|
||||
template <typename REAL>
|
||||
int
|
||||
testShape(ShapeDesc const & shapeDesc, Args const & args) {
|
||||
|
||||
//
|
||||
// Get the TopologyRefiner, positions and UVs for the Shape, report
|
||||
// failure to generate the shape, and run the test:
|
||||
//
|
||||
std::string const & meshName = shapeDesc.name;
|
||||
|
||||
std::vector< Vec3<REAL> > basePos;
|
||||
std::vector< Vec3<REAL> > baseUV;
|
||||
|
||||
Far::TopologyRefiner * refiner =
|
||||
createTopologyRefiner<REAL>(shapeDesc, basePos, baseUV, args);
|
||||
|
||||
if (refiner == 0) {
|
||||
if (args.printWarnings) {
|
||||
fprintf(stderr,
|
||||
"Warning: Shape '%s' ignored (unable to construct refiner)\n",
|
||||
meshName.c_str());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nFailures = testMesh<REAL>(*refiner, meshName, basePos, baseUV, args);
|
||||
|
||||
delete refiner;
|
||||
|
||||
return nFailures;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Run comparison tests on a list of shapes using command line options:
|
||||
//
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
|
||||
Args args(argc, argv);
|
||||
|
||||
// Capture relevant command line options used here:
|
||||
if (args.printArgs) {
|
||||
args.Print();
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the list of shapes and test each (or only the first):
|
||||
//
|
||||
// - currently the internal list can be overridden on the command
|
||||
// line (so use of wildcards is possible)
|
||||
//
|
||||
// - still exploring additional command line options, e.g. hoping
|
||||
// to specify a list of shape names from the internal list...
|
||||
//
|
||||
// So a bit more to be done here...
|
||||
//
|
||||
std::vector<ShapeDesc>& shapeList = g_shapes;
|
||||
|
||||
if (!args.shapes.empty()) {
|
||||
shapeList.swap(args.shapes);
|
||||
}
|
||||
if (shapeList.empty()) {
|
||||
if (args.shapesAll) {
|
||||
initShapesAll(shapeList);
|
||||
} else {
|
||||
initShapes(shapeList);
|
||||
}
|
||||
}
|
||||
|
||||
int shapesToTest = (int) shapeList.size();
|
||||
int shapesIgnored = 0;
|
||||
if ((args.shapeCount > 0) && (args.shapeCount < shapesToTest)) {
|
||||
shapesIgnored = shapesToTest - args.shapeCount;
|
||||
shapesToTest = args.shapeCount;
|
||||
}
|
||||
|
||||
if (args.printProgress) {
|
||||
printf("Testing %d shapes", shapesToTest);
|
||||
if (shapesIgnored) {
|
||||
printf(" (%d ignored)", shapesIgnored);
|
||||
}
|
||||
printf(":\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Run the comparison test for each shape (ShapeDesc) in the
|
||||
// specified precision and report results:
|
||||
//
|
||||
int shapesFailed = 0;
|
||||
|
||||
for (int shapeIndex = 0; shapeIndex < shapesToTest; ++shapeIndex) {
|
||||
ShapeDesc & shapeDesc = shapeList[shapeIndex];
|
||||
|
||||
if (args.printProgress) {
|
||||
printf("%4d of %d: '%s'\n", 1 + shapeIndex, shapesToTest,
|
||||
shapeDesc.name.c_str());
|
||||
}
|
||||
|
||||
int nFailures = args.doublePrecision ?
|
||||
testShape<double>(shapeDesc, args) :
|
||||
testShape<float>(shapeDesc, args);
|
||||
|
||||
if (nFailures < 0) {
|
||||
// Possible error/warning...?
|
||||
++ shapesFailed;
|
||||
}
|
||||
if (nFailures > 0) {
|
||||
++ shapesFailed;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.printSummary) {
|
||||
printf("\n");
|
||||
if (shapesFailed == 0) {
|
||||
printf("All tests passed for %d shapes\n", shapesToTest);
|
||||
} else {
|
||||
printf("Total failures: %d of %d shapes\n", shapesFailed,
|
||||
shapesToTest);
|
||||
}
|
||||
}
|
||||
|
||||
return (shapesFailed == args.passCount) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
296
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/types.h
vendored
Normal file
296
blender-5.2.0/extern/opensubdiv-source/regression/bfr_evaluate/types.h
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// Copyright 2021 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
#ifndef OPENSUBDIV3_REGRESSION_BFR_EVALUATE_TYPES_H
|
||||
#define OPENSUBDIV3_REGRESSION_BFR_EVALUATE_TYPES_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
//
|
||||
// Simple interpolatable struct for (x,y,z) positions and normals:
|
||||
//
|
||||
template <typename REAL>
|
||||
struct Vec3 {
|
||||
Vec3<REAL>() { }
|
||||
Vec3<REAL>(REAL x, REAL y, REAL z) { p[0] = x, p[1] = y, p[2] = z; }
|
||||
|
||||
// Clear() and AddWithWeight() required for interpolation:
|
||||
void Clear( void * =0 ) { p[0] = p[1] = p[2] = 0.0f; }
|
||||
|
||||
void AddWithWeight(Vec3<REAL> const & src, REAL weight) {
|
||||
p[0] += weight * src.p[0];
|
||||
p[1] += weight * src.p[1];
|
||||
p[2] += weight * src.p[2];
|
||||
}
|
||||
|
||||
// Element access via []:
|
||||
REAL const & operator[](int i) const { return p[i]; }
|
||||
REAL & operator[](int i) { return p[i]; }
|
||||
|
||||
// Element access via []:
|
||||
REAL const * Coords() const { return p; }
|
||||
REAL * Coords() { return p; }
|
||||
|
||||
// Additional useful mathematical operations:
|
||||
Vec3<REAL> operator-(Vec3<REAL> const & x) const {
|
||||
return Vec3<REAL>(p[0] - x.p[0], p[1] - x.p[1], p[2] - x.p[2]);
|
||||
}
|
||||
Vec3<REAL> operator+(Vec3<REAL> const & x) const {
|
||||
return Vec3<REAL>(p[0] + x.p[0], p[1] + x.p[1], p[2] + x.p[2]);
|
||||
}
|
||||
Vec3<REAL> operator*(REAL s) const {
|
||||
return Vec3<REAL>(p[0] * s, p[1] * s, p[2] * s);
|
||||
}
|
||||
Vec3<REAL> Cross(Vec3<REAL> const & x) const {
|
||||
return Vec3<REAL>(p[1]*x.p[2] - p[2]*x.p[1],
|
||||
p[2]*x.p[0] - p[0]*x.p[2],
|
||||
p[0]*x.p[1] - p[1]*x.p[0]);
|
||||
}
|
||||
REAL Dot(Vec3<REAL> const & x) const {
|
||||
return p[0]*x.p[0] + p[1]*x.p[1] + p[2]*x.p[2];
|
||||
}
|
||||
REAL Length() const {
|
||||
return std::sqrt(this->Dot(*this));
|
||||
}
|
||||
|
||||
// Static method to compute normal vector:
|
||||
static
|
||||
Vec3<REAL> ComputeNormal(Vec3<REAL> const & Du, Vec3<REAL> const & Dv,
|
||||
REAL eps = 0.0f) {
|
||||
Vec3<REAL> N = Du.Cross(Dv);
|
||||
REAL lenSqrd = N.Dot(N);
|
||||
if (lenSqrd <= eps) return Vec3<REAL>(0.0f, 0.0f, 0.0f);
|
||||
return N * (1.0f / std::sqrt(lenSqrd));
|
||||
}
|
||||
|
||||
// Member variables (XYZ coordinates):
|
||||
REAL p[3];
|
||||
};
|
||||
|
||||
typedef Vec3<float> Vec3f;
|
||||
typedef Vec3<double> Vec3d;
|
||||
|
||||
|
||||
//
|
||||
// Simple struct to hold the results of a face evaluation:
|
||||
//
|
||||
template <typename REAL>
|
||||
struct EvalResults {
|
||||
EvalResults() : evalPosition(true),
|
||||
eval1stDeriv(true),
|
||||
eval2ndDeriv(false),
|
||||
evalUV(false),
|
||||
useStencils(false) { }
|
||||
|
||||
bool evalPosition;
|
||||
bool eval1stDeriv;
|
||||
bool eval2ndDeriv;
|
||||
bool evalUV;
|
||||
bool useStencils;
|
||||
|
||||
std::vector< Vec3<REAL> > p;
|
||||
std::vector< Vec3<REAL> > du;
|
||||
std::vector< Vec3<REAL> > dv;
|
||||
std::vector< Vec3<REAL> > duu;
|
||||
std::vector< Vec3<REAL> > duv;
|
||||
std::vector< Vec3<REAL> > dvv;
|
||||
|
||||
std::vector< Vec3<REAL> > uv;
|
||||
|
||||
void Resize(int size) {
|
||||
if (evalPosition) {
|
||||
p.resize(size);
|
||||
if (eval1stDeriv) {
|
||||
du.resize(size);
|
||||
dv.resize(size);
|
||||
if (eval2ndDeriv) {
|
||||
duu.resize(size);
|
||||
duv.resize(size);
|
||||
dvv.resize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (evalUV) {
|
||||
uv.resize(size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Simple struct to hold the differences between two vectors:
|
||||
//
|
||||
template <typename REAL>
|
||||
class VectorDelta {
|
||||
public:
|
||||
typedef std::vector< Vec3<REAL> > VectorVec3;
|
||||
|
||||
public:
|
||||
// Member variables:
|
||||
std::vector< Vec3<REAL> > const * vectorA;
|
||||
std::vector< Vec3<REAL> > const * vectorB;
|
||||
|
||||
int numDeltas;
|
||||
REAL maxDelta;
|
||||
REAL tolerance;
|
||||
|
||||
public:
|
||||
VectorDelta(REAL epsilon = 0.0f) :
|
||||
vectorA(0), vectorB(0),
|
||||
numDeltas(0), maxDelta(0.0f),
|
||||
tolerance(epsilon) { }
|
||||
|
||||
void
|
||||
Compare(VectorVec3 const & a, VectorVec3 const & b) {
|
||||
|
||||
assert(a.size() == b.size());
|
||||
|
||||
vectorA = &a;
|
||||
vectorB = &b;
|
||||
|
||||
numDeltas = 0;
|
||||
maxDelta = 0.0f;
|
||||
|
||||
for (size_t i = 0; i < a.size(); ++i) {
|
||||
REAL const * ai = a[i].Coords();
|
||||
REAL const * bi = b[i].Coords();
|
||||
|
||||
REAL dx = std::abs(ai[0] - bi[0]);
|
||||
REAL dy = std::abs(ai[1] - bi[1]);
|
||||
REAL dz = std::abs(ai[2] - bi[2]);
|
||||
if ((dx > tolerance) || (dy > tolerance) || (dz > tolerance)) {
|
||||
++ numDeltas;
|
||||
|
||||
if (maxDelta < dx) maxDelta = dx;
|
||||
if (maxDelta < dy) maxDelta = dy;
|
||||
if (maxDelta < dz) maxDelta = dz;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
class FaceDelta {
|
||||
public:
|
||||
// Member variables:
|
||||
bool hasDeltas;
|
||||
bool hasGeomDeltas;
|
||||
bool hasUVDeltas;
|
||||
|
||||
int numPDeltas;
|
||||
int numD1Deltas;
|
||||
int numD2Deltas;
|
||||
int numUVDeltas;
|
||||
|
||||
REAL maxPDelta;
|
||||
REAL maxD1Delta;
|
||||
REAL maxD2Delta;
|
||||
REAL maxUVDelta;
|
||||
|
||||
public:
|
||||
FaceDelta() { Clear(); }
|
||||
|
||||
void Clear() {
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void AddPDelta(VectorDelta<REAL> const & pDelta) {
|
||||
if (pDelta.numDeltas) {
|
||||
numPDeltas = pDelta.numDeltas;
|
||||
maxPDelta = pDelta.maxDelta;
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddDuDelta(VectorDelta<REAL> const & duDelta) {
|
||||
if (duDelta.numDeltas) {
|
||||
numD1Deltas += duDelta.numDeltas;
|
||||
maxD1Delta = std::max(maxD1Delta, duDelta.maxDelta);
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddDvDelta(VectorDelta<REAL> const & dvDelta) {
|
||||
if (dvDelta.numDeltas) {
|
||||
numD1Deltas += dvDelta.numDeltas;
|
||||
maxD1Delta = std::max(maxD1Delta, dvDelta.maxDelta);
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddDuuDelta(VectorDelta<REAL> const & duuDelta) {
|
||||
if (duuDelta.numDeltas) {
|
||||
numD2Deltas += duuDelta.numDeltas;
|
||||
maxD2Delta = std::max(maxD2Delta, duuDelta.maxDelta);
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddDuvDelta(VectorDelta<REAL> const & duvDelta) {
|
||||
if (duvDelta.numDeltas) {
|
||||
numD2Deltas += duvDelta.numDeltas;
|
||||
maxD2Delta = std::max(maxD2Delta, duvDelta.maxDelta);
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddDvvDelta(VectorDelta<REAL> const & dvvDelta) {
|
||||
if (dvvDelta.numDeltas) {
|
||||
numD2Deltas += dvvDelta.numDeltas;
|
||||
maxD2Delta = std::max(maxD2Delta, dvvDelta.maxDelta);
|
||||
hasDeltas = hasGeomDeltas = true;
|
||||
}
|
||||
}
|
||||
void AddUVDelta(VectorDelta<REAL> const & uvDelta) {
|
||||
if (uvDelta.numDeltas) {
|
||||
numUVDeltas = uvDelta.numDeltas;
|
||||
maxUVDelta = uvDelta.maxDelta;
|
||||
hasDeltas = hasUVDeltas = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
class MeshDelta {
|
||||
public:
|
||||
// Member variables:
|
||||
int numFacesWithDeltas;
|
||||
int numFacesWithGeomDeltas;
|
||||
int numFacesWithUVDeltas;
|
||||
|
||||
int numFacesWithPDeltas;
|
||||
int numFacesWithD1Deltas;
|
||||
int numFacesWithD2Deltas;
|
||||
|
||||
REAL maxPDelta;
|
||||
REAL maxD1Delta;
|
||||
REAL maxD2Delta;
|
||||
REAL maxUVDelta;
|
||||
|
||||
public:
|
||||
MeshDelta() { Clear(); }
|
||||
|
||||
void Clear() {
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void AddFace(FaceDelta<REAL> const & faceDelta) {
|
||||
|
||||
numFacesWithDeltas += faceDelta.hasDeltas;
|
||||
numFacesWithGeomDeltas += faceDelta.hasGeomDeltas;
|
||||
numFacesWithUVDeltas += faceDelta.hasUVDeltas;
|
||||
|
||||
numFacesWithPDeltas += (faceDelta.numPDeltas > 0);
|
||||
numFacesWithD1Deltas += (faceDelta.numD1Deltas > 0);
|
||||
numFacesWithD2Deltas += (faceDelta.numD2Deltas > 0);
|
||||
|
||||
maxPDelta = std::max(maxPDelta, faceDelta.maxPDelta);
|
||||
maxD1Delta = std::max(maxD1Delta, faceDelta.maxD1Delta);
|
||||
maxD2Delta = std::max(maxD2Delta, faceDelta.maxD2Delta);
|
||||
maxUVDelta = std::max(maxUVDelta, faceDelta.maxUVDelta);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* OPENSUBDIV3_REGRESSION_BFR_EVALUATE_TYPES_H */
|
||||
Reference in New Issue
Block a user