Addition of Bfr interface (3 of 4): regression/bfr_evaluate

This commit is contained in:
Barry Fowler 2022-08-02 20:41:44 -07:00
parent 8cbc059e6b
commit e27fe41b01
16 changed files with 2929 additions and 122 deletions

View File

@ -26,6 +26,8 @@ add_subdirectory(common)
if (NOT NO_REGRESSION) if (NOT NO_REGRESSION)
add_subdirectory(bfr_evaluate)
add_subdirectory(hbr_regression) add_subdirectory(hbr_regression)
add_subdirectory(far_regression) add_subdirectory(far_regression)

View File

@ -0,0 +1,54 @@
#
# Copyright 2021 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.
#
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)

View File

@ -0,0 +1,208 @@
//
// Copyright 2021 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.
//
#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>;

View File

@ -0,0 +1,82 @@
//
// Copyright 2021 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.
//
#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;
};

View File

@ -0,0 +1,291 @@
//
// Copyright 2021 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.
//
#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.isolationLevel = primaryLevel;
refineOptions.secondaryLevel = 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>;

View File

@ -0,0 +1,83 @@
//
// Copyright 2021 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.
//
#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;
};

View File

@ -0,0 +1,99 @@
//
// Copyright 2021 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.
//
#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_chaikin1", catmark_chaikin1, 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));
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,149 @@
//
// Copyright 2021 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.
//
#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_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));
}

View File

@ -0,0 +1,954 @@
//
// Copyright 2021 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.
//
#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;
}

View File

@ -0,0 +1,313 @@
//
// Copyright 2021 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.
//
#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 */

View File

@ -106,6 +106,9 @@
#include "catmark_torus_creases0.h" #include "catmark_torus_creases0.h"
#include "catmark_torus_creases1.h" #include "catmark_torus_creases1.h"
#include "catmark_val2_interior.h" #include "catmark_val2_interior.h"
#include "catmark_val2_back2back.h"
#include "catmark_val2_foldover.h"
#include "catmark_val2_nonman.h"
#include "catmark_xord_interior.h" #include "catmark_xord_interior.h"
#include "catmark_xord_boundary.h" #include "catmark_xord_boundary.h"
@ -144,5 +147,6 @@
#include "loop_triangle_edgeonly.h" #include "loop_triangle_edgeonly.h"
#include "loop_xord_boundary.h" #include "loop_xord_boundary.h"
#include "loop_xord_interior.h" #include "loop_xord_interior.h"
#include "loop_val2_interior.h"
#endif // OPENSUBDIV_REGRESSION_SHAPES_ALL_H #endif // OPENSUBDIV_REGRESSION_SHAPES_ALL_H

View File

@ -0,0 +1,98 @@
//
// Copyright 2022 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.
//
static const std::string catmark_val2_back2back =
"#\n"
"# Four shapes ordered left->right and top->bottom in the XZ plane\n"
"#\n"
"# Shape 1: top-left\n"
"#\n"
"v -0.90 0 0.10\n"
"v -0.10 0 0.10\n"
"v -0.50 0 0.90\n"
"\n"
"vt -0.90 0.10\n"
"vt -0.10 0.10\n"
"vt -0.50 0.90\n"
"\n"
"f 1/1 2/2 3/3\n"
"f 3/3 2/2 1/1\n"
"\n"
"#\n"
"# Shape 2: top-right\n"
"#\n"
"v 0.10 0 0.10\n"
"v 0.90 0 0.10\n"
"v 0.90 0 0.90\n"
"v 0.10 0 0.90\n"
"\n"
"vt 0.10 0.10\n"
"vt 0.90 0.10\n"
"vt 0.90 0.90\n"
"vt 0.10 0.90\n"
"\n"
"f 4/4 5/5 6/6 7/7\n"
"f 7/7 6/6 5/5 4/4\n"
"\n"
"#\n"
"# Shape 3: bottom-left\n"
"#\n"
"v -0.70 0 -0.90\n"
"v -0.30 0 -0.90\n"
"v -0.10 0 -0.50\n"
"v -0.50 0 -0.10\n"
"v -0.90 0 -0.50\n"
"\n"
"vt -0.70 -0.90\n"
"vt -0.30 -0.90\n"
"vt -0.10 -0.50\n"
"vt -0.50 -0.10\n"
"vt -0.90 -0.50\n"
"\n"
"f 8/8 9/9 10/10 11/11 12/12\n"
"f 12/12 11/11 10/10 9/9 8/8\n"
"\n"
"#\n"
"# Shape 4: bottom-right\n"
"#\n"
"v 0.30 0 -0.90\n"
"v 0.70 0 -0.90\n"
"v 0.90 0 -0.50\n"
"v 0.70 0 -0.10\n"
"v 0.30 0 -0.10\n"
"v 0.10 0 -0.50\n"
"\n"
"vt 0.30 -0.90\n"
"vt 0.70 -0.90\n"
"vt 0.90 -0.50\n"
"vt 0.70 -0.10\n"
"vt 0.30 -0.10\n"
"vt 0.10 -0.50\n"
"\n"
"f 13/13 14/14 15/15 16/16 17/17 18/18\n"
"f 18/18 17/17 16/16 15/15 14/14 13/13\n"
"\n"
"t interpolateboundary 1/0/0 1\n"
"\n"
;

