Merge pull request #564 from takahito-tejima/singlecrease

Fix screen-space tessellation on single crease patch.
This commit is contained in:
David G Yu 2015-05-30 23:58:39 -07:00
commit 4bf1ef722c
6 changed files with 679 additions and 90 deletions

View File

@ -91,6 +91,7 @@ static void initShapes() {
g_defaultShapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark ) );
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) );

View File

@ -113,7 +113,7 @@ OSD_USER_VARYING_ATTRIBUTE_DECLARE
out block {
OutputVertex v;
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
vec2 vSegments;
#endif
OSD_USER_VARYING_DECLARE
} outpt;
@ -123,7 +123,7 @@ void main()
outpt.v.position = ModelViewMatrix * position;
outpt.v.patchCoord = vec4(0);
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
outpt.sharpness = 0;
outpt.vSegments = vec2(0);
#endif
OSD_USER_VARYING_PER_VERTEX();
}
@ -156,7 +156,7 @@ layout(triangle_strip, max_vertices = EDGE_VERTS) out;
in block {
OutputVertex v;
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
vec2 vSegments;
#endif
OSD_USER_VARYING_DECLARE
} inpt[EDGE_VERTS];
@ -165,7 +165,7 @@ out block {
OutputVertex v;
noperspective out vec4 edgeDistance;
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
vec2 vSegments;
#endif
OSD_USER_VARYING_DECLARE
} outpt;
@ -181,7 +181,7 @@ void emit(int index, vec3 normal)
#endif
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
outpt.sharpness = inpt[index].sharpness;
outpt.vSegments = inpt[index].vSegments;
#endif
#ifdef VARYING_COLOR
@ -315,7 +315,7 @@ in block {
OutputVertex v;
noperspective in vec4 edgeDistance;
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
vec2 vSegments;
#endif
OSD_USER_VARYING_DECLARE
} inpt;
@ -449,7 +449,7 @@ getAdaptivePatchColor(ivec3 patchParam)
int patchType = 0;
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
if (inpt.sharpness > 0) {
if (inpt.vSegments.y > 0) {
patchType = 1;
}
#elif defined OSD_PATCH_GREGORY

View File

@ -57,7 +57,7 @@ in block {
} inpt[];
out block {
OsdPerPatchVertexBSpline v;
OsdPerPatchVertexBezier v;
OSD_USER_VARYING_DECLARE
} outpt[];
@ -87,13 +87,37 @@ void main()
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
// Gather bezier control points to compute limit surface tess levels
OsdPerPatchVertexBezier cpBezier[16];
#if 0
// XXX: this doesn't work on nvidia driver 34x.
for (int i=0; i<16; ++i) {
cv[i] = outpt[i].v.P.xyz;
cpBezier[i] = outpt[i].v;
}
#else
cpBezier[0] = outpt[0].v;
cpBezier[1] = outpt[1].v;
cpBezier[2] = outpt[2].v;
cpBezier[3] = outpt[3].v;
cpBezier[4] = outpt[4].v;
cpBezier[5] = outpt[5].v;
cpBezier[6] = outpt[6].v;
cpBezier[7] = outpt[7].v;
cpBezier[8] = outpt[8].v;
cpBezier[9] = outpt[9].v;
cpBezier[10] = outpt[10].v;
cpBezier[11] = outpt[11].v;
cpBezier[12] = outpt[12].v;
cpBezier[13] = outpt[13].v;
cpBezier[14] = outpt[14].v;
cpBezier[15] = outpt[15].v;
#endif
OsdGetTessLevels(cv, patchParam, tessLevelOuter, tessLevelInner,
OsdGetTessLevelsAdaptiveLimitPoints(cpBezier, patchParam,
tessLevelOuter, tessLevelInner,
tessOuterLo, tessOuterHi);
#else
OsdGetTessLevelsUniform(patchParam, tessLevelOuter, tessLevelInner,
tessOuterLo, tessOuterHi);
#endif
gl_TessLevelOuter[0] = tessLevelOuter[0];
gl_TessLevelOuter[1] = tessLevelOuter[1];
@ -118,14 +142,14 @@ layout(OSD_SPACING) in;
patch in vec4 tessOuterLo, tessOuterHi;
in block {
OsdPerPatchVertexBSpline v;
OsdPerPatchVertexBezier v;
OSD_USER_VARYING_DECLARE
} inpt[];
out block {
OutputVertex v;
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
vec2 vSegments;
#endif
OSD_USER_VARYING_DECLARE
} outpt;
@ -135,7 +159,7 @@ void main()
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
OsdPerPatchVertexBSpline cv[16];
OsdPerPatchVertexBezier cv[16];
for (int i = 0; i < 16; ++i) {
cv[i] = inpt[i].v;
}
@ -144,7 +168,7 @@ void main()
tessOuterLo, tessOuterHi);
ivec3 patchParam = inpt[0].v.patchParam;
OsdEvalPatchBSpline(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
// all code below here is client code
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
@ -156,7 +180,7 @@ void main()
outpt.v.Nv = dNv;
#endif
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
outpt.sharpness = cv[0].sharpness;
outpt.vSegments = cv[0].vSegments;
#endif
outpt.v.tessCoord = UV;

View File

@ -350,7 +350,6 @@ uniform samplerBuffer OsdFVarDataBuffer;
#endif
// ----------------------------------------------------------------------------
void
OsdUnivar4x4(in float u, out float B[4], out float D[4])
{
@ -404,6 +403,16 @@ OsdUnivar4x4(in float u, out float B[4], out float D[4], out float C[4])
// ----------------------------------------------------------------------------
struct OsdPerPatchVertexBezier {
ivec3 patchParam;
vec3 P;
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
vec3 P1;
vec3 P2;
vec2 vSegments;
#endif
};
vec3
OsdEvalBezier(vec3 cp[16], vec2 uv)
{
@ -429,6 +438,67 @@ OsdEvalBezier(vec3 cp[16], vec2 uv)
return P;
}
// When OSD_PATCH_ENABLE_SINGLE_CREASE is defined,
// this function evaluates single-crease patch, which is segmented into
// 3 parts in the v-direction.
//
// v=0 vSegment.x vSegment.y v=1
// +------------------+-------------------+------------------+
// | cp 0 | cp 1 | cp 2 |
// | (infinite sharp) | (floor sharpness) | (ceil sharpness) |
// +------------------+-------------------+------------------+
//
vec3
OsdEvalBezier(OsdPerPatchVertexBezier cp[16], vec2 uv)
{
vec3 BUCP[4] = vec3[4](vec3(0), vec3(0), vec3(0), vec3(0));
float B[4], D[4];
OsdUnivar4x4(uv.x, B, D);
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
vec2 vSegments = cp[0].vSegments;
if (uv.y < vSegments.x) {
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
vec3 A = cp[4*i + j].P.xyz;
BUCP[i] += A * B[j];
}
}
} else if (uv.y < vSegments.y) {
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
vec3 A = cp[4*i + j].P1.xyz;
BUCP[i] += A * B[j];
}
}
} else {
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
vec3 A = cp[4*i + j].P2.xyz;
BUCP[i] += A * B[j];
}
}
}
#else
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
vec3 A = cp[4*i + j].P;
BUCP[i] += A * B[j];
}
}
#endif
vec3 P = vec3(0);
OsdUnivar4x4(uv.y, B, D);
for (int k=0; k<4; ++k) {
P += B[k] * BUCP[k];
}
return P;
}
// ----------------------------------------------------------------------------
// Boundary Interpolation
// ----------------------------------------------------------------------------
@ -607,8 +677,8 @@ OsdGetTessLevelsRefinedPoints(vec3 cp[16], ivec3 patchParam,
}
void
OsdGetTessLevelsLimitPoints(vec3 cpBezier[16], ivec3 patchParam,
out vec4 tessOuterLo, out vec4 tessOuterHi)
OsdGetTessLevelsLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
{
// Each edge of a transition patch is adjacent to one or two patches
// at the next refined level of subdivision. When the patch control
@ -623,48 +693,107 @@ OsdGetTessLevelsLimitPoints(vec3 cpBezier[16], ivec3 patchParam,
int transitionMask = OsdGetPatchTransitionMask(patchParam);
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
if ((transitionMask & 8) != 0) {
vec3 ev03 = OsdEvalBezier(cpBezier, vec2(0.0, 0.5));
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0], ev03);
tessOuterHi[0] = OsdComputeTessLevel(cpBezier[12], ev03);
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, ev03);
tessOuterHi[0] = OsdComputeTessLevel(cpBezier[12].P2, ev03);
} else {
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0], cpBezier[12]);
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[12].P2);
}
if ((transitionMask & 1) != 0) {
vec3 ev01 = OsdEvalBezier(cpBezier, vec2(0.5, 0.0));
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0], ev01);
tessOuterHi[1] = OsdComputeTessLevel(cpBezier[3], ev01);
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, ev01);
tessOuterHi[1] = OsdComputeTessLevel(cpBezier[3].P, ev01);
} else {
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0], cpBezier[3]);
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[3].P);
}
if ((transitionMask & 2) != 0) {
vec3 ev12 = OsdEvalBezier(cpBezier, vec2(1.0, 0.5));
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3], ev12);
tessOuterHi[2] = OsdComputeTessLevel(cpBezier[15], ev12);
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, ev12);
tessOuterHi[2] = OsdComputeTessLevel(cpBezier[15].P2, ev12);
} else {
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3], cpBezier[15]);
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, cpBezier[15].P2);
}
if ((transitionMask & 4) != 0) {
vec3 ev23 = OsdEvalBezier(cpBezier, vec2(0.5, 1.0));
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12], ev23);
tessOuterHi[3] = OsdComputeTessLevel(cpBezier[15], ev23);
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P2, ev23);
tessOuterHi[3] = OsdComputeTessLevel(cpBezier[15].P2, ev23);
} else {
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12], cpBezier[15]);
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P2, cpBezier[15].P2);
}
#else
if ((transitionMask & 8) != 0) {
vec3 ev03 = OsdEvalBezier(cpBezier, vec2(0.0, 0.5));
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, ev03);
tessOuterHi[0] = OsdComputeTessLevel(cpBezier[12].P, ev03);
} else {
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[12].P);
}
if ((transitionMask & 1) != 0) {
vec3 ev01 = OsdEvalBezier(cpBezier, vec2(0.5, 0.0));
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, ev01);
tessOuterHi[1] = OsdComputeTessLevel(cpBezier[3].P, ev01);
} else {
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[3].P);
}
if ((transitionMask & 2) != 0) {
vec3 ev12 = OsdEvalBezier(cpBezier, vec2(1.0, 0.5));
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, ev12);
tessOuterHi[2] = OsdComputeTessLevel(cpBezier[15].P, ev12);
} else {
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, cpBezier[15].P);
}
if ((transitionMask & 4) != 0) {
vec3 ev23 = OsdEvalBezier(cpBezier, vec2(0.5, 1.0));
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, ev23);
tessOuterHi[3] = OsdComputeTessLevel(cpBezier[15].P, ev23);
} else {
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, cpBezier[15].P);
}
#endif
}
void
OsdGetTessLevels(vec3 cp[16], ivec3 patchParam,
OsdGetTessLevelsUniform(ivec3 patchParam,
out vec4 tessLevelOuter, out vec2 tessLevelInner,
out vec4 tessOuterLo, out vec4 tessOuterHi)
{
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
OsdGetTessLevelsLimitPoints(cp, patchParam, tessOuterLo, tessOuterHi);
#elif defined OSD_ENABLE_SCREENSPACE_TESSELLATION_REFINED
OsdGetTessLevelsRefinedPoints(cp, patchParam, tessOuterLo, tessOuterHi);
#else
// uniform tessellation
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
#endif
// Outer levels are the sum of the Lo and Hi segments where the Hi
// segments will have a length of zero for non-transition edges.
tessLevelOuter = tessOuterLo + tessOuterHi;
// Inner levels are the average the corresponding outer levels.
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
}
void
OsdGetTessLevelsAdaptiveRefinedPoints(vec3 cpRefined[16], ivec3 patchParam,
out vec4 tessLevelOuter, out vec2 tessLevelInner,
out vec4 tessOuterLo, out vec4 tessOuterHi)
{
OsdGetTessLevelsRefinedPoints(cpRefined, patchParam, tessOuterLo, tessOuterHi);
// Outer levels are the sum of the Lo and Hi segments where the Hi
// segments will have a length of zero for non-transition edges.
tessLevelOuter = tessOuterLo + tessOuterHi;
// Inner levels are the average the corresponding outer levels.
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
}
void
OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
ivec3 patchParam,
out vec4 tessLevelOuter, out vec2 tessLevelInner,
out vec4 tessOuterLo, out vec4 tessOuterHi)
{
OsdGetTessLevelsLimitPoints(cpBezier, patchParam, tessOuterLo, tessOuterHi);
// Outer levels are the sum of the Lo and Hi segments where the Hi
// segments will have a length of zero for non-transition edges.
@ -737,16 +866,6 @@ OsdGetTessParameterization(vec2 uv, vec4 tessOuterLo, vec4 tessOuterHi)
// BSpline
// ----------------------------------------------------------------------------
struct OsdPerPatchVertexBSpline {
ivec3 patchParam;
vec3 P;
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
vec3 P1;
vec3 P2;
float sharpness;
#endif
};
// compute single-crease patch matrix
mat4
OsdComputeMs(float sharpness)
@ -767,9 +886,10 @@ OsdComputeMs(float sharpness)
return m;
}
// convert BSpline cv to Bezier cv
void
OsdComputePerPatchVertexBSpline(ivec3 patchParam, int ID, vec3 cv[16],
out OsdPerPatchVertexBSpline result)
out OsdPerPatchVertexBezier result)
{
// Regular BSpline to Bezier
mat4 Q = mat4(
@ -803,19 +923,21 @@ OsdComputePerPatchVertexBSpline(ivec3 patchParam, int ID, vec3 cv[16],
0.f, 0.f, 1.f, 0.f
);
result.sharpness = OsdGetPatchSharpness(patchParam);
if (result.sharpness > 0) {
float Sf = floor(result.sharpness);
float Sc = ceil(result.sharpness);
float Sr = fract(result.sharpness);
float sharpness = OsdGetPatchSharpness(patchParam);
if (sharpness > 0) {
float Sf = floor(sharpness);
float Sc = ceil(sharpness);
float Sr = fract(sharpness);
mat4 Mf = OsdComputeMs(Sf);
mat4 Mc = OsdComputeMs(Sc);
mat4 Mj = (1-Sr) * Mf + Sr * Mi;
mat4 Ms = (1-Sr) * Mf + Sr * Mc;
float s0 = 1 - pow(2, -floor(sharpness));
float s1 = 1 - pow(2, -ceil(sharpness));
result.P = vec3(0);
result.P1 = vec3(0);
result.P2 = vec3(0);
result.vSegments = vec2(s0, s1);
for (int k=0; k<4; ++k) {
result.P += Mi[j][k]*H[k]; // 0 to 1-2^(-Sf)
result.P1 += Mj[j][k]*H[k]; // 1-2^(-Sf) to 1-2^(-Sc)
@ -823,11 +945,12 @@ OsdComputePerPatchVertexBSpline(ivec3 patchParam, int ID, vec3 cv[16],
}
} else {
result.P = vec3(0);
result.P1 = vec3(0);
result.P2 = vec3(0);
for (int k=0; k<4; ++k) {
result.P += Q[j][k]*H[k];
}
result.P1 = result.P;
result.P2 = result.P;
result.vSegments = vec2(0);
}
#else
{
@ -840,10 +963,10 @@ OsdComputePerPatchVertexBSpline(ivec3 patchParam, int ID, vec3 cv[16],
}
void
OsdEvalPatchBSpline(ivec3 patchParam, vec2 UV,
OsdPerPatchVertexBSpline cv[16],
out vec3 P, out vec3 dPu, out vec3 dPv,
out vec3 N, out vec3 dNu, out vec3 dNv)
OsdEvalPatchBezier(ivec3 patchParam, vec2 UV,
OsdPerPatchVertexBezier cv[16],
out vec3 P, out vec3 dPu, out vec3 dPv,
out vec3 N, out vec3 dNu, out vec3 dNv)
{
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
float B[4], D[4], C[4];
@ -860,39 +983,21 @@ OsdEvalPatchBSpline(ivec3 patchParam, vec2 UV,
// ----------------------------------------------------------------
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness = cv[0].sharpness;
if (sharpness != 0) {
float s0 = 1.0 - pow(2.0f, -floor(sharpness));
float s1 = 1.0 - pow(2.0f, -ceil(sharpness));
vec2 vSegments = cv[0].vSegments;
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
int k = 4*i + j;
float s = UV.y;
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
int k = 4*i + j;
float s = UV.y;
vec3 A = (s <= vSegments.x) ? cv[k].P.xyz
: ((s <= vSegments.y) ? cv[k].P1.xyz
: cv[k].P2.xyz);
vec3 A = (s < s0) ?
cv[k].P :
((s < s1) ?
cv[k].P1.xyz :
cv[k].P2.xyz);
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
CUCP[i] += A * C[j];
CUCP[i] += A * C[j];
#endif
}
}
} else {
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
vec3 A = cv[4*i + j].P;
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
CUCP[i] += A * C[j];
#endif
}
}
}
#else

View File

@ -74,6 +74,7 @@
#include "catmark_pyramid_creases1.h"
#include "catmark_pyramid.h"
#include "catmark_rook.h"
#include "catmark_single_crease.h"
#include "catmark_smoothtris0.h"
#include "catmark_smoothtris1.h"
#include "catmark_square_hedit0.h"

View File

@ -0,0 +1,458 @@
//
// Copyright 2015 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_single_crease =
"v -2.000000 -0.500000 0.000000\n"
"v -1.800000 -0.500000 0.200000\n"
"v -1.600000 -0.500000 0.000000\n"
"v -1.400000 -0.500000 0.200000\n"
"v -1.200000 -0.500000 0.000000\n"
"v -1.000000 -0.500000 0.200000\n"
"v -0.800000 -0.500000 0.000000\n"
"v -0.600000 -0.500000 0.200000\n"
"v -0.400000 -0.500000 0.000000\n"
"v -0.200000 -0.500000 0.200000\n"
"v 0.000000 -0.500000 0.000000\n"
"v 0.200000 -0.500000 0.200000\n"
"v 0.400000 -0.500000 0.000000\n"
"v 0.600000 -0.500000 0.200000\n"
"v 0.800000 -0.500000 0.000000\n"
"v 1.000000 -0.500000 0.200000\n"
"v 1.200000 -0.500000 0.000000\n"
"v 1.400000 -0.500000 0.200000\n"
"v 1.600000 -0.500000 0.000000\n"
"v 1.800000 -0.500000 0.200000\n"
"v 2.000000 -0.500000 0.000000\n"
"v -2.000000 -0.250000 0.000000\n"
"v -1.800000 -0.250000 0.500000\n"
"v -1.600000 -0.250000 0.000000\n"
"v -1.400000 -0.250000 0.500000\n"
"v -1.200000 -0.250000 0.000000\n"
"v -1.000000 -0.250000 0.500000\n"
"v -0.800000 -0.250000 0.000000\n"
"v -0.600000 -0.250000 0.500000\n"
"v -0.400000 -0.250000 0.000000\n"
"v -0.200000 -0.250000 0.500000\n"
"v 0.000000 -0.250000 0.000000\n"
"v 0.200000 -0.250000 0.500000\n"
"v 0.400000 -0.250000 0.000000\n"
"v 0.600000 -0.250000 0.500000\n"
"v 0.800000 -0.250000 0.000000\n"
"v 1.000000 -0.250000 0.500000\n"
"v 1.200000 -0.250000 0.000000\n"
"v 1.400000 -0.250000 0.500000\n"
"v 1.600000 -0.250000 0.000000\n"
"v 1.800000 -0.250000 0.500000\n"
"v 2.000000 -0.250000 0.000000\n"
"v -2.000000 0.000000 0.000000\n"
"v -1.800000 0.000000 0.500000\n"
"v -1.600000 0.000000 0.000000\n"
"v -1.400000 0.000000 0.500000\n"
"v -1.200000 0.000000 0.000000\n"
"v -1.000000 0.000000 0.500000\n"
"v -0.800000 0.000000 0.000000\n"
"v -0.600000 0.000000 0.500000\n"
"v -0.400000 0.000000 0.000000\n"
"v -0.200000 0.000000 0.500000\n"
"v 0.000000 0.000000 0.000000\n"
"v 0.200000 0.000000 0.500000\n"
"v 0.400000 0.000000 0.000000\n"
"v 0.600000 0.000000 0.500000\n"
"v 0.800000 0.000000 0.000000\n"
"v 1.000000 0.000000 0.500000\n"
"v 1.200000 0.000000 0.000000\n"
"v 1.400000 0.000000 0.500000\n"
"v 1.600000 0.000000 0.000000\n"
"v 1.800000 0.000000 0.500000\n"
"v 2.000000 0.000000 0.000000\n"
"v -2.000000 0.250000 0.000000\n"
"v -1.800000 0.250000 0.500000\n"
"v -1.600000 0.250000 0.000000\n"
"v -1.400000 0.250000 0.500000\n"
"v -1.200000 0.250000 0.000000\n"
"v -1.000000 0.250000 0.500000\n"
"v -0.800000 0.250000 0.000000\n"
"v -0.600000 0.250000 0.500000\n"
"v -0.400000 0.250000 0.000000\n"
"v -0.200000 0.250000 0.500000\n"
"v 0.000000 0.250000 0.000000\n"
"v 0.200000 0.250000 0.500000\n"
"v 0.400000 0.250000 0.000000\n"
"v 0.600000 0.250000 0.500000\n"
"v 0.800000 0.250000 0.000000\n"
"v 1.000000 0.250000 0.500000\n"
"v 1.200000 0.250000 0.000000\n"
"v 1.400000 0.250000 0.500000\n"
"v 1.600000 0.250000 0.000000\n"
"v 1.800000 0.250000 0.500000\n"
"v 2.000000 0.250000 0.000000\n"
"v -2.000000 0.500000 0.000000\n"
"v -1.800000 0.500000 0.500000\n"
"v -1.600000 0.500000 0.000000\n"
"v -1.400000 0.500000 0.500000\n"
"v -1.200000 0.500000 0.000000\n"
"v -1.000000 0.500000 0.500000\n"
"v -0.800000 0.500000 0.000000\n"
"v -0.600000 0.500000 0.500000\n"
"v -0.400000 0.500000 0.000000\n"
"v -0.200000 0.500000 0.500000\n"
"v 0.000000 0.500000 0.000000\n"
"v 0.200000 0.500000 0.500000\n"
"v 0.400000 0.500000 0.000000\n"
"v 0.600000 0.500000 0.500000\n"
"v 0.800000 0.500000 0.000000\n"
"v 1.000000 0.500000 0.500000\n"
"v 1.200000 0.500000 0.000000\n"
"v 1.400000 0.500000 0.500000\n"
"v 1.600000 0.500000 0.000000\n"
"v 1.800000 0.500000 0.500000\n"
"v 2.000000 0.500000 0.000000\n"
"vt 0.000000 0.000000 \n"
"vt 0.050000 0.000000 \n"
"vt 0.100000 0.000000 \n"
"vt 0.150000 0.000000 \n"
"vt 0.200000 0.000000 \n"
"vt 0.250000 0.000000 \n"
"vt 0.300000 0.000000 \n"
"vt 0.350000 0.000000 \n"
"vt 0.400000 0.000000 \n"
"vt 0.450000 0.000000 \n"
"vt 0.500000 0.000000 \n"
"vt 0.550000 0.000000 \n"
"vt 0.600000 0.000000 \n"
"vt 0.650000 0.000000 \n"
"vt 0.700000 0.000000 \n"
"vt 0.750000 0.000000 \n"
"vt 0.800000 0.000000 \n"
"vt 0.850000 0.000000 \n"
"vt 0.900000 0.000000 \n"
"vt 0.950000 0.000000 \n"
"vt 1.000000 0.000000 \n"
"vt 0.000000 0.062500 \n"
"vt 0.050000 0.062500 \n"
"vt 0.100000 0.062500 \n"
"vt 0.150000 0.062500 \n"
"vt 0.200000 0.062500 \n"
"vt 0.250000 0.062500 \n"
"vt 0.300000 0.062500 \n"
"vt 0.350000 0.062500 \n"
"vt 0.400000 0.062500 \n"
"vt 0.450000 0.062500 \n"
"vt 0.500000 0.062500 \n"
"vt 0.550000 0.062500 \n"
"vt 0.600000 0.062500 \n"
"vt 0.650000 0.062500 \n"
"vt 0.700000 0.062500 \n"
"vt 0.750000 0.062500 \n"
"vt 0.800000 0.062500 \n"
"vt 0.850000 0.062500 \n"
"vt 0.900000 0.062500 \n"
"vt 0.950000 0.062500 \n"
"vt 1.000000 0.062500 \n"
"vt 0.000000 0.125000 \n"
"vt 0.050000 0.125000 \n"
"vt 0.100000 0.125000 \n"
"vt 0.150000 0.125000 \n"
"vt 0.200000 0.125000 \n"
"vt 0.250000 0.125000 \n"
"vt 0.300000 0.125000 \n"
"vt 0.350000 0.125000 \n"
"vt 0.400000 0.125000 \n"
"vt 0.450000 0.125000 \n"
"vt 0.500000 0.125000 \n"
"vt 0.550000 0.125000 \n"
"vt 0.600000 0.125000 \n"
"vt 0.650000 0.125000 \n"
"vt 0.700000 0.125000 \n"
"vt 0.750000 0.125000 \n"
"vt 0.800000 0.125000 \n"
"vt 0.850000 0.125000 \n"
"vt 0.900000 0.125000 \n"
"vt 0.950000 0.125000 \n"
"vt 1.000000 0.125000 \n"
"vt 0.000000 0.187500 \n"
"vt 0.050000 0.187500 \n"
"vt 0.100000 0.187500 \n"
"vt 0.150000 0.187500 \n"
"vt 0.200000 0.187500 \n"
"vt 0.250000 0.187500 \n"
"vt 0.300000 0.187500 \n"
"vt 0.350000 0.187500 \n"
"vt 0.400000 0.187500 \n"
"vt 0.450000 0.187500 \n"
"vt 0.500000 0.187500 \n"
"vt 0.550000 0.187500 \n"
"vt 0.600000 0.187500 \n"
"vt 0.650000 0.187500 \n"
"vt 0.700000 0.187500 \n"
"vt 0.750000 0.187500 \n"
"vt 0.800000 0.187500 \n"
"vt 0.850000 0.187500 \n"
"vt 0.900000 0.187500 \n"
"vt 0.950000 0.187500 \n"
"vt 1.000000 0.187500 \n"
"vt 0.000000 0.250000 \n"
"vt 0.050000 0.250000 \n"
"vt 0.100000 0.250000 \n"
"vt 0.150000 0.250000 \n"
"vt 0.200000 0.250000 \n"
"vt 0.250000 0.250000 \n"
"vt 0.300000 0.250000 \n"
"vt 0.350000 0.250000 \n"
"vt 0.400000 0.250000 \n"
"vt 0.450000 0.250000 \n"
"vt 0.500000 0.250000 \n"
"vt 0.550000 0.250000 \n"
"vt 0.600000 0.250000 \n"
"vt 0.650000 0.250000 \n"
"vt 0.700000 0.250000 \n"
"vt 0.750000 0.250000 \n"
"vt 0.800000 0.250000 \n"
"vt 0.850000 0.250000 \n"
"vt 0.900000 0.250000 \n"
"vt 0.950000 0.250000 \n"
"vt 1.000000 0.250000 \n"
"vn -0.832155 -0.285311 0.475517\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn -0.000000 -0.514496 0.857493\n"
"vn -0.000000 -0.514496 0.857493\n"
"vn -0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn 0.000000 -0.514496 0.857493\n"
"vn -0.000000 -0.514496 0.857493\n"
"vn -0.000000 -0.514496 0.857493\n"
"vn 0.832155 -0.285311 0.475517\n"
"vn -0.891704 -0.144501 0.428932\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn -0.000000 -0.319255 0.947669\n"
"vn -0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn 0.000000 -0.319255 0.947669\n"
"vn 0.000000 -0.226541 0.974002\n"
"vn -0.000000 -0.319255 0.947669\n"
"vn -0.000000 -0.226541 0.974002\n"
"vn 0.891704 -0.144501 0.428932\n"
"vn -0.928477 0.000000 0.371391\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.928477 0.000000 0.371391\n"
"vn -0.928477 0.000000 0.371391\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.928477 0.000000 0.371391\n"
"vn -0.928477 0.000000 0.371391\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn -0.000000 0.000000 1.000000\n"
"vn 0.928477 0.000000 0.371391\n"
"s off\n"
"f 1/1/1 2/2/2 23/23/23 22/22/22\n"
"f 2/2/2 3/3/3 24/24/24 23/23/23\n"
"f 3/3/3 4/4/4 25/25/25 24/24/24\n"
"f 4/4/4 5/5/5 26/26/26 25/25/25\n"
"f 5/5/5 6/6/6 27/27/27 26/26/26\n"
"f 6/6/6 7/7/7 28/28/28 27/27/27\n"
"f 7/7/7 8/8/8 29/29/29 28/28/28\n"
"f 8/8/8 9/9/9 30/30/30 29/29/29\n"
"f 9/9/9 10/10/10 31/31/31 30/30/30\n"
"f 10/10/10 11/11/11 32/32/32 31/31/31\n"
"f 11/11/11 12/12/12 33/33/33 32/32/32\n"
"f 12/12/12 13/13/13 34/34/34 33/33/33\n"
"f 13/13/13 14/14/14 35/35/35 34/34/34\n"
"f 14/14/14 15/15/15 36/36/36 35/35/35\n"
"f 15/15/15 16/16/16 37/37/37 36/36/36\n"
"f 16/16/16 17/17/17 38/38/38 37/37/37\n"
"f 17/17/17 18/18/18 39/39/39 38/38/38\n"
"f 18/18/18 19/19/19 40/40/40 39/39/39\n"
"f 19/19/19 20/20/20 41/41/41 40/40/40\n"
"f 20/20/20 21/21/21 42/42/42 41/41/41\n"
"f 22/22/22 23/23/23 44/44/44 43/43/43\n"
"f 23/23/23 24/24/24 45/45/45 44/44/44\n"
"f 24/24/24 25/25/25 46/46/46 45/45/45\n"
"f 25/25/25 26/26/26 47/47/47 46/46/46\n"
"f 26/26/26 27/27/27 48/48/48 47/47/47\n"
"f 27/27/27 28/28/28 49/49/49 48/48/48\n"
"f 28/28/28 29/29/29 50/50/50 49/49/49\n"
"f 29/29/29 30/30/30 51/51/51 50/50/50\n"
"f 30/30/30 31/31/31 52/52/52 51/51/51\n"
"f 31/31/31 32/32/32 53/53/53 52/52/52\n"
"f 32/32/32 33/33/33 54/54/54 53/53/53\n"
"f 33/33/33 34/34/34 55/55/55 54/54/54\n"
"f 34/34/34 35/35/35 56/56/56 55/55/55\n"
"f 35/35/35 36/36/36 57/57/57 56/56/56\n"
"f 36/36/36 37/37/37 58/58/58 57/57/57\n"
"f 37/37/37 38/38/38 59/59/59 58/58/58\n"
"f 38/38/38 39/39/39 60/60/60 59/59/59\n"
"f 39/39/39 40/40/40 61/61/61 60/60/60\n"
"f 40/40/40 41/41/41 62/62/62 61/61/61\n"
"f 41/41/41 42/42/42 63/63/63 62/62/62\n"
"f 43/43/43 44/44/44 65/65/65 64/64/64\n"
"f 44/44/44 45/45/45 66/66/66 65/65/65\n"
"f 45/45/45 46/46/46 67/67/67 66/66/66\n"
"f 46/46/46 47/47/47 68/68/68 67/67/67\n"
"f 47/47/47 48/48/48 69/69/69 68/68/68\n"
"f 48/48/48 49/49/49 70/70/70 69/69/69\n"
"f 49/49/49 50/50/50 71/71/71 70/70/70\n"
"f 50/50/50 51/51/51 72/72/72 71/71/71\n"
"f 51/51/51 52/52/52 73/73/73 72/72/72\n"
"f 52/52/52 53/53/53 74/74/74 73/73/73\n"
"f 53/53/53 54/54/54 75/75/75 74/74/74\n"
"f 54/54/54 55/55/55 76/76/76 75/75/75\n"
"f 55/55/55 56/56/56 77/77/77 76/76/76\n"
"f 56/56/56 57/57/57 78/78/78 77/77/77\n"
"f 57/57/57 58/58/58 79/79/79 78/78/78\n"
"f 58/58/58 59/59/59 80/80/80 79/79/79\n"
"f 59/59/59 60/60/60 81/81/81 80/80/80\n"
"f 60/60/60 61/61/61 82/82/82 81/81/81\n"
"f 61/61/61 62/62/62 83/83/83 82/82/82\n"
"f 62/62/62 63/63/63 84/84/84 83/83/83\n"
"f 64/64/64 65/65/65 86/86/86 85/85/85\n"
"f 65/65/65 66/66/66 87/87/87 86/86/86\n"
"f 66/66/66 67/67/67 88/88/88 87/87/87\n"
"f 67/67/67 68/68/68 89/89/89 88/88/88\n"
"f 68/68/68 69/69/69 90/90/90 89/89/89\n"
"f 69/69/69 70/70/70 91/91/91 90/90/90\n"
"f 70/70/70 71/71/71 92/92/92 91/91/91\n"
"f 71/71/71 72/72/72 93/93/93 92/92/92\n"
"f 72/72/72 73/73/73 94/94/94 93/93/93\n"
"f 73/73/73 74/74/74 95/95/95 94/94/94\n"
"f 74/74/74 75/75/75 96/96/96 95/95/95\n"
"f 75/75/75 76/76/76 97/97/97 96/96/96\n"
"f 76/76/76 77/77/77 98/98/98 97/97/97\n"
"f 77/77/77 78/78/78 99/99/99 98/98/98\n"
"f 78/78/78 79/79/79 100/100/100 99/99/99\n"
"f 79/79/79 80/80/80 101/101/101 100/100/100\n"
"f 80/80/80 81/81/81 102/102/102 101/101/101\n"
"f 81/81/81 82/82/82 103/103/103 102/102/102\n"
"f 82/82/82 83/83/83 104/104/104 103/103/103\n"
"f 83/83/83 84/84/84 105/105/105 104/104/104\n"
"t crease 2/1/0 1 22 10.000000\n"
"t crease 2/1/0 3 24 5.700000\n"
"t crease 2/1/0 5 26 5.000000\n"
"t crease 2/1/0 7 28 2.800000\n"
"t crease 2/1/0 9 30 2.000000\n"
"t crease 2/1/0 11 32 1.400000\n"
"t crease 2/1/0 13 34 1.000000\n"
"t crease 2/1/0 15 36 0.800000\n"
"t crease 2/1/0 17 38 0.200000\n"
"t crease 2/1/0 22 43 10.000000\n"
"t crease 2/1/0 24 45 5.700000\n"
"t crease 2/1/0 26 47 5.000000\n"
"t crease 2/1/0 28 49 2.800000\n"
"t crease 2/1/0 30 51 2.000000\n"
"t crease 2/1/0 32 53 1.400000\n"
"t crease 2/1/0 34 55 1.000000\n"
"t crease 2/1/0 36 57 0.800000\n"
"t crease 2/1/0 38 59 0.200000\n"
"t crease 2/1/0 43 64 10.000000\n"
"t crease 2/1/0 45 66 5.700000\n"
"t crease 2/1/0 47 68 5.000000\n"
"t crease 2/1/0 49 70 2.800000\n"
"t crease 2/1/0 51 72 2.000000\n"
"t crease 2/1/0 53 74 1.400000\n"
"t crease 2/1/0 55 76 1.000000\n"
"t crease 2/1/0 57 78 0.800000\n"
"t crease 2/1/0 59 80 0.200000\n"
"t crease 2/1/0 64 85 10.000000\n"
"t crease 2/1/0 66 87 5.700000\n"
"t crease 2/1/0 68 89 5.000000\n"
"t crease 2/1/0 70 91 2.800000\n"
"t crease 2/1/0 72 93 2.000000\n"
"t crease 2/1/0 74 95 1.400000\n"
"t crease 2/1/0 76 97 1.000000\n"
"t crease 2/1/0 78 99 0.800000\n"
"t crease 2/1/0 80 101 0.200000\n"
;