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)
add_subdirectory(bfr_evaluate)
add_subdirectory(hbr_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_creases1.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_boundary.h"
@ -144,5 +147,6 @@
#include "loop_triangle_edgeonly.h"
#include "loop_xord_boundary.h"
#include "loop_xord_interior.h"
#include "loop_val2_interior.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.25 -0.5 1.25\n"
"\n"
"vt -0.5 -0.5\n"
"vt -0.17 -0.5\n"
"vt 0.17 -0.5\n"
"vt 0.5 -0.5\n"
"vt 0.5 -0.17\n"
"vt 0.5 0.17\n"
"vt 0.5 0.5\n"
"vt 0.17 0.5\n"
"vt -0.17 0.5\n"
"vt -0.5 0.5\n"
"vt -0.5 0.17\n"
"vt -0.5 -0.17\n"
"vt -0.17 -0.17\n"
"vt 0.17 -0.17\n"
"vt 0.17 0.17\n"
"vt -0.17 0.17\n"
"vt 0.0 0.0 \n"
"vt -1.75 0.75\n"
"vt -1.42 0.75\n"
"vt -1.08 0.75\n"
"vt -0.75 0.75\n"
"vt -0.75 1.08\n"
"vt -0.75 1.42\n"
"vt -0.75 1.75\n"
"vt -1.08 1.75\n"
"vt -1.42 1.75\n"
"vt -1.75 1.75\n"
"vt -1.75 1.42\n"
"vt -1.75 1.08\n"
"vt -1.42 1.08\n"
"vt -1.08 1.08\n"
"vt -1.08 1.42\n"
"vt -1.42 1.42\n"
"vt -1.25 1.25\n"
"\n"
"f 1/1 2/2 13/13 12/12\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 1.0\n"
"\n"
"vt 0 0\n"
"vt 0.25 0.25\n"
"vt -0.25 0.25\n"
"vt -0.25 -0.25\n"
"vt 0.25 -0.25\n"
"vt 0.5 0.5\n"
"vt -0.25 0.5\n"
"vt -0.5 0.5\n"
"vt -0.5 0.25\n"
"vt -0.5 -0.5\n"
"vt 0.25 -0.5\n"
"vt 0.5 -0.5\n"
"vt 0.5 -0.25\n"
"vt 0.0 1.25\n"
"vt 0.25 1.5\n"
"vt -0.25 1.5\n"
"vt -0.25 1.0\n"
"vt 0.25 1.0\n"
"vt 0.5 1.75\n"
"vt -0.25 1.75\n"
"vt -0.5 1.75\n"
"vt -0.5 1.5\n"
"vt -0.5 0.75\n"
"vt 0.25 0.75\n"
"vt 0.5 0.75\n"
"vt 0.5 1.0\n"
"\n"
"f 18/18 19/19 20/20 21/21\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 1.0 \n"
"\n"
"vt 0 0\n"
"vt 0.25 0.25\n"
"vt -0.25 0.25\n"
"vt -0.25 -0.25\n"
"vt 0.25 -0.25\n"
"vt 0.5 0.5\n"
"vt -0.25 0.5\n"
"vt -0.5 0.5\n"
"vt -0.5 0.25\n"
"vt -0.5 -0.5\n"
"vt 0.25 -0.5\n"
"vt 0.5 -0.5\n"
"vt 0.5 -0.25\n"
"vt 1.25 1.25\n"
"vt 1.50 1.5 \n"
"vt 1.0 1.5 \n"
"vt 1.0 1.0 \n"
"vt 1.5 1.0 \n"
"vt 1.75 1.75\n"
"vt 1.0 1.75\n"
"vt 0.75 1.75\n"
"vt 0.75 1.5 \n"
"vt 0.75 0.75\n"
"vt 1.5 0.75\n"
"vt 1.75 0.75\n"
"vt 1.75 1.0 \n"
"\n"
"f 31/31 32/32 33/33 34/34\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"
"#\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 -1.75 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.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.42 0.0 0.5\n"
"v -1.08 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"
"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 -1.75 -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.42 0.17\n"
"vt -1.08 0.17\n"
"vt -0.75 0.17\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 -1.31 -0.06\n"
"vt -1.19 0.06\n"
"\n"
"f 44/44 45/45 49/49 47/47\n"
"f 45/45 46/46 51/51 49/49\n"
"f 44/44 47/47 49/49 48/48\n"
"f 48/48 49/49 51/51 50/50\n"
"f 44/44 45/45 49/49 48/48\n"
"f 45/45 46/46 50/50 49/49\n"
"f 46/46 47/47 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"
"# Shape 5: center-middle\n"
"#\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.0\n"
"v 0.0 0.0 0.0\n"
"v 0.5 0.0 0.0\n"
"v -0.17 -0.5 -0.17\n"
"v -0.5 0.0 0.17\n"
"v 0.17 0.0 0.17\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.1 0.1 -0.1\n"
"\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.0\n"
"vt 0.0 0.0\n"
"vt 0.5 0.0\n"
"vt -0.17 -0.17\n"
"vt -0.5 0.17\n"
"vt 0.17 0.17\n"
"vt -0.5 0.5\n"
"vt 0.0 0.5\n"
"vt 0.5 0.5\n"
"vt -0.1 -0.1\n"
"\n"
"f 52/52 53/53 56/56 55/55\n"
"f 53/53 54/54 57/57 56/56\n"
"f 55/55 56/56 59/59 58/58\n"
"f 56/56 57/57 60/60 59/59\n"
"f 53/53 52/52 55/55 61/61\n"
"f 62/62 63/63 67/67 65/65\n"
"f 63/63 64/64 69/69 67/67\n"
"f 62/62 65/65 67/67 66/66\n"
"f 66/66 67/67 69/69 68/68\n"
"\n"
"#\n"
"# Shape 6: center-right\n"
"#\n"
"# - starts at vertex 52\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 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 1.25 0.0 0.5\n"
"v 1.75 0.0 0.5\n"
"v 0.75 -0.5 -0.5\n"
"\n"
"vt 0.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.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"
"f 62/62 63/63 64/64 65/65\n"
"f 62/62 65/65 64/64 63/63\n"
"f 70/70 71/71 74/74 73/73\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"
"# 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 -0.75 0.0 -0.75\n"
"\n"
"vt -0.5 -0.5\n"
"vt 0.0 -0.5\n"
"vt 0.5 -0.5\n"
"vt 0.0 0.0\n"
"vt -0.5 0.5\n"
"vt 0.0 0.5\n"
"vt 0.5 0.5\n"
"vt -1.75 -1.75\n"
"vt -1.25 -1.75\n"
"vt -0.75 -1.75\n"
"vt -1.25 -1.25\n"
"vt -1.75 -0.75\n"
"vt -1.25 -0.75\n"
"vt -0.75 -0.75\n"
"\n"
"f 66/66 67/67 69/69 71/71 70/70\n"
"f 67/67 68/68 72/72 71/71 69/69\n"
"f 80/80 81/81 83/83 85/85 84/84\n"
"f 81/81 82/82 86/86 85/85 83/83\n"
"\n"
"#\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.5 0.0 -0.75\n"
"\n"
"vt -0.5 -0.5\n"
"vt 0.0 -0.5\n"
"vt 0.0 -0.5\n"
"vt 0.5 -0.5\n"
"vt -0.5 0.5\n"
"vt 0.0 0.5\n"
"vt 0.0 0.5\n"
"vt 0.5 0.5\n"
"vt -0.5 -1.75\n"
"vt 0.0 -1.75\n"
"vt 0.0 -1.75\n"
"vt 0.5 -1.75\n"
"vt -0.5 -0.75\n"
"vt 0.0 -0.75\n"
"vt 0.0 -0.75\n"
"vt 0.5 -0.75\n"
"\n"
"f 73/73 74/74 75/75 79/79 78/78 77/77\n"
"f 80/80 78/78 79/79 75/75 74/74 76/76\n"
"f 87/87 88/88 89/89 93/93 92/92 91/91\n"
"f 94/94 92/92 93/93 89/89 88/88 90/90\n"
"\n"
"#\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 0.75 0.5 -0.75\n"
"\n"
"vt 0.375 0.000\n"
"vt 0.500 0.000\n"
"vt 0.625 0.000\n"
"vt 0.375 0.250\n"
"vt 0.625 0.250\n"
"vt 0.375 0.500\n"
"vt 0.625 0.500\n"
"vt 0.375 0.750\n"
"vt 0.500 0.750\n"
"vt 0.625 0.750\n"
"vt 0.375 1.000\n"
"vt 0.500 1.000\n"
"vt 0.625 1.000\n"
"vt 0.875 0.000\n"
"vt 0.875 0.250\n"
"vt 0.125 0.000\n"
"vt 0.125 0.250\n"
"vt 1.15 -1.65\n"
"vt 1.35 -1.65\n"
"vt 1.15 -1.45\n"
"vt 1.35 -1.45\n"
"vt 1.05 -1.25\n"
"vt 1.25 -1.25\n"
"vt 1.45 -1.25\n"
"vt 1.15 -1.05\n"
"vt 1.35 -1.05\n"
"vt 1.15 -0.85\n"
"vt 1.35 -0.85\n"
"vt 1.00 -1.15\n"
"vt 0.80 -1.15\n"
"vt 0.80 -1.35\n"
"vt 1.00 -1.35\n"
"vt 1.70 -1.15\n"
"vt 1.50 -1.15\n"
"vt 1.50 -1.35\n"
"vt 1.70 -1.35\n"
"\n"
"f 84/84 81/81 82/82 83/83 85/85\n"
"f 86/86 84/84 85/85 87/87\n"
"f 88/88 86/86 87/87 89/89\n"
"f 82/92 81/91 88/88 89/89 83/93\n"
"f 83/83 89/94 87/95 85/85\n"
"f 88/96 81/81 84/84 86/97\n"
"f 98/98 95/101 96/100 97/99 99/97\n"
"f 100/96 98/98 99/97 101/95\n"
"f 102/103 100/105 101/104 103/102\n"
"f 95/101 102/103 103/102 97/99 96/100\n"
"f 97/106 103/107 101/108 99/109\n"
"f 102/110 95/111 98/112 100/113\n"
"\n"
"t interpolateboundary 1/0/0 1\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"
;