View File

@ -0,0 +1,207 @@
//
// Copyright 2022 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.
//
static const std::string catmark_val2_foldover =
"#\n"
"# Nine shapes ordered left->right and top->bottom in the XZ plane\n"
"#\n"
"# Shape 1: top-left\n"
"#\n"
"v -1.4 0.0 0.6\n"
"v -0.6 0.0 0.6\n"
"v -0.6 0.0 1.4\n"
"v -1.4 0.0 1.4\n"
"\n"
"vt -1.4 0.6\n"
"vt -0.6 0.6\n"
"vt -0.6 1.4\n"
"vt -1.4 1.4\n"
"\n"
"f 1/1 2/2 3/3 4/4\n"
"f 1/1 4/4 3/3\n"
"f 1/1 3/3 2/2\n"
"\n"
"#\n"
"# Shape 2: top-middle\n"
"#\n"
"v -0.4 0.0 0.6\n"
"v 0.4 0.0 0.6\n"
"v 0.4 0.0 1.4\n"
"v -0.4 0.0 1.4\n"
"\n"
"vt -0.4 0.6\n"
"vt 0.4 0.6\n"
"vt 0.4 1.4\n"
"vt -0.4 1.4\n"
"\n"
"f 5/5 6/6 7/7 8/8\n"
"f 5/5 8/8 7/7\n"
"\n"
"#\n"
"# Shape 3: top-right\n"
"#\n"
"v 0.8 0.0 0.6\n"
"v 1.2 0.0 0.6\n"
"v 1.4 0.0 1.0\n"
"v 1.0 0.0 1.4\n"
"v 0.6 0.0 1.0\n"
"\n"
"vt 0.8 0.6\n"
"vt 1.2 0.6\n"
"vt 1.4 1.0\n"
"vt 1.0 1.4\n"
"vt 0.6 1.0\n"
"\n"
"f 9/9 10/10 11/11 12/12 13/13\n"
"f 12/12 11/11 10/10 9/9 \n"
"f 12/12 9/9 13/13\n"
"\n"
"#\n"
"# Shape 4: center-left\n"
"#\n"
"v -1.2 0.0 -0.4\n"
"v -0.8 0.0 -0.4\n"
"v -0.6 0.0 0.0\n"
"v -1.0 0.0 0.4\n"
"v -1.4 0.0 0.0\n"
"\n"
"vt -1.2 -0.4\n"
"vt -0.8 -0.4\n"
"vt -0.6 0.0\n"
"vt -1.0 0.4\n"
"vt -1.4 0.0\n"
"\n"
"f 14/14 15/15 16/16 17/17 18/18\n"
"f 17/17 16/16 15/15\n"
"f 17/17 15/15 14/14\n"
"f 17/17 14/14 18/18\n"
"\n"
"#\n"
"# Shape 5: center-middle\n"
"#\n"
"v -0.2 0.0 -0.4\n"
"v 0.2 0.0 -0.4\n"
"v 0.4 0.0 0.0\n"
"v 0.0 0.0 0.4\n"
"v -0.4 0.0 0.0\n"
"\n"
"vt -0.2 -0.4\n"
"vt 0.2 -0.4\n"
"vt 0.4 0.0\n"
"vt 0.0 0.4\n"
"vt -0.4 0.0\n"
"\n"
"f 19/19 20/20 21/21 22/22 23/23\n"
"f 22/22 19/19 23/23\n"
"\n"
"#\n"
"# Shape 6: center-right\n"
"#\n"
"v 0.8 0.0 -0.4\n"
"v 1.2 0.0 -0.4\n"
"v 1.4 0.0 0.0\n"
"v 1.2 0.0 0.4\n"
"v 0.8 0.0 0.4\n"
"v 0.6 0.0 0.0\n"
"\n"
"vt 0.8 -0.4\n"
"vt 1.2 -0.4\n"
"vt 1.4 0.0\n"
"vt 1.2 0.4\n"
"vt 0.8 0.4\n"
"vt 0.6 0.0\n"
"\n"
"f 24/24 25/25 26/26 27/27 28/28 29/29\n"
"f 29/29 28/28 27/27 26/26\n"
"f 29/29 26/26 25/25 24/24\n"
"\n"
"#\n"
"# Shape 7: bottom-left\n"
"#\n"
"v -1.2 0.0 -1.4\n"
"v -0.8 0.0 -1.4\n"
"v -0.6 0.0 -1.0\n"
"v -0.8 0.0 -0.6\n"
"v -1.2 0.0 -0.6\n"
"v -1.4 0.0 -1.0\n"
"\n"
"vt -1.2 -1.4\n"
"vt -0.8 -1.4\n"
"vt -0.6 -1.0\n"
"vt -0.8 -0.6\n"
"vt -1.2 -0.6\n"
"vt -1.4 -1.0\n"
"\n"
"f 30/30 31/31 32/32 33/33 34/34 35/35\n"
"f 35/35 34/34 33/33\n"
"f 35/35 33/33 32/32\n"
"f 35/35 32/32 31/31\n"
"f 35/35 31/31 30/30\n"
"\n"
"#\n"
"# Shape 8: bottom-middle\n"
"#\n"
"v -0.2 0.0 -1.4\n"
"v 0.2 0.0 -1.4\n"
"v 0.4 0.0 -1.0\n"
"v 0.2 0.0 -0.6\n"
"v -0.2 0.0 -0.6\n"
"v -0.4 0.0 -1.0\n"
"\n"
"vt -0.2 -1.4\n"
"vt 0.2 -1.4\n"
"vt 0.4 -1.0\n"
"vt 0.2 -0.6\n"
"vt -0.2 -0.6\n"
"vt -0.4 -1.0\n"
"\n"
"f 36/36 37/37 38/38 39/39 40/40 41/41\n"
"f 41/41 40/40 39/39\n"
"f 41/41 37/37 36/36\n"
"\n"
"#\n"
"# Shape 9: bottom-right\n"
"#\n"
"v 0.8 0.0 -1.4\n"
"v 1.2 0.0 -1.4\n"
"v 1.4 0.0 -1.0\n"
"v 1.2 0.0 -0.6\n"
"v 0.8 0.0 -0.6\n"
"v 0.6 0.0 -1.0\n"
"\n"
"vt 0.8 -1.4\n"
"vt 1.2 -1.4\n"
"vt 1.4 -1.0\n"
"vt 1.2 -0.6\n"
"vt 0.8 -0.6\n"
"vt 0.6 -1.0\n"
"\n"
"f 42/42 43/43 44/44 45/45 46/46 47/47\n"
"f 47/47 46/46 45/45\n"
"f 47/47 45/45 44/44 43/43\n"
"f 47/47 43/43 42/42\n"
"\n"
"t interpolateboundary 1/0/0 1\n"
"\n"
;

View File

@ -46,23 +46,23 @@ static const std::string catmark_val2_interior =
"v -1.42 0.0 1.42\n" "v -1.42 0.0 1.42\n"
"v -1.25 -0.5 1.25\n" "v -1.25 -0.5 1.25\n"
"\n" "\n"
"vt -0.5 -0.5\n" "vt -1.75 0.75\n"
"vt -0.17 -0.5\n" "vt -1.42 0.75\n"
"vt 0.17 -0.5\n" "vt -1.08 0.75\n"
"vt 0.5 -0.5\n" "vt -0.75 0.75\n"
"vt 0.5 -0.17\n" "vt -0.75 1.08\n"
"vt 0.5 0.17\n" "vt -0.75 1.42\n"
"vt 0.5 0.5\n" "vt -0.75 1.75\n"
"vt 0.17 0.5\n" "vt -1.08 1.75\n"
"vt -0.17 0.5\n" "vt -1.42 1.75\n"
"vt -0.5 0.5\n" "vt -1.75 1.75\n"
"vt -0.5 0.17\n" "vt -1.75 1.42\n"
"vt -0.5 -0.17\n" "vt -1.75 1.08\n"
"vt -0.17 -0.17\n" "vt -1.42 1.08\n"
"vt 0.17 -0.17\n" "vt -1.08 1.08\n"
"vt 0.17 0.17\n" "vt -1.08 1.42\n"
"vt -0.17 0.17\n" "vt -1.42 1.42\n"
"vt 0.0 0.0 \n" "vt -1.25 1.25\n"
"\n" "\n"
"f 1/1 2/2 13/13 12/12\n" "f 1/1 2/2 13/13 12/12\n"
"f 2/2 3/3 14/14 13/13\n" "f 2/2 3/3 14/14 13/13\n"
@ -92,19 +92,19 @@ static const std::string catmark_val2_interior =
"v 0.5 0.0 0.75\n" "v 0.5 0.0 0.75\n"
"v 0.5 0.0 1.0\n" "v 0.5 0.0 1.0\n"
"\n" "\n"
"vt 0 0\n" "vt 0.0 1.25\n"
"vt 0.25 0.25\n" "vt 0.25 1.5\n"
"vt -0.25 0.25\n" "vt -0.25 1.5\n"
"vt -0.25 -0.25\n" "vt -0.25 1.0\n"
"vt 0.25 -0.25\n" "vt 0.25 1.0\n"
"vt 0.5 0.5\n" "vt 0.5 1.75\n"
"vt -0.25 0.5\n" "vt -0.25 1.75\n"
"vt -0.5 0.5\n" "vt -0.5 1.75\n"
"vt -0.5 0.25\n" "vt -0.5 1.5\n"
"vt -0.5 -0.5\n" "vt -0.5 0.75\n"
"vt 0.25 -0.5\n" "vt 0.25 0.75\n"
"vt 0.5 -0.5\n" "vt 0.5 0.75\n"
"vt 0.5 -0.25\n" "vt 0.5 1.0\n"
"\n" "\n"
"f 18/18 19/19 20/20 21/21\n" "f 18/18 19/19 20/20 21/21\n"
"f 18/18 21/21 22/22 19/19\n" "f 18/18 21/21 22/22 19/19\n"
@ -132,19 +132,19 @@ static const std::string catmark_val2_interior =
"v 1.75 0.0 0.75\n" "v 1.75 0.0 0.75\n"
"v 1.75 0.0 1.0 \n" "v 1.75 0.0 1.0 \n"
"\n" "\n"
"vt 0 0\n" "vt 1.25 1.25\n"
"vt 0.25 0.25\n" "vt 1.50 1.5 \n"
"vt -0.25 0.25\n" "vt 1.0 1.5 \n"
"vt -0.25 -0.25\n" "vt 1.0 1.0 \n"
"vt 0.25 -0.25\n" "vt 1.5 1.0 \n"
"vt 0.5 0.5\n" "vt 1.75 1.75\n"
"vt -0.25 0.5\n" "vt 1.0 1.75\n"
"vt -0.5 0.5\n" "vt 0.75 1.75\n"
"vt -0.5 0.25\n" "vt 0.75 1.5 \n"
"vt -0.5 -0.5\n" "vt 0.75 0.75\n"
"vt 0.25 -0.5\n" "vt 1.5 0.75\n"
"vt 0.5 -0.5\n" "vt 1.75 0.75\n"
"vt 0.5 -0.25\n" "vt 1.75 1.0 \n"
"\n" "\n"
"f 31/31 32/32 33/33 34/34\n" "f 31/31 32/32 33/33 34/34\n"
"f 31/31 34/34 35/35 32/32\n" "f 31/31 34/34 35/35 32/32\n"
@ -164,74 +164,112 @@ static const std::string catmark_val2_interior =
"# Shape 4: center-left\n" "# Shape 4: center-left\n"
"#\n" "#\n"
"v -1.75 0.0 -0.5\n" "v -1.75 0.0 -0.5\n"
"v -1.42 0.0 -0.5\n"
"v -1.08 0.0 -0.5\n" "v -1.08 0.0 -0.5\n"
"v -0.75 0.0 -0.5\n" "v -0.75 0.0 -0.5\n"
"v -1.75 0.0 -0.17\n"
"v -1.42 -0.5 -0.17\n" "v -1.42 -0.5 -0.17\n"
"v -1.08 -0.5 -0.17\n"
"v -0.75 0.0 -0.17\n"
"v -1.75 0.0 0.17\n" "v -1.75 0.0 0.17\n"
"v -1.08 0.0 0.17\n" "v -1.42 -0.5 0.17\n"
"v -1.08 -0.5 0.17\n"
"v -0.75 0.0 0.17\n"
"v -1.75 0.0 0.5\n" "v -1.75 0.0 0.5\n"
"v -1.42 0.0 0.5\n"
"v -1.08 0.0 0.5\n"
"v -0.75 0.0 0.5\n" "v -0.75 0.0 0.5\n"
"v -1.31 -0.5 -0.06\n"
"v -1.19 -0.5 0.06\n"
"\n" "\n"
"vt -1.75 -0.5\n" "vt -1.75 -0.5\n"
"vt -1.42 -0.5\n"
"vt -1.08 -0.5\n" "vt -1.08 -0.5\n"
"vt -0.75 -0.5\n" "vt -0.75 -0.5\n"
"vt -1.75 -0.17\n"
"vt -1.42 -0.17\n" "vt -1.42 -0.17\n"
"vt -1.08 -0.17\n"
"vt -0.75 -0.17\n"
"vt -1.75 0.17\n" "vt -1.75 0.17\n"
"vt -1.42 0.17\n"
"vt -1.08 0.17\n" "vt -1.08 0.17\n"
"vt -0.75 0.17\n"
"vt -1.75 0.5\n" "vt -1.75 0.5\n"
"vt -1.42 0.5\n"
"vt -1.08 0.5\n"
"vt -0.75 0.5\n" "vt -0.75 0.5\n"
"vt -1.31 -0.06\n"
"vt -1.19 0.06\n"
"\n" "\n"
"f 44/44 45/45 49/49 47/47\n" "f 44/44 45/45 49/49 48/48\n"
"f 45/45 46/46 51/51 49/49\n" "f 45/45 46/46 50/50 49/49\n"
"f 44/44 47/47 49/49 48/48\n" "f 46/46 47/47 51/51 50/50\n"
"f 48/48 49/49 51/51 50/50\n" "f 48/48 49/49 53/53 52/52\n"
"f 50/50 60/60 53/53 49/49\n"
"f 50/50 54/54 53/53 61/61\n"
"f 50/50 61/61 53/53 60/60\n"
"f 50/50 51/51 55/55 54/54\n"
"f 52/52 53/53 57/57 56/56\n"
"f 53/53 54/54 58/58 57/57\n"
"f 54/54 55/55 59/59 58/58\n"
"\n" "\n"
"#\n" "#\n"
"# Shape 5: center-middle\n" "# Shape 5: center-middle\n"
"#\n" "#\n"
"v -0.5 0.0 -0.5\n" "v -0.5 0.0 -0.5\n"
"v 0.0 0.0 -0.5\n" "v 0.17 0.0 -0.5\n"
"v 0.5 0.0 -0.5\n" "v 0.5 0.0 -0.5\n"
"v -0.5 0.0 0.0\n" "v -0.17 -0.5 -0.17\n"
"v 0.0 0.0 0.0\n" "v -0.5 0.0 0.17\n"
"v 0.5 0.0 0.0\n" "v 0.17 0.0 0.17\n"
"v -0.5 0.0 0.5\n" "v -0.5 0.0 0.5\n"
"v 0.0 0.0 0.5\n" "v 0.5 0.0 0.5\n"
"v 0.5 0.0 0.5\n"
"v -0.1 0.1 -0.1\n"
"\n" "\n"
"vt -0.5 -0.5\n" "vt -0.5 -0.5\n"
"vt 0.0 -0.5\n" "vt 0.17 -0.5\n"
"vt 0.5 -0.5\n" "vt 0.5 -0.5\n"
"vt -0.5 0.0\n" "vt -0.17 -0.17\n"
"vt 0.0 0.0\n" "vt -0.5 0.17\n"
"vt 0.5 0.0\n" "vt 0.17 0.17\n"
"vt -0.5 0.5\n" "vt -0.5 0.5\n"
"vt 0.0 0.5\n" "vt 0.5 0.5\n"
"vt 0.5 0.5\n"
"vt -0.1 -0.1\n"
"\n" "\n"
"f 52/52 53/53 56/56 55/55\n" "f 62/62 63/63 67/67 65/65\n"
"f 53/53 54/54 57/57 56/56\n" "f 63/63 64/64 69/69 67/67\n"
"f 55/55 56/56 59/59 58/58\n" "f 62/62 65/65 67/67 66/66\n"
"f 56/56 57/57 60/60 59/59\n" "f 66/66 67/67 69/69 68/68\n"
"f 53/53 52/52 55/55 61/61\n"
"\n" "\n"
"#\n" "#\n"
"# Shape 6: center-right\n" "# Shape 6: center-right\n"
"#\n" "#\n"
"# - starts at vertex 52\n"
"v 0.75 0.0 -0.5\n" "v 0.75 0.0 -0.5\n"
"v 1.25 0.0 -0.5\n"
"v 1.75 0.0 -0.5\n" "v 1.75 0.0 -0.5\n"
"v 1.75 0.0 0.5\n" "v 0.75 0.0 0.0\n"
"v 1.25 0.0 0.0\n"
"v 1.75 0.0 0.0\n"
"v 0.75 0.0 0.5\n" "v 0.75 0.0 0.5\n"
"v 1.25 0.0 0.5\n"
"v 1.75 0.0 0.5\n"
"v 0.75 -0.5 -0.5\n"
"\n" "\n"
"vt 0.75 -0.5\n" "vt 0.75 -0.5\n"
"vt 1.75 -0.5\n" "vt 1.25 -0.5\n"
"vt 1.75 0.5\n" "vt 1.75 -0.5\n"
"vt 0.75 0.5\n" "vt 0.75 0.0\n"
"vt 1.25 0.0\n"
"vt 1.75 0.0\n"
"vt 0.75 0.5\n"
"vt 1.25 0.5\n"
"vt 1.75 0.5\n"
"vt 0.75 -0.5\n"
"\n" "\n"
"f 62/62 63/63 64/64 65/65\n" "f 70/70 71/71 74/74 73/73\n"
"f 62/62 65/65 64/64 63/63\n" "f 71/71 72/72 75/75 74/74\n"
"f 73/73 74/74 77/77 76/76\n"
"f 74/74 75/75 78/78 77/77\n"
"f 71/71 70/70 73/73 79/79\n"
"\n" "\n"
"#\n" "#\n"
"# Shape 7: bottom-left\n" "# Shape 7: bottom-left\n"
@ -244,16 +282,16 @@ static const std::string catmark_val2_interior =
"v -1.25 0.0 -0.75\n" "v -1.25 0.0 -0.75\n"
"v -0.75 0.0 -0.75\n" "v -0.75 0.0 -0.75\n"
"\n" "\n"
"vt -0.5 -0.5\n" "vt -1.75 -1.75\n"
"vt 0.0 -0.5\n" "vt -1.25 -1.75\n"
"vt 0.5 -0.5\n" "vt -0.75 -1.75\n"
"vt 0.0 0.0\n" "vt -1.25 -1.25\n"
"vt -0.5 0.5\n" "vt -1.75 -0.75\n"
"vt 0.0 0.5\n" "vt -1.25 -0.75\n"
"vt 0.5 0.5\n" "vt -0.75 -0.75\n"
"\n" "\n"
"f 66/66 67/67 69/69 71/71 70/70\n" "f 80/80 81/81 83/83 85/85 84/84\n"
"f 67/67 68/68 72/72 71/71 69/69\n" "f 81/81 82/82 86/86 85/85 83/83\n"
"\n" "\n"
"#\n" "#\n"
"# Shape 8: bottom-middle\n" "# Shape 8: bottom-middle\n"
@ -267,17 +305,17 @@ static const std::string catmark_val2_interior =
"v 0.0 -0.5 -0.75\n" "v 0.0 -0.5 -0.75\n"
"v 0.5 0.0 -0.75\n" "v 0.5 0.0 -0.75\n"
"\n" "\n"
"vt -0.5 -0.5\n" "vt -0.5 -1.75\n"
"vt 0.0 -0.5\n" "vt 0.0 -1.75\n"
"vt 0.0 -0.5\n" "vt 0.0 -1.75\n"
"vt 0.5 -0.5\n" "vt 0.5 -1.75\n"
"vt -0.5 0.5\n" "vt -0.5 -0.75\n"
"vt 0.0 0.5\n" "vt 0.0 -0.75\n"
"vt 0.0 0.5\n" "vt 0.0 -0.75\n"
"vt 0.5 0.5\n" "vt 0.5 -0.75\n"
"\n" "\n"
"f 73/73 74/74 75/75 79/79 78/78 77/77\n" "f 87/87 88/88 89/89 93/93 92/92 91/91\n"
"f 80/80 78/78 79/79 75/75 74/74 76/76\n" "f 94/94 92/92 93/93 89/89 88/88 90/90\n"
"\n" "\n"
"#\n" "#\n"
"# Shape 9: bottom-right\n" "# Shape 9: bottom-right\n"
@ -292,30 +330,32 @@ static const std::string catmark_val2_interior =
"v 1.75 0.5 -0.75\n" "v 1.75 0.5 -0.75\n"
"v 0.75 0.5 -0.75\n" "v 0.75 0.5 -0.75\n"
"\n" "\n"
"vt 0.375 0.000\n" "vt 1.15 -1.65\n"
"vt 0.500 0.000\n" "vt 1.35 -1.65\n"
"vt 0.625 0.000\n" "vt 1.15 -1.45\n"
"vt 0.375 0.250\n" "vt 1.35 -1.45\n"
"vt 0.625 0.250\n" "vt 1.05 -1.25\n"
"vt 0.375 0.500\n" "vt 1.25 -1.25\n"
"vt 0.625 0.500\n" "vt 1.45 -1.25\n"
"vt 0.375 0.750\n" "vt 1.15 -1.05\n"
"vt 0.500 0.750\n" "vt 1.35 -1.05\n"
"vt 0.625 0.750\n" "vt 1.15 -0.85\n"
"vt 0.375 1.000\n" "vt 1.35 -0.85\n"
"vt 0.500 1.000\n" "vt 1.00 -1.15\n"
"vt 0.625 1.000\n" "vt 0.80 -1.15\n"
"vt 0.875 0.000\n" "vt 0.80 -1.35\n"
"vt 0.875 0.250\n" "vt 1.00 -1.35\n"
"vt 0.125 0.000\n" "vt 1.70 -1.15\n"
"vt 0.125 0.250\n" "vt 1.50 -1.15\n"
"vt 1.50 -1.35\n"
"vt 1.70 -1.35\n"
"\n" "\n"
"f 84/84 81/81 82/82 83/83 85/85\n" "f 98/98 95/101 96/100 97/99 99/97\n"
"f 86/86 84/84 85/85 87/87\n" "f 100/96 98/98 99/97 101/95\n"
"f 88/88 86/86 87/87 89/89\n" "f 102/103 100/105 101/104 103/102\n"
"f 82/92 81/91 88/88 89/89 83/93\n" "f 95/101 102/103 103/102 97/99 96/100\n"
"f 83/83 89/94 87/95 85/85\n" "f 97/106 103/107 101/108 99/109\n"
"f 88/96 81/81 84/84 86/97\n" "f 102/110 95/111 98/112 100/113\n"
"\n" "\n"
"t interpolateboundary 1/0/0 1\n" "t interpolateboundary 1/0/0 1\n"
"\n" "\n"

View File

@ -0,0 +1,125 @@
//
// Copyright 2022 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.
//
static const std::string catmark_val2_nonman =
"#\n"
"# Four shapes ordered left->right and top->bottom in the XZ plane\n"
"#\n"
"# Shape 1: top-left\n"
"#\n"
"v -0.70 0 0.30\n"
"v -0.30 0 0.30\n"
"v -0.30 0 0.70\n"
"v -0.70 0 0.70\n"
"v -0.70 0.2 0.10\n"
"v -0.30 0.2 0.10\n"
"v -0.70 -0.2 0.10\n"
"v -0.30 -0.2 0.10\n"
"\n"
"vt -0.70 0.30\n"
"vt -0.30 0.30\n"
"vt -0.30 0.70\n"
"vt -0.70 0.70\n"
"vt -0.70 0.10\n"
"vt -0.30 0.10\n"
"vt -0.70 0.10\n"
"vt -0.30 0.10\n"
"\n"
"f 1/1 2/2 3/3 4/4\n"
"f 4/4 3/3 2/2 1/1\n"
"f 1/1 2/2 6/6 5/5\n"
"f 2/2 1/1 7/7 8/8\n"
"\n"
"#\n"
"# Shape 2: top-right\n"
"#\n"
"v 0.30 0 0.30\n"
"v 0.70 0 0.30\n"
"v 0.50 0 0.70\n"
"v 0.50 0 0.70\n"
"v 0.30 0.2 0.10\n"
"v 0.70 0.2 0.10\n"
"v 0.30 -0.2 0.10\n"
"v 0.70 -0.2 0.10\n"
"\n"
"vt 0.30 0.30\n"
"vt 0.70 0.30\n"
"vt 0.50 0.70\n"
"vt 0.50 0.70\n"
"vt 0.30 0.10\n"
"vt 0.70 0.10\n"
"vt 0.30 0.10\n"
"vt 0.70 0.10\n"
"\n"
"f 9/9 10/10 11/11\n"
"f 11/11 10/10 9/9\n"
"f 9/9 10/10 14/14 13/13\n"
"f 10/10 9/9 15/15 16/16\n"
"\n"
"#\n"
"# Shape 3: bottom-left\n"
"#\n"
"v -0.70 0 -0.70\n"
"v -0.30 0 -0.70\n"
"v -0.30 0 -0.30\n"
"v -0.70 0 -0.30\n"
"v -0.70 -0.2 -0.90\n"
"v -0.30 -0.2 -0.90\n"
"\n"
"vt -0.70 -0.70\n"
"vt -0.30 -0.70\n"
"vt -0.30 -0.30\n"
"vt -0.70 -0.30\n"
"vt -0.70 -0.90\n"
"vt -0.30 -0.90\n"
"\n"
"f 17/17 18/18 19/19 20/20\n"
"f 20/20 19/19 18/18 17/17\n"
"f 21/21 22/22 17/17\n"
"\n"
"#\n"
"# Shape 4: bottom-right\n"
"#\n"
"v 0.30 0 -0.70\n"
"v 0.70 0 -0.70\n"
"v 0.70 0 -0.30\n"
"v 0.30 0 -0.30\n"
"v 0.30 -0.2 -0.90\n"
"v 0.70 -0.2 -0.90\n"
"\n"
"vt 0.30 -0.70\n"
"vt 0.70 -0.70\n"
"vt 0.70 -0.30\n"
"vt 0.30 -0.30\n"
"vt 0.30 -0.90\n"
"vt 0.70 -0.90\n"
"\n"
"f 23/23 24/24 25/25 26/26\n"
"f 26/26 25/25 24/24 23/23\n"
"f 27/27 28/28 23/23\n"
"f 27/27 28/28 24/24\n"
"\n"
"t interpolateboundary 1/0/0 1\n"
"\n"
;

View File

@ -0,0 +1,98 @@
//
// Copyright 2022 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.
//
static const std::string loop_val2_interior =
"#\n"
"# Shape 1:\n"
"#\n"
"v -1.75 0.0 0.0\n"
"v -0.75 0.0 0.0\n"
"v -1.25 0.0 0.866\n"
"v -1.75 -0.75 0.866\n"
"v -0.75 -0.75 0.866\n"
"v -1.75 0.75 0.866\n"
"v -0.75 0.75 0.866\n"
"\n"
"vt 0.05 0.10\n"
"vt 0.45 0.10\n"
"vt 0.25 0.40\n"
"vt 0.55 0.10\n"
"vt 0.95 0.10\n"
"vt 0.75 0.40\n"
"vt 0.20 0.90\n"
"vt 0.20 0.50\n"
"vt 0.50 0.70\n"
"vt 0.80 0.50\n"
"vt 0.80 0.90\n"
"\n"
"f 1/1 2/2 3/3\n"
"f 2/4 1/5 3/6\n"
"f 3/9 4/7 5/8\n"
"f 3/9 7/10 6/11\n"
"\n"
"#\n"
"# Shape 2:\n"
"#\n"
"v -0.5 0.0 0.0\n"
"v 0.5 0.0 0.0\n"
"v 0.0 0.0 0.866\n"
"\n"
"vt 1.05 0.30\n"
"vt 1.45 0.30\n"
"vt 1.25 0.60\n"
"vt 1.55 0.30\n"
"vt 1.95 0.30\n"
"vt 1.75 0.60\n"
"\n"
"f 8/12 9/13 10/14\n"
"f 9/15 8/16 10/17\n"
"\n"
"#\n"
"# Shape 3:\n"
"#\n"
"v 0.75 0.0 0.0\n"
"v 1.75 0.0 0.0\n"
"v 1.25 0.0 0.866\n"
"v 1.25 -0.75 0.0\n"
"v 1.25 0.75 0.0\n"
"\n"
"vt 2.05 0.60\n"
"vt 2.45 0.60\n"
"vt 2.25 0.90\n"
"vt 2.55 0.60\n"
"vt 2.95 0.60\n"
"vt 2.75 0.90\n"
"vt 2.10 0.30\n"
"vt 2.90 0.30\n"
"vt 2.50 0.10\n"
"vt 2.50 0.50\n"
"\n"
"f 11/18 12/19 13/20\n"
"f 12/21 11/22 13/23\n"
"f 14/24 12/26 11/27\n"
"f 15/25 11/27 12/26\n"
"\n"
"t interpolateboundary 1/0/0 1\n"
"\n"
;