Merge remote-tracking branch 'origin/dev' into rc/v3_4_0
@ -87,6 +87,8 @@ if (DOCUTILS_FOUND AND PYTHONINTERP_FOUND)
|
||||
intro.rst
|
||||
license.rst
|
||||
mod_notes.rst
|
||||
mtlviewer.rst
|
||||
mtlptexviewer.rst
|
||||
osd_overview.rst
|
||||
osd_shader_interface.rst
|
||||
porting.rst
|
||||
|
@ -38,20 +38,26 @@ of the software.
|
||||
:widths: 50 50
|
||||
|
||||
* - | `glViewer <glviewer.html>`_
|
||||
| `glFVarViewer <glfvarviewer.html>`_
|
||||
| `glEvalLimit <glevallimit.html>`_
|
||||
| `glPaintTest <glpainttest.html>`_
|
||||
| `glPtexViewer <glptexviewer.html>`_
|
||||
- | `glFVarViewer <glfvarviewer.html>`_
|
||||
| `glStencilViewer <glstencilviewer.html>`_
|
||||
- | `glPtexViewer <glptexviewer.html>`_
|
||||
| `glPaintTest <glpainttest.html>`_
|
||||
| `glShareTopology <glsharetopology.html>`_
|
||||
|
||||
.. list-table:: **DirectX examples**
|
||||
:class: quickref
|
||||
:widths: 50 50
|
||||
|
||||
* - | `dxViewer <dxviewer.html>`_
|
||||
- | `dxPtexViewer <dxptexviewer.html>`_
|
||||
|
||||
.. list-table:: **Metal examples**
|
||||
:class: quickref
|
||||
:widths: 50 50
|
||||
|
||||
* - | `mtlViewer <mtlviewer.html>`_
|
||||
- | `mtlPtexViewer <mtlptexviewer.html>`_
|
||||
|
||||
----
|
||||
|
||||
Common Command Line Options
|
||||
|
@ -35,7 +35,7 @@ SYNOPSIS
|
||||
.. parsed-literal::
|
||||
:class: codefhead
|
||||
|
||||
**dxPtexViewer** [**-f**] [**-l** *isolation level*] [**-c** *animation loops*] [**-y**]
|
||||
**dxPtexViewer** [**-f**] [**-yup**] [**-u**] [**-a**] [**-l** *isolation level*] [**-c** *animation loops*]
|
||||
[**-e** *environment map*] [**-d** *HDR diffuse map*] [**-s** *HDR specular map*]
|
||||
[**--disp** *displacement scale*]
|
||||
*ptex color file*
|
||||
@ -51,7 +51,11 @@ DESCRIPTION
|
||||
with color, displacement, occlusion and specular ptex maps. Multiple controls
|
||||
are available to experiment with the algorithms.
|
||||
|
||||
.. include:: under_development.rst
|
||||
.. image:: images/dxptexviewer.png
|
||||
:width: 400px
|
||||
:align: center
|
||||
:target: images/dxptexviewer.png
|
||||
|
||||
|
||||
|
||||
OPTIONS
|
||||
@ -98,7 +102,7 @@ for the subset of common options supported here.
|
||||
the data contained in all the ptex files !)
|
||||
|
||||
|
||||
Keyboard Controls
|
||||
KEYBOARD CONTROLS
|
||||
=================
|
||||
|
||||
.. code:: c++
|
||||
|
@ -35,8 +35,8 @@ SYNOPSIS
|
||||
.. parsed-literal::
|
||||
:class: codefhead
|
||||
|
||||
**dxViewer** [**-u**] [**-a**] [**-l** *refinement level*] [**-c** *animation loops*]
|
||||
*objfile(s)* [**-anim**] [**-catmark**] [**-loop**] [**-bilinear**]
|
||||
**dxViewer** [**-f**] [**-yup**] [**-u**] [**-a**] [**-l** *refinement level*] [**-c** *animation loops*]
|
||||
*objfile(s)* [**-catmark**] [**-loop**] [**-bilinear**]
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
@ -50,12 +50,6 @@ shapes. Multiple controls are available to experiment with the algorithms.
|
||||
:align: center
|
||||
:target: images/dxviewer.png
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
* **Note:**
|
||||
|
||||
dxViewer requires Microsoft's DirectX D3D11 SDK
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
|
@ -294,42 +294,21 @@ to refine primvar data.
|
||||
Far::PatchTable
|
||||
================
|
||||
|
||||
The patch table is a serialized topology representation. This container is
|
||||
generated using *Far::PatchTableFactory* from an instance
|
||||
*Far::TopologyRefiner* after a refinement has been applied. The
|
||||
FarPatchTableFactory traverses the data-structures of the TopologyRefiner and
|
||||
serializes the sub-faces into collections of bi-linear and bi-cubic patches as
|
||||
dictated by the refinement mode (uniform or adaptive). The patches are then
|
||||
sorted into arrays based on their types.
|
||||
PatchTable is the collection of patches derived from the refined faces of a particular mesh topology.
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
|
||||
The organization and API of Far::PatchTable is likely to change
|
||||
in the 3.1 release to accommodate additional functionality including:
|
||||
smooth face-varying interpolation on patches, and dynamic feature
|
||||
adaptive isolation (DFAS), and patch evaluation of Loop subdivision
|
||||
surfaces.
|
||||
This collection is created using *Far::PatchTableFactory* from an instance
|
||||
of *Far::TopologyRefiner* after refinement has been applied.
|
||||
|
||||
Patch Arrays
|
||||
************
|
||||
|
||||
The patch table is a collection of control vertex indices. Meshes are decomposed
|
||||
into a collection of patches, which can be of different types. Each type
|
||||
has different requirements for the internal organization of its
|
||||
control-vertices. A PatchArray contains a sequence of multiple patches that
|
||||
share a common set of attributes.
|
||||
The PatchTable is organized into patch arrays. All patches in each array have
|
||||
the same type except for face-varying patch arrays which may have a mix of regular and irregular patch types.
|
||||
|
||||
While all patches in a PatchArray will have the same type, each patch in the
|
||||
array is associated with a distinct *PatchParam* which specifies additional
|
||||
information about the individual patch.
|
||||
The *PatchDescriptor* provides the fundamental description of a patch, including the number of control points per patch as well as the basis for patch evaluation.
|
||||
|
||||
Each PatchArray contains a patch *Descriptor* that provides the fundamental
|
||||
description of the patches in the array.
|
||||
|
||||
The PatchArray *ArrayRange* provides the indices necessary to track the records
|
||||
of individual patches in the table.
|
||||
Each patch in the array is associated with a *PatchParam* which
|
||||
specifies additional information about the individual patch.
|
||||
|
||||
.. image:: images/far_patchtables.png
|
||||
:align: center
|
||||
@ -350,19 +329,21 @@ PatchTable:
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| LINES | 2 | Lines : useful for cage drawing |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| QUADS | 4 | Bi-linear quads-only patches |
|
||||
| QUADS | 4 | Bi-linear quadrilaterals |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| TRIANGLES | 3 | Bi-linear triangles-only mesh |
|
||||
| TRIANGLES | 3 | Linear triangles |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| LOOP | n/a | Loop patch (currently unsupported) |
|
||||
| LOOP | 12 | Quartic triangular Box-spline patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| REGULAR | 16 | B-spline Basis patches |
|
||||
| REGULAR | 16 | Bi-cubic B-spline patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| GREGORY | 4 | Legacy Gregory patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| GREGORY_BOUNDARY | 4 | Legacy Gregory Boundary patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| GREGORY_BASIS | 20 | Gregory Basis patches |
|
||||
| GREGORY_BASIS | 20 | Bi-cubic quadrilateral Gregory patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
| GREGORY_TRIANGLE | 18 | Quartic triangular Gregory patches |
|
||||
+---------------------+------+---------------------------------------------+
|
||||
|
||||
|
||||
@ -372,6 +353,10 @@ table as well as the method used to evaluate values.
|
||||
Patch Parameterization
|
||||
**********************
|
||||
|
||||
Here we describe the encoding of the patch parameterization for
|
||||
quadrilateral patches. The encoding for triangular patches is similar,
|
||||
please see the API documentation of Far::PatchParam for details.
|
||||
|
||||
Each patch represents a specific portion of the parametric space of the
|
||||
coarse topological face identified by the PatchParam FaceId. As topological
|
||||
refinement progresses through successive levels, each resulting patch
|
||||
@ -435,11 +420,9 @@ sharpness parameter.
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
**Release Notes (3.x)**
|
||||
|
||||
Currently, the crease sharpness parameter is encoded as a separate
|
||||
PatchArray within the PatchTable. This parameter may be combined
|
||||
with the other PatchParam values in future releases. Also, evaluation
|
||||
Evaluation
|
||||
of single-crease patches is currently only implemented for OSD patch
|
||||
drawing, but we expect to implement support in all of the evaluation
|
||||
code paths for future releases.
|
||||
@ -453,15 +436,6 @@ adaptively to the points of the coarse mesh. However, the final patches
|
||||
generated from irregular faces, e.g. patches incident on an extraordinary
|
||||
vertex might have a representation which requires additional local points.
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
|
||||
Currently, representations which require local points also require
|
||||
the use of a StencilTable to compute the values of local points.
|
||||
This requirement, as well as the rest of the API related to local
|
||||
points may change in future releases.
|
||||
|
||||
Legacy Gregory Patches
|
||||
**********************
|
||||
|
||||
@ -472,15 +446,6 @@ Legacy Gregory patches are used, the PatchTable must also have an alternative
|
||||
representation of the mesh topology encoded as a vertex valence table
|
||||
and a quad offsets table.
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
|
||||
The encoding and support for Legacy Gregory patches may change
|
||||
in future releases. The current encoding of the vertex valence
|
||||
and quad offsets tables may be prohibitively expensive for some
|
||||
use cases.
|
||||
|
||||
Far::StencilTable
|
||||
==================
|
||||
|
||||
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 7.8 MiB |
BIN
documentation/images/basis_bezier.jpg
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
documentation/images/basis_bspline.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 124 KiB |
BIN
documentation/images/dxptexviewer.png
Executable file
After Width: | Height: | Size: 1.6 MiB |
BIN
documentation/images/dxviewer.png
Normal file → Executable file
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 580 KiB |
Before Width: | Height: | Size: 359 KiB After Width: | Height: | Size: 424 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 343 KiB |
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 270 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 556 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 202 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 176 KiB |
BIN
documentation/images/mtlptexviewer.png
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
documentation/images/mtlviewer.png
Normal file
After Width: | Height: | Size: 964 KiB |
BIN
documentation/images/mtlviewer_ios.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 353 KiB |
61
documentation/mtlptexviewer.rst
Normal file
@ -0,0 +1,61 @@
|
||||
..
|
||||
Copyright 2019 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.
|
||||
|
||||
|
||||
mtlPtexViewer
|
||||
-------------
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
.. parsed-literal::
|
||||
:class: codefhead
|
||||
|
||||
**open** **mtlPtexViewer.app** **--args** [**-yup**] [**-u**] [**-a**] [**-l** *isolation level*]
|
||||
*ptex color file*
|
||||
*ptex displacement file*
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
``mtlPtexViewer`` is a stand-alone application demonstrating shading with color and displacement ptex maps. Multiple controls are available to experiment with the algorithms.
|
||||
|
||||
.. image:: images/mtlptexviewer.png
|
||||
:width: 400px
|
||||
:align: center
|
||||
:target: images/mtlptexviewer.png
|
||||
|
||||
KEYBOARD CONTROLS
|
||||
=================
|
||||
|
||||
.. code:: c++
|
||||
|
||||
q : quit
|
||||
f : fit frame
|
||||
+/- : increase / decrease tessellation rate
|
||||
|
||||
.. include:: examples_see_also.rst
|
75
documentation/mtlviewer.rst
Normal file
@ -0,0 +1,75 @@
|
||||
..
|
||||
Copyright 2019 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.
|
||||
|
||||
|
||||
mtlViewer
|
||||
---------
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
.. parsed-literal::
|
||||
:class: codefhead
|
||||
|
||||
**open** **mtlViewer.app** **--args** [**-yup**] [**-u**] [**-a**] [**-l** *refinement level*]
|
||||
*objfile(s)* [**-catmark**] [**-loop**] [**-bilinear**]
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
``mtlViewer`` is a stand-alone application that showcases the application of
|
||||
uniform and feature adaptive subdivision schemes to a collection of geometric
|
||||
shapes. Multiple controls are available to experiment with the algorithms.
|
||||
|
||||
+----------------------------------------------------+
|
||||
| .. image:: images/mtlviewer.png |
|
||||
| :width: 400px |
|
||||
| :align: center |
|
||||
| :target: images/mtlviewer.png |
|
||||
| |
|
||||
| mtlViewer running on macOS |
|
||||
+----------------------------------------------------+
|
||||
|
||||
+----------------------------------------------------+
|
||||
| .. image:: images/mtlviewer_ios.png |
|
||||
| :width: 400px |
|
||||
| :align: center |
|
||||
| :target: images/mtlviewer_ios.png |
|
||||
| |
|
||||
| mtlViewer running on iOS |
|
||||
+----------------------------------------------------+
|
||||
|
||||
KEYBOARD CONTROLS
|
||||
=================
|
||||
|
||||
.. code:: c++
|
||||
|
||||
q : quit
|
||||
f : fit frame
|
||||
+/- : increase / decrease tessellation rate
|
||||
|
||||
.. include:: examples_see_also.rst
|
@ -42,8 +42,8 @@ The main roles of **Osd** are:
|
||||
Compute limit surfaces by limit stencils on CPU/GPU backends
|
||||
- **Limit Evaluation with PatchTable**
|
||||
Compute limit surfaces by patch evaluation on CPU/GPU backends
|
||||
- **OpenGL/DX11 Drawing with hardware tessellation**
|
||||
Provide GLSL/HLSL tessellation functions for patch table
|
||||
- **OpenGL/DX11/Metal Drawing with hardware tessellation**
|
||||
Provide GLSL/HLSL/Metal tessellation functions for patch table
|
||||
- **Interleaved/Batched buffer configuration**
|
||||
Provide consistent buffer descriptor to deal with arbitrary buffer layout.
|
||||
- **Cross-Platform Implementation**
|
||||
@ -98,7 +98,8 @@ as a stencil tables as long as Evaluator::EvalStencils() can access the necessar
|
||||
+-----------------------------+-----------------------+-------------------------+
|
||||
| DX11 ComputeShader (GPU) | D3D11ComputeEvaluator | D3D11StencilTable |
|
||||
+-----------------------------+-----------------------+-------------------------+
|
||||
|
||||
| Metal (GPU) | MTLComputeEvaluator | MTLStencilTable |
|
||||
+-----------------------------+-----------------------+-------------------------+
|
||||
|
||||
Limit Stencil Evaluation
|
||||
========================
|
||||
@ -141,17 +142,18 @@ Once all control vertices and local points are resolved by the stencil evaluatio
|
||||
| DX11 ComputeShader (GPU) | | D3D11ComputeEvaluator | D3D11PatchTable |
|
||||
| | | (*)not yet supported | |
|
||||
+-----------------------------+-------------------------+-------------------------+
|
||||
| Metal ComputeShader (GPU) | | MTLComputeEvaluator | MTLPatchTable |
|
||||
+-----------------------------+-------------------------+-------------------------+
|
||||
|
||||
.. container:: notebox
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
**Release Notes (3.x)**
|
||||
|
||||
* GPU limit evaluation backends (Evaluator::EvalPatches()) only support
|
||||
BSpline patches. Clients need to specify BSpline approximation for endcap
|
||||
when creating a patch table. See `end capping <far_overview.html#endcap>`__.
|
||||
* Osd evaluation backends (Evaluator::EvalPatches()) do not support
|
||||
evaluation of single-crease or Legacy Gregory patch types.
|
||||
|
||||
OpenGL/DX11 Drawing with Hardware Tessellation
|
||||
==============================================
|
||||
OpenGL/DX11/Metal Drawing with Hardware Tessellation
|
||||
====================================================
|
||||
|
||||
One of the most interesting use cases of the **Osd** layer is realtime drawing
|
||||
of subdivision surfaces using hardware tessellation. This is somewhat similar to
|
||||
@ -265,6 +267,8 @@ The methods that need to be implemented for the Evaluators are:
|
||||
+-----------------------+------------------------+------------------+
|
||||
| D3D11ComputeEvaluator | D3D11 UAV | BindD3D11UAV() |
|
||||
+-----------------------+------------------------+------------------+
|
||||
| MTLComputeEvaluator | MTLBuffer | BindMTLBuffer() |
|
||||
+-----------------------+------------------------+------------------+
|
||||
|
||||
The buffers can use these methods as a trigger of interop. **Osd** provides a default
|
||||
implementation of interop buffer for most of the backend combinations.
|
||||
|
@ -50,8 +50,8 @@ The following is a minimal example of GLSL code explaining how client shader cod
|
||||
uses OpenSubdiv shader functions to tessellate patches of a patch table.
|
||||
|
||||
|
||||
Tessellation Control Shader Example (for BSpline patches)
|
||||
*********************************************************
|
||||
Tessellation Control Shader Example (for B-Spline patches)
|
||||
**********************************************************
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
@ -88,8 +88,8 @@ Tessellation Control Shader Example (for BSpline patches)
|
||||
|
||||
|
||||
|
||||
Tessellation Evaluation Shader Example (for BSpline patches)
|
||||
************************************************************
|
||||
Tessellation Evaluation Shader Example (for B-Spline patches)
|
||||
*************************************************************
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
@ -160,7 +160,8 @@ are stored in a OsdPerPatchVertexGreogryBasis struct.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void OsdComputePerPatchVertexGregoryBasis(
|
||||
void
|
||||
OsdComputePerPatchVertexGregoryBasis(
|
||||
ivec3 patchParam, int ID, vec3 cv, out OsdPerPatchVertexGregoryBasis result)
|
||||
|
||||
The tessellation evaluation shader takes an array of OsdPerPatchVertexGregoryBasis struct,
|
||||
@ -174,6 +175,54 @@ and then evaluates the patch using the OsdEvalPatchGregory() function.
|
||||
out vec3 N, out vec3 dNu, out vec3 dNv)
|
||||
|
||||
|
||||
Box-spline Triangle Patch
|
||||
*************************
|
||||
|
||||
While regular triangle patches are expressed as triangular box-spline patches in Far::PatchTable,
|
||||
the **Osd** shader converts them into triangular Bezier patches for consistency.
|
||||
This conversion is performed in the tessellation control stage. The boundary edge evaluation is resolved during this conversion.
|
||||
OsdComputePerPatchVertexBoxSplineTriangle() can be used for this process.
|
||||
The resulting Bezier control vertices are stored in OsdPerPatchVertexBezier struct.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexBoxSplineTriangle(
|
||||
ivec3 patchParam, int ID, vec3 cv[12], out OsdPerPatchVertexBezier result);
|
||||
|
||||
The tessellation evaluation shader takes an array of OsdPerPatchVertexBezier struct,
|
||||
and then evaluates the patch using the OsdEvalPatchBezierTriangle() function.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void OsdEvalPatchBezierTriangle(ivec3 patchParam, vec2 UV,
|
||||
OsdPerPatchVertexBezier cv[15],
|
||||
out vec3 P, out vec3 dPu, out vec3 dPv,
|
||||
out vec3 N, out vec3 dNu, out vec3 dNv)
|
||||
|
||||
|
||||
Gregory Triangle Patch
|
||||
**********************
|
||||
|
||||
OsdComputePerPatchVertexGregoryBasis() can be used for the quartic triangular Gregory patches (although no basis conversion involved for the Gregory triangle patches) and the resulting vertices are stored in a OsdPerPatchVertexGreogryBasis struct.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregoryBasis(
|
||||
ivec3 patchParam, int ID, vec3 cv, out OsdPerPatchVertexGregoryBasis result)
|
||||
|
||||
The tessellation evaluation shader takes an array of OsdPerPatchVertexGregoryBasis struct,
|
||||
and then evaluates the patch using the OsdEvalPatchGregoryTriangle() function.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void
|
||||
OsdEvalPatchGregoryTriangle(ivec3 patchParam, vec2 UV, vec3 cv[18],
|
||||
out vec3 P, out vec3 dPu, out vec3 dPv,
|
||||
out vec3 N, out vec3 dNu, out vec3 dNv)
|
||||
|
||||
|
||||
Legacy Gregory Patch (2.x compatibility)
|
||||
****************************************
|
||||
|
||||
@ -190,12 +239,6 @@ Tessellation levels
|
||||
|
||||
**Osd** provides both uniform and screen-space adaptive tessellation level computation.
|
||||
|
||||
Uniform tessellation
|
||||
OsdGetTessLevelsUniform()
|
||||
|
||||
Screen-space adaptive tessellation
|
||||
OsdGetTessLevelsAdaptiveLimitPoints()
|
||||
|
||||
Because of the nature of `feature adaptive subdivision <far_overview.html>`__,
|
||||
we need to pay extra attention for a patch's outer tessellation level for the screen-space
|
||||
adaptive case so that cracks don't appear.
|
||||
@ -212,31 +255,63 @@ as separate levels for the two segments of the edge split at the middle.
|
||||
|
||||
.. image:: images/osd_shader_transition.png
|
||||
|
||||
Then the tessellation evaluation shader takes gl_TessCoord and those two values, and remaps
|
||||
gl_TessCoord using OsdGetTessParameterization() to ensure the parameters are consistent
|
||||
Tessellation levels at each tessellated vertex
|
||||
**********************************************
|
||||
|
||||
The tessellation evaluation shader takes gl_TessCoord and those two values, and remaps
|
||||
gl_TessCoord using OsdGetTessParameterization() or OsdGetTessLevelParameterizationTriangle() to ensure the parameters are consistent
|
||||
across adjacent patches.
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
vec2 OsdGetTessParameterization(vec2 uv, vec4 tessOuterLo, vec4 tessOuterHi);
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
vec2 OsdGetTessParameterizationTriangle(vec3 uvw, vec4 tessOuterLo, vec4 tessOuterHi);
|
||||
|
||||
.. image:: images/osd_shader_param_remap.png
|
||||
|
||||
.. code:: glsl
|
||||
Tessellation levels computed at each patch
|
||||
******************************************
|
||||
|
||||
vec2 OsdGetTessParameterization(vec2 uv, vec4 tessOuterLo, vec4 tessOuterHi)
|
||||
|
||||
These tessellation levels can be computed by OsdGetTessLevelsAdaptiveLimitPoints()
|
||||
in the tessellation control shader. Note that this function requires all 16 bezier control
|
||||
These tessellation levels can be computed the corresponding method in the tesselation control shader. Note that these functions potentially requires all bezier control
|
||||
points, you need to call barrier() to ensure the conversion is done for all invocations.
|
||||
See osd/glslPatchBSpline.glsl for more details.
|
||||
|
||||
Uniform
|
||||
~~~~~~~
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
void
|
||||
OsdGetTessLevelsUniform(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
|
||||
.. container:: notebox
|
||||
.. code:: glsl
|
||||
|
||||
**Release Notes (3.0.0)**
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
|
||||
* Currently OsdGetTessParameterization doesn't support fraction spacing.
|
||||
It will be fixed in a future release.
|
||||
|
||||
Screenspace
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void OsdEvalPatchBezierTessLevels(
|
||||
OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi);
|
||||
|
||||
.. code:: glsl
|
||||
|
||||
void OsdEvalPatchBezierTriangleTessLevels(
|
||||
vec3 cv[15],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi);
|
||||
|
@ -22,8 +22,8 @@
|
||||
language governing permissions and limitations under the Apache License.
|
||||
|
||||
|
||||
Overview of Release 3.4 (draft)
|
||||
===============================
|
||||
Overview of Release 3.4
|
||||
=======================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
@ -34,9 +34,8 @@ New Features
|
||||
|
||||
Triangular Patches for Loop Subdivision
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Added support for drawing and evaluation of Loop subdivision meshes with
|
||||
triangular patches. This includes the full set of Far and Osd interfaces
|
||||
Support for the drawing and evaluation of Loop subdivision meshes with
|
||||
triangular patches was added. This includes the full set of Far and Osd interfaces
|
||||
for both evaluation and drawing.
|
||||
|
||||
+-----------------------------------+-----------------------------------+
|
||||
@ -56,11 +55,18 @@ including creases, face-varying patches, non-manifold topology, etc.
|
||||
| :target: images/loop_rel_3.png| :target: images/loop_rel_4.png |
|
||||
+----------------------------------+----------------------------------------------------------------+
|
||||
|
||||
Quartic triangular patches are used to exactly match the limit surface of
|
||||
Loop subdivision where the mesh is regular and approximated where irregular.
|
||||
As is the case with use of the Catmark scheme, application of Loop subdivision
|
||||
to dense, poorly modeled meshes may lead to unexpectedly poor performance or
|
||||
surface quality.
|
||||
The long standing requirement that Loop meshes be purely triangular remains, as
|
||||
Loop subdivision is not defined for non-triangular faces. And as is the case with
|
||||
the use of the Catmark scheme, application of Loop subdivision to dense, poorly
|
||||
modeled meshes may lead to unexpectedly poor performance and/or surface quality.
|
||||
|
||||
The patch representation used for Loop subdivision is intended to exactly match the
|
||||
underlying limit surface where regular, and so uses quartic triangular Box-splines.
|
||||
This is in contrast to approaches that use simpler patches to approximate the Loop
|
||||
limit surface everywhere. As with Catmark, Gregory patches are used to approximate
|
||||
irregular areas. Though other choices are available that compromise surface
|
||||
quality in favor of improved performance, they may be less effective with Loop than
|
||||
they are with Catmark.
|
||||
|
||||
Major Improvements to Introductory Documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -119,27 +125,6 @@ API Additions
|
||||
|
||||
See associated `Doxygen <doxy_html/index.html>`__ for full details.
|
||||
|
||||
Osd::MeshBits
|
||||
~~~~~~~~~~~~~
|
||||
- enumeration MeshEndCapBilinearBasis
|
||||
|
||||
Osd::PatchArray
|
||||
~~~~~~~~~~~~~~~
|
||||
- GetDescriptorRegular()
|
||||
- GetDescriptorIrregular()
|
||||
- GetPatchTyperRegular()
|
||||
- GetPatchTyperIrregular()
|
||||
- GetStride()
|
||||
|
||||
Osd extensions common to all shaders
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- TBD
|
||||
|
||||
Far construction and refinement of topology
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- overloaded TopologyRefinerFactory::Create()
|
||||
- extensions to TopologyRefiner::RefineAdaptive()
|
||||
|
||||
Far extensions for triangular patches
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- enum PatchDescriptor::Type::GREGORY_TRIANGLE
|
||||
@ -147,6 +132,11 @@ Far extensions for triangular patches
|
||||
- PatchParam::UnnormalizeTriangle()
|
||||
- PatchParam::IsTriangleRotated()
|
||||
|
||||
Construction and refinement of topology
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- overloaded TopologyRefinerFactory::Create()
|
||||
- extensions to TopologyRefiner::RefineAdaptive()
|
||||
|
||||
Construction and interface of Far::PatchTable
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- overloaded PatchTableFactory::Create()
|
||||
@ -190,6 +180,51 @@ Far member functions converted to templates for double precision
|
||||
- PatchTable::GetLocalPointFaceVaryingStencilTable()
|
||||
- PatchMap::FindPatch()
|
||||
|
||||
Osd::MeshBits
|
||||
~~~~~~~~~~~~~
|
||||
- enumeration MeshEndCapBilinearBasis
|
||||
|
||||
Osd::PatchArray
|
||||
~~~~~~~~~~~~~~~
|
||||
- GetDescriptorRegular()
|
||||
- GetDescriptorIrregular()
|
||||
- GetPatchTyperRegular()
|
||||
- GetPatchTyperIrregular()
|
||||
- GetStride()
|
||||
|
||||
Osd extensions for patch evaluation common to all shaders
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- struct OsdPatchArray and OsdPatchArrayInit()
|
||||
- struct OsdPatchCoord and OsdPatchCoordInit()
|
||||
- struct OsdPatchParam and OsdPatchParamInit()
|
||||
- OsdPatchParamGetFaceId()
|
||||
- OsdPatchParamGetU()
|
||||
- OsdPatchParamGetV()
|
||||
- OsdPatchParamGetTransition()
|
||||
- OsdPatchParamGetBoundary()
|
||||
- OsdPatchParamGetNonQuadRoot()
|
||||
- OsdPatchParamGetDepth()
|
||||
- OsdPatchParamGetParamFraction()
|
||||
- OsdPatchParamIsRegular()
|
||||
- OsdPatchParamIsTriangleRotated()
|
||||
- OsdPatchParamNormalize()
|
||||
- OsdPatchParamUnnormalize()
|
||||
- OsdPatchParamNormalize(Triangle)
|
||||
- OsdPatchParamUnnormalizeTriangle()
|
||||
- OsdEvaluatePatchBasisNormalized()
|
||||
- OsdEvaluatePatchBasis()
|
||||
|
||||
Osd extensions for patch tessellation common to all shaders
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- OsdInterpolatePatchCoordTriangle()
|
||||
- OsdComputePerPatchVertexBoxSplineTriangle
|
||||
- OsdEvalPatchBezierTriangle()
|
||||
- OsdEvalPatchGregoryTriangle()
|
||||
- OsdGetTessLevelsUniformTriangle()
|
||||
- OsdEvalPatchBezierTessLevels()
|
||||
- OsdEvalPatchBezierTriangleTessLevels()
|
||||
- OsdGetTessParameterizationTriangle()
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
----
|
||||
|
||||
Release 3.4
|
||||
~~~~~~~~~~~
|
||||
|
||||
Release 3.4.0 - Jun 2019
|
||||
========================
|
||||
|
||||
@ -63,6 +66,9 @@ code and configuration improvements. For more information on the following, ple
|
||||
- Fixed Far::StencilTable append when base StencilTable empty (GitHub #982)
|
||||
- Patches around non-manifold vertices now free of cracks (GitHub #1013)
|
||||
|
||||
Release 3.3
|
||||
~~~~~~~~~~~
|
||||
|
||||
Release 3.3.3 - Jul 2018
|
||||
========================
|
||||
|
||||
@ -116,6 +122,9 @@ Release 3.3.0 is significant release adding an Osd implementation for Apple's Me
|
||||
- Fixed several instances of local variable shadowing that could cause build warnings
|
||||
- Updated continuous-integration build scripts and added testing on macOS
|
||||
|
||||
Release 3.2
|
||||
~~~~~~~~~~~
|
||||
|
||||
Release 3.2.0 - Feb 2017
|
||||
========================
|
||||
|
||||
@ -134,6 +143,9 @@ Release 3.2.0 is a minor release containing API additions and bug fixes
|
||||
**Bug Fixes**
|
||||
- Fixed a double delete of GL program in Osd::GLComputeEvaluator
|
||||
|
||||
Release 3.1
|
||||
~~~~~~~~~~~
|
||||
|
||||
Release 3.1.1 - Jan 2017
|
||||
========================
|
||||
|
||||
@ -179,6 +191,9 @@ code and configuration improvements. For more information on the following, ple
|
||||
- Fixed bug with refinement using Chaikin creasing
|
||||
- Fixed bugs with HUD sliders in the example viewers
|
||||
|
||||
Release 3.0
|
||||
~~~~~~~~~~~
|
||||
|
||||
Release 3.0.5 - Mar 2016
|
||||
========================
|
||||
|
||||
@ -315,7 +330,8 @@ Release 3.0.0 RC1
|
||||
supported.
|
||||
- The Osd layer was largely refactored.
|
||||
|
||||
|
||||
Previous 2.x Release Notes
|
||||
==========================
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`Previous releases <release_notes_2x.html>`_
|
||||
|
@ -139,8 +139,18 @@ the surface they define compared to the similar Bezier patch. The two patches i
|
||||
that example actually represent exactly the same piece of surface -- each with a set
|
||||
of control points having different effects on it. In mathematical terms, each control
|
||||
point has a "basis function" associated with it that affects the surface in a particular
|
||||
way when only that point is moved. It is these basis functions that often give rise
|
||||
to the names of the different patches.
|
||||
way when only that point is moved:
|
||||
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| .. image:: images/basis_bspline.jpg | .. image:: images/basis_bezier.jpg |
|
||||
| :align: center | :align: center |
|
||||
| :width: 80% | :width: 80% |
|
||||
| :target: images/basis_bspline.jpg | :target: images/basis_bezier.jpg |
|
||||
| | |
|
||||
| Bicubic B-Spline basis function | Bicubic Bezier basis funciton |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
|
||||
It is these basis functions that often give rise to the names of the different patches.
|
||||
|
||||
There are pros and cons to these different properties of the control points of patches,
|
||||
which become more apparent as we assemble patches into piecewise surfaces.
|
||||
@ -635,8 +645,7 @@ involving topology (computing the weights) and combining the data separately.
|
||||
| :width: 95% | :width: 95% | :width: 95% |
|
||||
| :target: images/data_pose_1.jpg | :target: images/data_pose_2.jpg | :target: images/data_pose_3.jpg |
|
||||
+---------------------------------------+---------------------------------------+---------------------------------------+
|
||||
| Three shapes resulting from three sets of positions for the a mesh of complex but fixed topology. |
|
||||
| (currently stand-in images until we have an animated character approved for publication) |
|
||||
| Three shapes resulting from three sets of positions for a mesh of fixed topology. |
|
||||
+---------------------------------------+---------------------------------------+---------------------------------------+
|
||||
|
||||
When the topology is fixed, enormous savings are possible by pre-computing information
|
||||
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 6.1 KiB |
@ -31,16 +31,16 @@
|
||||
#define FONT_TEXTURE_ROWS 8
|
||||
#define FONT_CHAR_WIDTH (FONT_TEXTURE_WIDTH/FONT_TEXTURE_COLUMNS)
|
||||
#define FONT_CHAR_HEIGHT (FONT_TEXTURE_HEIGHT/FONT_TEXTURE_ROWS)
|
||||
#define FONT_CHECK_BOX_OFF 0x3
|
||||
#define FONT_CHECK_BOX_ON 0x4
|
||||
#define FONT_RADIO_BUTTON_OFF 0x6
|
||||
#define FONT_RADIO_BUTTON_ON 0x7
|
||||
#define FONT_CHECK_BOX_OFF 0x2
|
||||
#define FONT_CHECK_BOX_ON 0x3
|
||||
#define FONT_RADIO_BUTTON_OFF 0x4
|
||||
#define FONT_RADIO_BUTTON_ON 0x5
|
||||
#define FONT_SLIDER_LEFT 0x10
|
||||
#define FONT_SLIDER_MIDDLE 0x11
|
||||
#define FONT_SLIDER_RIGHT 0x12
|
||||
#define FONT_SLIDER_CURSOR 0x7c
|
||||
#define FONT_ARROW_RIGHT 0x15
|
||||
#define FONT_ARROW_DOWN 0x17
|
||||
#define FONT_SLIDER_CURSOR 0x13
|
||||
#define FONT_ARROW_RIGHT 0x14
|
||||
#define FONT_ARROW_DOWN 0x15
|
||||
|
||||
extern unsigned char font_image[];
|
||||
|
||||
|
@ -556,10 +556,15 @@ Hud::Rebuild(int width, int height, int framebufferWidth, int framebufferHeight)
|
||||
}
|
||||
}
|
||||
|
||||
drawString(_staticVboSource, _windowWidth-80, _windowHeight-48, .5, .5, .5,
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f");
|
||||
drawString(_staticVboSource, _windowWidth-80, _windowHeight-32, .5, .5, .5,
|
||||
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
|
||||
// draw the character cells corresponding to the logo
|
||||
drawString(_staticVboSource, _windowWidth-128, _windowHeight-44, .5, .5, .5,
|
||||
"\x06\x07\x08\x09");
|
||||
drawString(_staticVboSource, _windowWidth-128, _windowHeight-28, .5, .5, .5,
|
||||
"\x16\x17\x18\x19");
|
||||
drawString(_staticVboSource, _windowWidth-92, _windowHeight-36, .5, .5, .5,
|
||||
"\x0a\x0b\x0c\x0d");
|
||||
drawString(_staticVboSource, _windowWidth-58, _windowHeight-36, .5, .5, .5,
|
||||
"\x1a\x1b\x1c\x1d\x1e\x1f");
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -46,7 +46,17 @@ const char* MTLPtexMipmapTexture::GetShaderSource() {
|
||||
MTLPtexMipmapTexture * MTLPtexMipmapTexture::Create(Osd::MTLContext *deviceContext, PtexTexture *reader, int maxLevels) {
|
||||
const auto maxNumPages = 2048;
|
||||
|
||||
PtexMipmapTextureLoader loader(reader, maxNumPages, maxLevels);
|
||||
size_t targetMemory = 0;
|
||||
|
||||
// Read the ptex data and pack the texels
|
||||
bool padAlpha = reader->numChannels()==3;
|
||||
|
||||
PtexMipmapTextureLoader loader(reader,
|
||||
maxNumPages,
|
||||
maxLevels,
|
||||
targetMemory,
|
||||
true/*seemlessMipmap*/,
|
||||
padAlpha);
|
||||
const auto numFaces = loader.GetNumFaces();
|
||||
|
||||
const auto layoutBuffer = [deviceContext->device newBufferWithBytes:loader.GetLayoutBuffer() length:numFaces * 6 * sizeof(short) options:Osd::MTLDefaultStorageMode];
|
||||
@ -54,7 +64,7 @@ MTLPtexMipmapTexture * MTLPtexMipmapTexture::Create(Osd::MTLContext *deviceConte
|
||||
const auto textureDescriptor = [MTLTextureDescriptor new];
|
||||
int bpp = 0;
|
||||
textureDescriptor.pixelFormat = [&]() {
|
||||
const auto numChannels = reader->numChannels();
|
||||
const auto numChannels = reader->numChannels() + padAlpha;
|
||||
switch(reader->dataType()) {
|
||||
case Ptex::dt_uint16:
|
||||
bpp = sizeof(short) * numChannels;
|
||||
|
@ -1960,7 +1960,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmd
|
||||
const char *diffuseEnvironmentMap = NULL, *specularEnvironmentMap = NULL;
|
||||
const char *colorFilename = NULL, *displacementFilename = NULL,
|
||||
*occlusionFilename = NULL, *specularFilename = NULL;
|
||||
int memLimit;
|
||||
int memLimit = 0;
|
||||
|
||||
for (int i = 0; i < (int)argv.size(); ++i) {
|
||||
if (strstr(argv[i].c_str(), ".obj"))
|
||||
|
@ -465,13 +465,7 @@ getAdaptivePatchColor(int3 patchParam, float sharpness)
|
||||
};
|
||||
|
||||
int patchType = 0;
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
if (sharpness > 0) {
|
||||
pattern = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int pattern = countbits(OsdGetPatchTransitionMask(patchParam));
|
||||
int edgeCount = countbits(OsdGetPatchBoundaryMask(patchParam));
|
||||
if (edgeCount == 1) {
|
||||
patchType = 2; // BOUNDARY
|
||||
@ -480,9 +474,11 @@ getAdaptivePatchColor(int3 patchParam, float sharpness)
|
||||
patchType = 3; // CORNER
|
||||
}
|
||||
|
||||
// XXX: it looks like edgeCount != 0 for some gregory boundary patches.
|
||||
// there might be a bug somewhere...
|
||||
#if defined OSD_PATCH_GREGORY
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
if (sharpness > 0) {
|
||||
patchType = 1;
|
||||
}
|
||||
#elif defined OSD_PATCH_GREGORY
|
||||
patchType = 4;
|
||||
#elif defined OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchType = 5;
|
||||
@ -490,6 +486,8 @@ getAdaptivePatchColor(int3 patchParam, float sharpness)
|
||||
patchType = 6;
|
||||
#endif
|
||||
|
||||
int pattern = countbits(OsdGetPatchTransitionMask(patchParam));
|
||||
|
||||
return patchColors[6*patchType + pattern];
|
||||
}
|
||||
|
||||
|
@ -135,15 +135,15 @@ int g_freeze = 0,
|
||||
g_displayStyle = kDisplayStyleWireOnShaded,
|
||||
g_adaptive = 1,
|
||||
g_endCap = kEndCapGregoryBasis,
|
||||
g_smoothCornerPatch = 0,
|
||||
g_smoothCornerPatch = 1,
|
||||
g_singleCreasePatch = 1,
|
||||
g_infSharpPatch = 0,
|
||||
g_infSharpPatch = 1,
|
||||
g_drawNormals = 0,
|
||||
g_mbutton[3] = {0, 0, 0};
|
||||
|
||||
int g_screenSpaceTess = 1,
|
||||
g_fractionalSpacing = 1,
|
||||
g_patchCull = 1,
|
||||
int g_screenSpaceTess = 0,
|
||||
g_fractionalSpacing = 0,
|
||||
g_patchCull = 0,
|
||||
g_displayPatchCounts = 0;
|
||||
|
||||
float g_rotate[2] = {0, 0},
|
||||
|
@ -72,6 +72,7 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
|
@ -416,11 +416,7 @@ getAdaptivePatchColor(int3 patchParam, float2 vSegments)
|
||||
if (vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// XXX: it looks like edgeCount != 0 for gregory_boundary.
|
||||
// there might be a bug somewhere.
|
||||
#if defined OSD_PATCH_GREGORY
|
||||
#elif defined OSD_PATCH_GREGORY
|
||||
patchType = 4;
|
||||
#elif defined OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchType = 5;
|
||||
|
@ -139,9 +139,9 @@ int g_currentShape = 0,
|
||||
g_level = 2,
|
||||
g_kernel = kCPU,
|
||||
g_endCap = kEndCapGregoryBasis,
|
||||
g_smoothCornerPatch = 0,
|
||||
g_smoothCornerPatch = 1,
|
||||
g_singleCreasePatch = 0,
|
||||
g_infSharpPatch = 0,
|
||||
g_infSharpPatch = 1,
|
||||
g_numElements = 3;
|
||||
|
||||
int g_running = 1,
|
||||
|
@ -28,66 +28,71 @@
|
||||
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) );
|
||||
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_bishop", catmark_bishop, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, 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_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, 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_pole8", catmark_pole8, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64",catmark_nonman_quadpole64,kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -82,9 +82,9 @@ int g_freeze = 0,
|
||||
g_uvCullBackface = 0,
|
||||
g_displayStyle = kWireShaded,
|
||||
g_adaptive = 1,
|
||||
g_smoothCornerPatch = 0,
|
||||
g_singleCreasePatch = 0,
|
||||
g_infSharpPatch = 0,
|
||||
g_smoothCornerPatch = 1,
|
||||
g_singleCreasePatch = 1,
|
||||
g_infSharpPatch = 1,
|
||||
g_mbutton[3] = {0, 0, 0},
|
||||
g_mouseUvView = 0,
|
||||
g_running = 1;
|
||||
@ -236,7 +236,7 @@ struct FVarData
|
||||
glBindTexture(GL_TEXTURE_BUFFER, textureBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindTexture(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
@ -251,7 +251,7 @@ struct FVarData
|
||||
glBindTexture(GL_TEXTURE_BUFFER, textureParamBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindTexture(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
@ -545,13 +545,11 @@ GetEffect(bool uvDraw = false) {
|
||||
|
||||
struct EffectDesc {
|
||||
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc,
|
||||
Effect effect) : desc(desc), fvarDesc(fvarDesc),
|
||||
Effect effect) : desc(desc),
|
||||
effect(effect),
|
||||
maxValence(0), numElements(0) { }
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor desc;
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc;
|
||||
Effect effect;
|
||||
int maxValence;
|
||||
int numElements;
|
||||
@ -559,10 +557,9 @@ struct EffectDesc {
|
||||
bool operator < (const EffectDesc &e) const {
|
||||
return
|
||||
(desc < e.desc || ((desc == e.desc &&
|
||||
(fvarDesc < e.fvarDesc || ((fvarDesc == e.fvarDesc &&
|
||||
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
|
||||
(numElements < e.numElements || ((numElements == e.numElements) &&
|
||||
(effect < e.effect)))))))))));
|
||||
(effect < e.effect))))))));
|
||||
}
|
||||
};
|
||||
|
||||
@ -589,11 +586,6 @@ public:
|
||||
|
||||
if (type == Far::PatchDescriptor::QUADS) {
|
||||
ss << "#define PRIM_QUAD\n";
|
||||
} else if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define PRIM_TRI\n";
|
||||
ss << "#define LOOP\n";
|
||||
} else {
|
||||
ss << "#define PRIM_TRI\n";
|
||||
}
|
||||
@ -626,14 +618,6 @@ public:
|
||||
ss << "#define SHADING_FACEVARYING_UNIFORM_SUBDIVISION\n";
|
||||
}
|
||||
|
||||
if (effectDesc.desc.IsAdaptive()) {
|
||||
if (effectDesc.fvarDesc.GetType() == Far::PatchDescriptor::REGULAR) {
|
||||
ss << "#define SHADING_FACEVARYING_SMOOTH_BSPLINE_BASIS\n";
|
||||
} else if (effectDesc.fvarDesc.GetType() == Far::PatchDescriptor::GREGORY_BASIS) {
|
||||
ss << "#define SHADING_FACEVARYING_SMOOTH_GREGORY_BASIS\n";
|
||||
}
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
ss << "#define OSD_PATCH_BASIS_GLSL\n";
|
||||
ss << Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
@ -699,7 +683,7 @@ public:
|
||||
glUniformBlockBinding(program, uboIndex, g_tessellationBinding);
|
||||
|
||||
g_fvarArrayDataBinding = 2;
|
||||
uboIndex = glGetUniformBlockIndex(program, "FVarArrayData");
|
||||
uboIndex = glGetUniformBlockIndex(program, "OsdFVarArrayData");
|
||||
if (uboIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(program, uboIndex, g_fvarArrayDataBinding);
|
||||
|
||||
@ -802,10 +786,9 @@ bindTextures() {
|
||||
|
||||
static GLenum
|
||||
bindProgram(Effect effect,
|
||||
OpenSubdiv::Osd::PatchArray const & patch,
|
||||
OpenSubdiv::Far::PatchDescriptor const & fvarDesc) {
|
||||
OpenSubdiv::Osd::PatchArray const & patch) {
|
||||
|
||||
EffectDesc effectDesc(patch.GetDescriptor(), fvarDesc, effect);
|
||||
EffectDesc effectDesc(patch.GetDescriptor(), effect);
|
||||
|
||||
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
|
||||
|
||||
@ -884,9 +867,6 @@ display() {
|
||||
|
||||
glBindVertexArray(g_vao);
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc =
|
||||
g_mesh->GetFarPatchTable()->GetFVarPatchDescriptor(0);
|
||||
|
||||
OpenSubdiv::Osd::PatchArrayVector const & patches =
|
||||
g_mesh->GetPatchTable()->GetPatchArrays();
|
||||
|
||||
@ -900,7 +880,7 @@ display() {
|
||||
for (int i = 0; i < (int)patches.size(); ++i) {
|
||||
OpenSubdiv::Osd::PatchArray const & patch = patches[i];
|
||||
|
||||
GLenum primType = bindProgram(GetEffect(), patch, fvarDesc);
|
||||
GLenum primType = bindProgram(GetEffect(), patch);
|
||||
|
||||
glDrawElements(
|
||||
primType,
|
||||
@ -934,7 +914,7 @@ display() {
|
||||
for (int i = 0; i < (int)patches.size(); ++i) {
|
||||
OpenSubdiv::Osd::PatchArray const & patch = patches[i];
|
||||
|
||||
GLenum primType = bindProgram(GetEffect(/*uvDraw=*/ true), patch, fvarDesc);
|
||||
GLenum primType = bindProgram(GetEffect(/*uvDraw=*/ true), patch);
|
||||
|
||||
glDrawElements(
|
||||
primType,
|
||||
@ -1189,7 +1169,7 @@ initHUD() {
|
||||
10, 60, callbackControlEdges, 0, 'h');
|
||||
g_hud.AddCheckBox("Control vertices (J)", g_controlMeshDisplay.GetVerticesDisplay(),
|
||||
10, 80, callbackControlVertices, 0, 'j');
|
||||
g_hud.AddCheckBox("UV Backface Culling (B)", g_uvCullBackface,
|
||||
g_hud.AddCheckBox("UV Backface Culling (B)", g_uvCullBackface != 0,
|
||||
10, 100, callbackUVCullBackface, 0, 'b');
|
||||
|
||||
int shading_pulldown = g_hud.AddPullDown("Display Style (W)",
|
||||
|
@ -60,6 +60,7 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
|
@ -167,7 +167,7 @@ out block {
|
||||
} outpt;
|
||||
|
||||
uniform isamplerBuffer OsdFVarParamBuffer;
|
||||
layout(std140) uniform FVarArrayData {
|
||||
layout(std140) uniform OsdFVarArrayData {
|
||||
OsdPatchArray fvarPatchArray[2];
|
||||
};
|
||||
|
||||
@ -211,25 +211,22 @@ void emit(int index, vec3 normal)
|
||||
outpt.v.normal = normal;
|
||||
#endif
|
||||
|
||||
#ifdef LOOP // ----- scheme : LOOP
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
// interpolate fvar data at refined tri or quad vertex locations
|
||||
#ifdef PRIM_TRI
|
||||
vec2 trist[3] = vec2[](vec2(0,0), vec2(1,0), vec2(0,1));
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
vec2 st = trist[index];
|
||||
#else
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
|
||||
|
||||
#else // ----- scheme : CATMARK / BILINEAR
|
||||
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
#ifdef PRIM_QUAD
|
||||
vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
|
||||
vec2 st = quadst[index];
|
||||
#endif
|
||||
#else
|
||||
// interpolate fvar data at tessellated vertex locations
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
|
||||
#endif // ------ scheme
|
||||
|
||||
outpt.color = vec3(uv.s, uv.t, 0);
|
||||
|
||||
|
@ -117,11 +117,6 @@ public:
|
||||
} else if (type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n";
|
||||
}
|
||||
if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define LOOP\n";
|
||||
}
|
||||
|
||||
if (desc.IsAdaptive()) {
|
||||
ss << "#define SMOOTH_NORMALS\n";
|
||||
@ -658,12 +653,12 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
ofs << "</tr>\n";
|
||||
|
||||
for (size_t i = 0; i < g_shapes.size(); ++i) {
|
||||
for (size_t i = 0; i < g_defaultShapes.size(); ++i) {
|
||||
ofs << "<tr>\n";
|
||||
ofs << "<td>" << g_shapes[i].name << "</td>\n";
|
||||
ofs << "<td>" << g_defaultShapes[i].name << "</td>\n";
|
||||
for (size_t k = 0; k < kernels.size(); ++k) {
|
||||
ofs << "<td>";
|
||||
ofs << "<img src='" << prefix << "_" << kernels[k] << "_" << g_shapes[i].name << ".png'>";
|
||||
ofs << "<img src='" << prefix << "_" << kernels[k] << "_" << g_defaultShapes[i].name << ".png'>";
|
||||
ofs << "</td>";
|
||||
}
|
||||
ofs << "</tr>\n";
|
||||
@ -698,9 +693,9 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (size_t i = 0; i < g_shapes.size(); ++i) {
|
||||
for (size_t i = 0; i < g_defaultShapes.size(); ++i) {
|
||||
// run test
|
||||
runTest(g_shapes[i], kernel, isolationLevel, adaptive, &shaderCache);
|
||||
runTest(g_defaultShapes[i], kernel, isolationLevel, adaptive, &shaderCache);
|
||||
|
||||
if (writeToFile) {
|
||||
// read back pixels
|
||||
@ -708,7 +703,7 @@ int main(int argc, char ** argv) {
|
||||
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
|
||||
|
||||
// write image
|
||||
std::string filename = prefix + "_" + kernel + "_" + g_shapes[i].name + ".png";
|
||||
std::string filename = prefix + "_" + kernel + "_" + g_defaultShapes[i].name + ".png";
|
||||
// flip vertical
|
||||
stbi_write_png(filename.c_str(), width, height, 3, &data[width*3*(height-1)], -width*3);
|
||||
}
|
||||
|
@ -26,83 +26,73 @@
|
||||
#include "../../regression/shapes/all.h"
|
||||
|
||||
|
||||
static std::vector<ShapeDesc> g_shapes;
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, 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_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, 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_pole8", catmark_pole8, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64",catmark_nonman_quadpole64,kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) );
|
||||
g_shapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
|
||||
g_shapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_fvar_bound0", loop_fvar_bound0, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_fvar_bound1", loop_fvar_bound1, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_fvar_bound2", loop_fvar_bound2, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_fvar_bound3", loop_fvar_bound3, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
|
||||
g_shapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
|
||||
|
||||
g_shapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) );
|
||||
g_shapes.push_back( ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear ) );
|
||||
g_shapes.push_back( ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear ) );
|
||||
g_shapes.push_back( ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -44,6 +44,13 @@
|
||||
mix(mix(inpt[a].color, inpt[b].color, UV.x), \
|
||||
mix(inpt[c].color, inpt[d].color, UV.x), UV.y)
|
||||
|
||||
#undef OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c) \
|
||||
outpt.color = \
|
||||
inpt[a].color * (1.0f - UV.x - UV.y) + \
|
||||
inpt[b].color * UV.x + \
|
||||
inpt[c].color * UV.y;
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Uniforms / Uniform Blocks
|
||||
//--------------------------------------------------------------
|
||||
@ -358,7 +365,7 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
patchType = 3; // CORNER (not correct for patches that are not isolated)
|
||||
}
|
||||
|
||||
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (inpt.vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
|
@ -109,7 +109,7 @@ int g_running = 1,
|
||||
g_displayDisplacement = 0,
|
||||
g_mbutton[3] = {0, 0, 0};
|
||||
|
||||
int g_brushSize = 500;
|
||||
int g_brushSize = 100;
|
||||
int g_frame = 0;
|
||||
|
||||
GLuint g_ptexPages = 0,
|
||||
@ -704,16 +704,16 @@ display() {
|
||||
averageFps += g_fpsTimeSamples[i]/(float)NUM_FPS_TIME_SAMPLES;
|
||||
}
|
||||
|
||||
g_hud.DrawString(10, -180, "Tess level (+/-): %d", g_tessLevel);
|
||||
g_hud.DrawString(10, -100, "Tess level (+/-): %d", g_tessLevel);
|
||||
if (numPrimsGenerated > 1000000) {
|
||||
g_hud.DrawString(10, -160, "Primitives : %3.1f million", (float)numPrimsGenerated/1000000.0);
|
||||
g_hud.DrawString(10, -80, "Primitives : %3.1f million", (float)numPrimsGenerated/1000000.0);
|
||||
} else if (numPrimsGenerated > 1000) {
|
||||
g_hud.DrawString(10, -160, "Primitives : %3.1f thousand", (float)numPrimsGenerated/1000.0);
|
||||
g_hud.DrawString(10, -80, "Primitives : %3.1f thousand", (float)numPrimsGenerated/1000.0);
|
||||
} else {
|
||||
g_hud.DrawString(10, -160, "Primitives : %d", numPrimsGenerated);
|
||||
g_hud.DrawString(10, -80, "Primitives : %d", numPrimsGenerated);
|
||||
}
|
||||
g_hud.DrawString(10, -140, "Vertices : %d", g_mesh->GetNumVertices());
|
||||
g_hud.DrawString(10, -20, "FPS : %3.1f", averageFps);
|
||||
g_hud.DrawString(10, -60, "Vertices : %d", g_mesh->GetNumVertices());
|
||||
g_hud.DrawString(10, -20, "FPS : %3.1f", averageFps);
|
||||
}
|
||||
|
||||
g_hud.Flush();
|
||||
@ -961,6 +961,12 @@ callbackModel(int m) {
|
||||
createOsdMesh();
|
||||
}
|
||||
|
||||
static void
|
||||
callbackBrushSize(float value, int /* data */) {
|
||||
|
||||
g_brushSize = (int)value;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
initHUD() {
|
||||
@ -982,6 +988,9 @@ initHUD() {
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Shaded", 1, g_wire==1);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Wire+Shaded", 2, g_wire==2);
|
||||
|
||||
g_hud.AddSlider("Brush size", 10, 500, g_brushSize,
|
||||
350, -60, 40, true, callbackBrushSize, 0);
|
||||
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
char level[16];
|
||||
sprintf(level, "Lv. %d", i);
|
||||
|
@ -704,11 +704,6 @@ public:
|
||||
} else if (type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n";
|
||||
}
|
||||
if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define LOOP\n";
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
ss << Osd::GLSLPatchShaderSource::GetCommonShaderSource();
|
||||
|
@ -475,7 +475,7 @@ GetOverrideColor(ivec3 patchParam)
|
||||
patchType = 3; // CORNER (not correct for patches that are not isolated)
|
||||
}
|
||||
|
||||
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (inpt.vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
|
@ -378,11 +378,6 @@ public:
|
||||
} else if (type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n";
|
||||
}
|
||||
if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define LOOP\n";
|
||||
}
|
||||
|
||||
// for legacy gregory
|
||||
ss << "#define OSD_MAX_VALENCE " << effectDesc.maxValence << "\n";
|
||||
|
@ -424,7 +424,7 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
patchType = 3; // CORNER (not correct for patches that are not isolated)
|
||||
}
|
||||
|
||||
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (inpt.vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
|
@ -121,7 +121,7 @@ int g_running = 1,
|
||||
g_repeatCount=0;
|
||||
|
||||
bool g_adaptive=true,
|
||||
g_infSharpPatch=false;
|
||||
g_infSharpPatch=true;
|
||||
|
||||
float g_rotate[2] = {0, 0},
|
||||
g_dolly = 5,
|
||||
|
@ -30,60 +30,69 @@ static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) );
|
||||
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_bishop", catmark_bishop, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, 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_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, 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_pole8", catmark_pole8, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64",catmark_nonman_quadpole64,kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -184,9 +184,9 @@ int g_freeze = 0,
|
||||
g_displayStyle = kDisplayStyleWireOnShaded,
|
||||
g_adaptive = 1,
|
||||
g_endCap = kEndCapGregoryBasis,
|
||||
g_smoothCornerPatch = 0,
|
||||
g_smoothCornerPatch = 1,
|
||||
g_singleCreasePatch = 1,
|
||||
g_infSharpPatch = 0,
|
||||
g_infSharpPatch = 1,
|
||||
g_mbutton[3] = {0, 0, 0},
|
||||
g_running = 1;
|
||||
|
||||
@ -233,7 +233,9 @@ GLuint g_transformUB = 0,
|
||||
g_tessellationUB = 0,
|
||||
g_tessellationBinding = 1,
|
||||
g_lightingUB = 0,
|
||||
g_lightingBinding = 2;
|
||||
g_lightingBinding = 2,
|
||||
g_fvarArrayDataUB = 0,
|
||||
g_fvarArrayDataBinding = 3;
|
||||
|
||||
struct Transform {
|
||||
float ModelViewMatrix[16];
|
||||
@ -251,7 +253,7 @@ GLuint g_vao = 0;
|
||||
struct FVarData
|
||||
{
|
||||
FVarData() :
|
||||
textureBuffer(0) {
|
||||
textureBuffer(0), textureParamBuffer(0) {
|
||||
}
|
||||
~FVarData() {
|
||||
Release();
|
||||
@ -260,11 +262,17 @@ struct FVarData
|
||||
if (textureBuffer)
|
||||
glDeleteTextures(1, &textureBuffer);
|
||||
textureBuffer = 0;
|
||||
if (textureParamBuffer)
|
||||
glDeleteTextures(1, &textureParamBuffer);
|
||||
textureParamBuffer = 0;
|
||||
}
|
||||
void Create(OpenSubdiv::Far::PatchTable const *patchTable,
|
||||
int fvarWidth, std::vector<float> const & fvarSrcData) {
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
Release();
|
||||
OpenSubdiv::Far::ConstIndexArray indices = patchTable->GetFVarValues();
|
||||
Far::ConstIndexArray indices = patchTable->GetFVarValues();
|
||||
|
||||
// expand fvardata to per-patch array
|
||||
std::vector<float> data;
|
||||
@ -289,8 +297,22 @@ struct FVarData
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
Far::ConstPatchParamArray fvarParam = patchTable->GetFVarPatchParams();
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, fvarParam.size()*sizeof(Far::PatchParam),
|
||||
&fvarParam[0], GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &textureParamBuffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, textureParamBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
GLuint textureBuffer;
|
||||
GLuint textureBuffer, textureParamBuffer;
|
||||
} g_fvarData;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -780,11 +802,6 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define LOOP\n";
|
||||
}
|
||||
if (type != Far::PatchDescriptor::TRIANGLES &&
|
||||
type != Far::PatchDescriptor::QUADS) {
|
||||
ss << "#define SMOOTH_NORMALS\n";
|
||||
@ -869,6 +886,10 @@ public:
|
||||
if (uboIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(program, uboIndex, g_lightingBinding);
|
||||
|
||||
uboIndex = glGetUniformBlockIndex(program, "OsdFVarArrayData");
|
||||
if (uboIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(program, uboIndex, g_fvarArrayDataBinding);
|
||||
|
||||
// assign texture locations
|
||||
GLint loc;
|
||||
glUseProgram(program);
|
||||
@ -878,16 +899,19 @@ public:
|
||||
if ((loc = glGetUniformLocation(program, "OsdFVarDataBuffer")) != -1) {
|
||||
glUniform1i(loc, 1); // GL_TEXTURE1
|
||||
}
|
||||
// for legacy gregory patches
|
||||
if ((loc = glGetUniformLocation(program, "OsdVertexBuffer")) != -1) {
|
||||
if ((loc = glGetUniformLocation(program, "OsdFVarParamBuffer")) != -1) {
|
||||
glUniform1i(loc, 2); // GL_TEXTURE2
|
||||
}
|
||||
if ((loc = glGetUniformLocation(program, "OsdValenceBuffer")) != -1) {
|
||||
// for legacy gregory patches
|
||||
if ((loc = glGetUniformLocation(program, "OsdVertexBuffer")) != -1) {
|
||||
glUniform1i(loc, 3); // GL_TEXTURE3
|
||||
}
|
||||
if ((loc = glGetUniformLocation(program, "OsdQuadOffsetBuffer")) != -1) {
|
||||
if ((loc = glGetUniformLocation(program, "OsdValenceBuffer")) != -1) {
|
||||
glUniform1i(loc, 4); // GL_TEXTURE4
|
||||
}
|
||||
if ((loc = glGetUniformLocation(program, "OsdQuadOffsetBuffer")) != -1) {
|
||||
glUniform1i(loc, 5); // GL_TEXTURE5
|
||||
}
|
||||
glUseProgram(0);
|
||||
|
||||
return config;
|
||||
@ -899,6 +923,9 @@ ShaderCache g_shaderCache;
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
updateUniformBlocks() {
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
if (! g_transformUB) {
|
||||
glGenBuffers(1, &g_transformUB);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
|
||||
@ -932,6 +959,29 @@ updateUniformBlocks() {
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB);
|
||||
|
||||
// Update and bind fvar patch array state
|
||||
if (g_mesh->GetPatchTable()->GetNumFVarChannels() > 0) {
|
||||
Osd::PatchArrayVector const &fvarPatchArrays =
|
||||
g_mesh->GetPatchTable()->GetFVarPatchArrays();
|
||||
|
||||
// bind patch arrays UBO (std140 struct size padded to vec4 alignment)
|
||||
int patchArraySize =
|
||||
sizeof(GLint) * ((sizeof(Osd::PatchArray)/sizeof(GLint) + 3) & ~3);
|
||||
if (!g_fvarArrayDataUB) {
|
||||
glGenBuffers(1, &g_fvarArrayDataUB);
|
||||
}
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_fvarArrayDataUB);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
fvarPatchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
|
||||
for (int i=0; i<(int)fvarPatchArrays.size(); ++i) {
|
||||
glBufferSubData(GL_UNIFORM_BUFFER,
|
||||
i*patchArraySize, sizeof(Osd::PatchArray), &fvarPatchArrays[i]);
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER,
|
||||
g_fvarArrayDataBinding, g_fvarArrayDataUB);
|
||||
}
|
||||
|
||||
// Update and bind lighting state
|
||||
struct Lighting {
|
||||
struct Light {
|
||||
@ -978,17 +1028,20 @@ bindTextures() {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_fvarData.textureBuffer);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_fvarData.textureParamBuffer);
|
||||
}
|
||||
|
||||
// legacy gregory
|
||||
if (g_legacyGregoryPatchTable) {
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_legacyGregoryPatchTable->GetVertexTextureBuffer());
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_legacyGregoryPatchTable->GetVertexValenceTextureBuffer());
|
||||
g_legacyGregoryPatchTable->GetVertexTextureBuffer());
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_legacyGregoryPatchTable->GetVertexValenceTextureBuffer());
|
||||
glActiveTexture(GL_TEXTURE5);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
g_legacyGregoryPatchTable->GetQuadOffsetsTextureBuffer());
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
|
@ -179,23 +179,29 @@ out block {
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
uniform isamplerBuffer OsdFVarParamBuffer;
|
||||
layout(std140) uniform OsdFVarArrayData {
|
||||
OsdPatchArray fvarPatchArray[2];
|
||||
};
|
||||
|
||||
vec2
|
||||
interpolateFaceVarying(vec2 uv, int fvarOffset)
|
||||
{
|
||||
int patchIndex = OsdGetPatchIndex(gl_PrimitiveID);
|
||||
|
||||
OsdPatchArray array = fvarPatchArray[0];
|
||||
|
||||
ivec3 fvarPatchParam = texelFetch(OsdFVarParamBuffer, patchIndex).xyz;
|
||||
OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,
|
||||
fvarPatchParam.y,
|
||||
fvarPatchParam.z);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
#ifdef LOOP
|
||||
int patchType = OSD_PATCH_DESCRIPTOR_TRIANGLES;
|
||||
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
|
||||
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
|
||||
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
#else
|
||||
int patchType = OSD_PATCH_DESCRIPTOR_QUADS;
|
||||
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
|
||||
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
|
||||
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
#endif
|
||||
|
||||
int patchArrayStride = numPoints;
|
||||
|
||||
int primOffset = patchIndex * patchArrayStride;
|
||||
@ -230,27 +236,22 @@ void emit(int index, vec3 normal)
|
||||
#endif
|
||||
|
||||
#ifdef SHADING_FACEVARYING_COLOR
|
||||
#ifdef LOOP // ----- scheme : LOOP
|
||||
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
// interpolate fvar data at refined tri or quad vertex locations
|
||||
#ifdef PRIM_TRI
|
||||
vec2 trist[3] = vec2[](vec2(0,0), vec2(1,0), vec2(0,1));
|
||||
vec2 st = trist[index];
|
||||
#else
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
|
||||
|
||||
#else // ----- scheme : CATMARK / BILINEAR
|
||||
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
#ifdef PRIM_QUAD
|
||||
vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
|
||||
vec2 st = quadst[index];
|
||||
#endif
|
||||
#else
|
||||
// interpolate fvar data at tessellated vertex locations
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
|
||||
|
||||
#endif // ------ scheme
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
|
||||
outpt.color = vec3(uv.s, uv.t, 0);
|
||||
#endif
|
||||
|
||||
@ -324,8 +325,8 @@ void main()
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef PRIM_TRI
|
||||
vec3 A = (inpt[1].v.position - inpt[0].v.position).xyz;
|
||||
vec3 B = (inpt[2].v.position - inpt[0].v.position).xyz;
|
||||
vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
|
||||
vec3 B = (inpt[2].v.position - inpt[1].v.position).xyz;
|
||||
vec3 n0 = normalize(cross(B, A));
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
@ -502,7 +503,7 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
patchType = 3; // CORNER (not correct for patches that are not isolated)
|
||||
}
|
||||
|
||||
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (inpt.vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
|
@ -90,12 +90,17 @@ enum {
|
||||
|
||||
-(void)keyDown:(NSEvent *)event {
|
||||
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
|
||||
if(key == '=') {
|
||||
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16.0f);
|
||||
if (hud.KeyDown(key)) {
|
||||
return;
|
||||
} else if(key == '=') {
|
||||
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16);
|
||||
} else if (key == '-') {
|
||||
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0.0f);
|
||||
} else if(!hud.KeyDown(key))
|
||||
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0);
|
||||
} else if (key == 'f') {
|
||||
[_controller.osdRenderer fitFrame];
|
||||
} else {
|
||||
[super keyDown:event];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)scrollWheel:(NSEvent *)event {
|
||||
@ -184,6 +189,9 @@ enum {
|
||||
case kHUD_CB_FRACTIONAL_SPACING:
|
||||
self.osdRenderer.useFractionalTessellation = checked;
|
||||
break;
|
||||
case kHUD_CB_SEAMLESS_MIPMAP:
|
||||
self.osdRenderer.useSeamlessMipmap = checked;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown checkbox ID" && 0);
|
||||
}
|
||||
@ -397,8 +405,6 @@ enum {
|
||||
|
||||
auto commandBuffer = [_commandQueue commandBuffer];
|
||||
|
||||
_osdRenderer.displacementScale = 3;
|
||||
|
||||
double avg = 0;
|
||||
for(int i = 0; i < FRAME_HISTORY; i++)
|
||||
avg += _frameBeginTimestamp[i];
|
||||
@ -408,7 +414,7 @@ enum {
|
||||
|
||||
auto& hud = self.view->hud;
|
||||
if(hud.IsVisible()) {
|
||||
hud.DrawString(10, -120, "Tess level : %f", _osdRenderer.tessellationLevel);
|
||||
hud.DrawString(10, -120, "Tess level : %d", _osdRenderer.tessellationLevel);
|
||||
hud.DrawString(10, -20, "FPS = %3.1f", 1.0 / avg);
|
||||
|
||||
//Disable Culling & Force Fill mode when drawing the UI
|
||||
|
@ -1,111 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../../regression/common/shape_utils.h"
|
||||
#include "../../regression/shapes/all.h"
|
||||
|
||||
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
// g_defaultShapes.push_back(ShapeDesc("temple", Viewer::shapes::temple, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fan", catmark_fan, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_flap", catmark_flap, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_flap2", catmark_flap2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases1", catmark_tent_creases1, kCatmark));
|
||||
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 ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
//
|
||||
// g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
//
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole8", loop_pole8, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole360", loop_pole360, kLoop));
|
||||
}
|
@ -63,13 +63,12 @@ typedef struct {
|
||||
|
||||
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
-(void)fitFrame;
|
||||
|
||||
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
|
||||
|
||||
@property (nonatomic) unsigned refinementLevel;
|
||||
@property (nonatomic) float tessellationLevel;
|
||||
|
||||
@property (readonly, nonatomic) NSArray<NSString*>* loadedModels;
|
||||
@property (nonatomic) NSString* currentModel;
|
||||
@property (nonatomic) int tessellationLevel;
|
||||
|
||||
@property (readonly, nonatomic) Camera* camera;
|
||||
|
||||
@ -80,7 +79,8 @@ typedef struct {
|
||||
@property (nonatomic) bool usePatchIndexBuffer;
|
||||
@property (nonatomic) bool usePatchBackfaceCulling;
|
||||
@property (nonatomic) bool usePatchClipCulling;
|
||||
@property (nonatomic) bool useSingleCrease;
|
||||
@property (nonatomic) bool useSmoothCornerPatch;
|
||||
@property (nonatomic) bool useSingleCreasePatch;
|
||||
@property (nonatomic) bool useInfinitelySharpPatch;
|
||||
@property (nonatomic) bool useStageIn;
|
||||
@property (nonatomic) bool usePrimitiveBackfaceCulling;
|
||||
@ -91,6 +91,7 @@ typedef struct {
|
||||
@property (nonatomic) bool displayControlMeshVertices;
|
||||
@property (nonatomic) bool displaySpecular;
|
||||
@property (nonatomic) bool displayOcclusion;
|
||||
@property (nonatomic) bool yup;
|
||||
@property (nonatomic) float mipmapBias;
|
||||
@property (nonatomic) float displacementScale;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#line 0 "examples/mtlPtexViewer/mtlPtexViewer.metal"
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
// Copyright 2013-2019 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
@ -26,6 +26,10 @@
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#if OSD_IS_ADAPTIVE
|
||||
static_assert(!OSD_ENABLE_SCREENSPACE_TESSELLATION || !USE_PTVS_FACTORS, "USE_PTVS_FACTORS cannot be enabled if OSD_ENABLE_SCREENSPACE_TESSELLATION is enabled");
|
||||
#endif
|
||||
|
||||
struct Config {
|
||||
float displacementScale;
|
||||
float mipmapBias;
|
||||
@ -64,11 +68,11 @@ const constant float4 patchColors[] = {
|
||||
float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
|
||||
|
||||
float4(0.0f, 1.0f, 0.0f, 1.0f), // corner
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 0
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 1
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 2
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 3
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 4
|
||||
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
@ -95,33 +99,32 @@ const constant float4 patchColors[] = {
|
||||
float4
|
||||
getAdaptivePatchColor(int3 patchParam, float sharpness)
|
||||
{
|
||||
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
|
||||
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
|
||||
|
||||
int patchType = 0;
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
if (sharpness > 0) {
|
||||
pattern = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
|
||||
if (edgeCount == 1) {
|
||||
patchType = 2; // BOUNDARY
|
||||
}
|
||||
if (edgeCount == 2) {
|
||||
if (edgeCount > 1) {
|
||||
patchType = 3; // CORNER
|
||||
}
|
||||
|
||||
// XXX: it looks like edgeCount != 0 for some gregory boundary patches.
|
||||
// there might be a bug somewhere...
|
||||
#if OSD_PATCH_GREGORY
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
if (sharpness > 0) {
|
||||
patchType = 1;
|
||||
}
|
||||
#elif OSD_PATCH_GREGORY
|
||||
patchType = 4;
|
||||
#elif OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchType = 5;
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
patchType = 6;
|
||||
#elif OSD_PATCH_GREGORY_TRIANGLE
|
||||
patchType = 6;
|
||||
#endif
|
||||
|
||||
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
|
||||
|
||||
return patchColors[6*patchType + pattern];
|
||||
}
|
||||
|
||||
@ -248,10 +251,9 @@ struct FragmentInput
|
||||
|
||||
#if OSD_IS_ADAPTIVE
|
||||
#if USE_STAGE_IN
|
||||
#if OSD_PATCH_REGULAR
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float3 P1 [[attribute(1)]];
|
||||
@ -261,6 +263,21 @@ struct ControlPoint
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
struct ControlPoint
|
||||
{
|
||||
float3 P [[attribute(0)]];
|
||||
float3 Ep [[attribute(1)]];
|
||||
float3 Em [[attribute(2)]];
|
||||
float3 Fp [[attribute(3)]];
|
||||
float3 Fm [[attribute(4)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE
|
||||
struct ControlPoint
|
||||
{
|
||||
float3 position [[attribute(0)]];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
@ -271,77 +288,67 @@ struct PatchInput
|
||||
#endif
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
float3 Ep [[attribute(1)]];
|
||||
float3 Em [[attribute(2)]];
|
||||
float3 Fp [[attribute(3)]];
|
||||
float3 Fm [[attribute(4)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
struct ControlPoint
|
||||
{
|
||||
float3 position [[attribute(0)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
typedef MTLQuadTessellationFactorsHalf PatchTessFactors;
|
||||
#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE
|
||||
typedef MTLTriangleTessellationFactorsHalf PatchTessFactors;
|
||||
#endif
|
||||
|
||||
|
||||
kernel void compute_main(
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
unsigned thread_position_in_grid [[thread_position_in_grid]],
|
||||
unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]],
|
||||
unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]],
|
||||
OsdPatchParamBufferSet osdBuffers,
|
||||
device MTLQuadTessellationFactorsHalf* quadTessellationFactors [[buffer(QUAD_TESSFACTORS_INDEX)]]
|
||||
device PatchTessFactors* patchTessellationFactors [[buffer(PATCH_TESSFACTORS_INDEX)]]
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
,device unsigned* patchIndex [[buffer(OSD_PATCH_INDEX_BUFFER_INDEX)]]
|
||||
,device MTLDrawPatchIndirectArguments* drawIndirectCommands [[buffer(OSD_DRAWINDIRECT_BUFFER_INDEX)]]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
//----------------------------------------------------------
|
||||
// OSD Kernel Setup
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define PATCHES_PER_THREADGROUP (THREADS_PER_THREADGROUP / THREADS_PER_PATCH)
|
||||
int const primitiveID = thread_position_in_grid / THREADS_PER_PATCH;
|
||||
int const primitiveIDInTG = thread_position_in_threadgroup / THREADS_PER_PATCH;
|
||||
int const vertexIndex = threadgroup_position_in_grid * PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH +
|
||||
thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD;
|
||||
int const vertexIndexInTG = thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD;
|
||||
int const invocationID = (thread_position_in_threadgroup * VERTEX_CONTROL_POINTS_PER_THREAD) % (THREADS_PER_PATCH*VERTEX_CONTROL_POINTS_PER_THREAD);
|
||||
|
||||
//Contains the shared patchParam value used by all threads that act upon a single patch
|
||||
//the .z (sharpness) field is set to -1 (NAN) if that patch should be culled to signal other threads to return.
|
||||
threadgroup int3 patchParam[PATCHES_PER_THREADGROUP];
|
||||
threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH];
|
||||
|
||||
const auto real_threadgroup = thread_position_in_grid / REAL_THREADGROUP_DIVISOR;
|
||||
const auto subthreadgroup_in_threadgroup = thread_position_in_threadgroup / REAL_THREADGROUP_DIVISOR;
|
||||
const auto real_thread_in_threadgroup = thread_position_in_threadgroup & (REAL_THREADGROUP_DIVISOR - 1);
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
const auto validThread = thread_position_in_grid * CONTROL_POINTS_PER_THREAD < osdBuffers.kernelExecutionLimit;
|
||||
#else
|
||||
const auto validThread = true;
|
||||
if(thread_position_in_grid * CONTROL_POINTS_PER_THREAD >= osdBuffers.kernelExecutionLimit)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(validThread)
|
||||
//----------------------------------------------------------
|
||||
// OSD Vertex Transform
|
||||
//----------------------------------------------------------
|
||||
{
|
||||
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
|
||||
patchParam[primitiveIDInTG] = OsdGetPatchParam(primitiveID, osdBuffers.patchParamBuffer);
|
||||
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
for (unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; ++threadOffset)
|
||||
{
|
||||
const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride];
|
||||
const auto v = osdBuffers.vertexBuffer[vertexId];
|
||||
if (vertexIndexInTG + threadOffset < PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH)
|
||||
{
|
||||
const auto vertexId = osdBuffers.indexBuffer[(vertexIndex + threadOffset)];
|
||||
const auto v = osdBuffers.vertexBuffer[vertexId];
|
||||
|
||||
threadgroup auto& patchVertex = patchVertices[thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset];
|
||||
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
|
||||
//User per vertex goes here, modifying 'patchVertex'
|
||||
threadgroup auto& patchVertex = patchVertices[vertexIndexInTG + threadOffset];
|
||||
|
||||
//----------------------------------------------------------
|
||||
// User Vertex Transform
|
||||
//----------------------------------------------------------
|
||||
|
||||
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,27 +356,31 @@ kernel void compute_main(
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread)
|
||||
//----------------------------------------------------------
|
||||
// OSD Patch Cull
|
||||
//----------------------------------------------------------
|
||||
{
|
||||
#if PATCHES_PER_THREADGROUP > 1
|
||||
auto patch = patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_THREAD * CONTROL_POINTS_PER_PATCH;
|
||||
#else
|
||||
//Small optimization for the '1 patch per threadgroup' case
|
||||
auto patch = patchVertices;
|
||||
#endif
|
||||
auto patch = patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH;
|
||||
|
||||
if(!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
|
||||
if (!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
|
||||
{
|
||||
#if !OSD_USE_PATCH_INDEX_BUFFER
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[1] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[2] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[3] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[1] = 0.0h;
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[3] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].insideTessellationFactor[0] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].insideTessellationFactor[1] = 0.0h;
|
||||
#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h;
|
||||
patchTessellationFactors[primitiveID].insideTessellationFactor = 0.0h;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
patchParam[subthreadgroup_in_threadgroup].z = -1;
|
||||
patchParam[primitiveIDInTG].z = -1;
|
||||
#if !NEEDS_BARRIER
|
||||
return;
|
||||
#endif
|
||||
@ -380,18 +391,24 @@ kernel void compute_main(
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread && patchParam[subthreadgroup_in_threadgroup].z != -1)
|
||||
//----------------------------------------------------------
|
||||
// OSD Patch Compute
|
||||
//----------------------------------------------------------
|
||||
if (patchParam[primitiveIDInTG].z != -1)
|
||||
{
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
for (unsigned threadOffset = 0; threadOffset < VERTEX_CONTROL_POINTS_PER_THREAD; ++threadOffset)
|
||||
{
|
||||
OsdComputePerPatchVertex(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
real_thread_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
real_threadgroup,
|
||||
thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers
|
||||
);
|
||||
if (invocationID + threadOffset < VERTEX_CONTROL_POINTS_PER_PATCH)
|
||||
{
|
||||
OsdComputePerPatchVertex(
|
||||
patchParam[primitiveIDInTG],
|
||||
invocationID + threadOffset,
|
||||
primitiveID,
|
||||
invocationID + threadOffset + primitiveID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,26 +416,29 @@ kernel void compute_main(
|
||||
threadgroup_barrier(mem_flags::mem_device_and_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread && real_thread_in_threadgroup == 0)
|
||||
//----------------------------------------------------------
|
||||
// OSD Tessellation Factors
|
||||
//----------------------------------------------------------
|
||||
if (invocationID == 0)
|
||||
{
|
||||
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed);
|
||||
patchIndex[patchId] = real_threadgroup;
|
||||
patchIndex[patchId] = primitiveID;
|
||||
#else
|
||||
const auto patchId = real_threadgroup;
|
||||
const auto patchId = primitiveID;
|
||||
#endif
|
||||
|
||||
OsdComputePerPatchFactors(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
patchParam[primitiveIDInTG],
|
||||
frameConsts.TessLevel,
|
||||
real_threadgroup,
|
||||
primitiveID,
|
||||
frameConsts.ProjectionMatrix,
|
||||
frameConsts.ModelViewMatrix,
|
||||
osdBuffers,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
quadTessellationFactors[patchId]
|
||||
);
|
||||
patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH,
|
||||
patchTessellationFactors[patchId]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -607,14 +627,14 @@ fragment float4 fragment_main(
|
||||
float3 normal = perturbNormalFromDisplacement(input.position.xyz,
|
||||
input.normal,
|
||||
input.patchCoord,
|
||||
config.mipmapBias,
|
||||
mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
config.displacementScale);
|
||||
displacementScale);
|
||||
#elif NORMAL_BIQUADRATIC || NORMAL_BIQUADRATIC_WG
|
||||
float4 du, dv;
|
||||
float4 disp = PtexMipmapLookupQuadratic(du, dv, input.patchCoord,
|
||||
config.mipmapBias,
|
||||
mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing);
|
||||
|
||||
@ -655,15 +675,15 @@ fragment float4 fragment_main(
|
||||
textureImage_Packing);
|
||||
#elif COLOR_PATCHTYPE
|
||||
float4 texColor = lighting(float4(input.patchColor), input.position.xyz, normal, 0, lightSource);
|
||||
outColor = texColor;
|
||||
outColor = max(texColor, shade);
|
||||
return outColor;
|
||||
#elif COLOR_PATCHCOORD
|
||||
float4 texColor = lighting(input.patchCoord, input.position.xyz, normal, 0, lightSource);
|
||||
outColor = texColor;
|
||||
outColor = max(texColor, shade);
|
||||
return outColor;
|
||||
#elif COLOR_NORMAL
|
||||
float4 texColor = float4(normal.x, normal.y, normal.z, 1);
|
||||
outColor = texColor;
|
||||
outColor = max(texColor, shade);
|
||||
return outColor;
|
||||
#else // COLOR_NONE
|
||||
float4 texColor = float4(0.5, 0.5, 0.5, 1);
|
||||
@ -672,7 +692,7 @@ fragment float4 fragment_main(
|
||||
// ------------ occlusion ---------------
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
float occ = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
|
||||
float occ = PtexMipmapLookup(input.patchCoord, mipmapBias,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing).x;
|
||||
#else
|
||||
@ -682,7 +702,7 @@ fragment float4 fragment_main(
|
||||
// ------------ specular ---------------
|
||||
|
||||
#if USE_PTEX_SPECULAR
|
||||
float specular = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
|
||||
float specular = PtexMipmapLookup(input.patchCoord, mipmapBias,
|
||||
textureSpecular_Data,
|
||||
textureSpecular_Packing).x;
|
||||
#else
|
||||
|
@ -87,12 +87,17 @@ enum {
|
||||
|
||||
-(void)keyDown:(NSEvent *)event {
|
||||
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
|
||||
if(key == '=') {
|
||||
if (hud.KeyDown(key)) {
|
||||
return;
|
||||
} else if(key == '=') {
|
||||
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16);
|
||||
} else if (key == '-') {
|
||||
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0);
|
||||
} else if(!hud.KeyDown(key))
|
||||
} else if (key == 'f') {
|
||||
[_controller.osdRenderer fitFrame];
|
||||
} else {
|
||||
[super keyDown:event];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)scrollWheel:(NSEvent *)event {
|
||||
@ -300,8 +305,8 @@ enum {
|
||||
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
|
||||
10, y, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Frustum Patch Culling (F)", _osdRenderer.usePatchClipCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'f');
|
||||
hud.AddCheckBox("Frustum Patch Culling (P)", _osdRenderer.usePatchClipCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'p');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Backface Culling (B)", _osdRenderer.usePatchBackfaceCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_BACK_CULL, 'b');
|
||||
@ -392,7 +397,7 @@ enum {
|
||||
hud.AddPullDownButton(endcap_pulldown, "Gregory",
|
||||
kEndCapGregoryBasis,
|
||||
_osdRenderer.endCapMode == kEndCapGregoryBasis);
|
||||
if (true || _osdRenderer.legacyGregoryEnabled) {
|
||||
if (_osdRenderer.legacyGregoryEnabled) {
|
||||
hud.AddPullDownButton(endcap_pulldown, "LegacyGregory",
|
||||
kEndCapLegacyGregory,
|
||||
_osdRenderer.endCapMode == kEndCapLegacyGregory);
|
||||
@ -402,7 +407,7 @@ enum {
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
char level[16];
|
||||
sprintf(level, "Lv. %d", i);
|
||||
hud.AddRadioButton(3, level, i==2, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
||||
hud.AddRadioButton(3, level, i==_osdRenderer.refinementLevel, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
||||
}
|
||||
|
||||
int shapes_pulldown = hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n');
|
||||
|
@ -98,7 +98,7 @@
|
||||
_osdRenderer.displayControlMeshVertices = _controlMeshSwitch.isOn;
|
||||
_osdRenderer.displayControlMeshEdges = _controlMeshSwitch.isOn;
|
||||
_osdRenderer.usePatchClipCulling = _patchClipCullingSwitch.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useFractionalTessellation;
|
||||
_osdRenderer.useAdaptive = true;
|
||||
_osdRenderer.freeze = true;
|
||||
_osdRenderer.animateVertices = false;
|
||||
@ -210,7 +210,7 @@
|
||||
_osdRenderer.displayControlMeshVertices = sender.isOn;
|
||||
} else if(sender == _screenspaceTessellationSwitch) {
|
||||
_osdRenderer.useScreenspaceTessellation = sender.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useFractionalTessellation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
|
@ -30,8 +30,8 @@
|
||||
typedef enum {
|
||||
kEndCapBilinearBasis = 0,
|
||||
kEndCapBSplineBasis,
|
||||
kEndCapLegacyGregory,
|
||||
kEndCapGregoryBasis,
|
||||
kEndCapLegacyGregory,
|
||||
} EndCap;
|
||||
|
||||
typedef enum {
|
||||
@ -86,6 +86,8 @@ typedef struct {
|
||||
|
||||
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
-(void)fitFrame;
|
||||
|
||||
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
|
||||
|
||||
@property (nonatomic) unsigned refinementLevel;
|
||||
@ -109,6 +111,7 @@ typedef struct {
|
||||
@property (nonatomic) bool useStageIn;
|
||||
@property (nonatomic) bool usePrimitiveBackfaceCulling;
|
||||
@property (nonatomic) bool useAdaptive;
|
||||
@property (nonatomic) bool yup;
|
||||
@property (nonatomic) bool freeze;
|
||||
@property (nonatomic) bool animateVertices;
|
||||
@property (nonatomic) bool displayControlMeshEdges;
|
||||
|
@ -47,11 +47,13 @@
|
||||
#import <opensubdiv/osd/mtlComputeEvaluator.h>
|
||||
#import <opensubdiv/osd/mtlPatchShaderSource.h>
|
||||
|
||||
#import "../common/simple_math.h"
|
||||
#import "../../regression/common/far_utils.h"
|
||||
#import "init_shapes.h"
|
||||
#import "../common/argOptions.h"
|
||||
#import "../common/mtlUtils.h"
|
||||
#import "../common/mtlControlMeshDisplay.h"
|
||||
#import "../common/simple_math.h"
|
||||
#import "../common/viewerArgsUtils.h"
|
||||
#import "init_shapes.h"
|
||||
|
||||
#define VERTEX_BUFFER_INDEX 0
|
||||
#define PATCH_INDICES_BUFFER_INDEX 1
|
||||
@ -150,8 +152,9 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
|
||||
PerFrameBuffer<unsigned> _patchIndexBuffers[DISPATCHSLOTS];
|
||||
|
||||
unsigned _tessFactorOffsets[DISPATCHSLOTS];
|
||||
unsigned _tessFactorsOffsets[DISPATCHSLOTS];
|
||||
unsigned _perPatchVertexOffsets[DISPATCHSLOTS];
|
||||
unsigned _perPatchTessFactorsOffsets[DISPATCHSLOTS];
|
||||
|
||||
unsigned _threadgroupSizes[DISPATCHSLOTS];
|
||||
id<MTLComputePipelineState> _computePipelines[DISPATCHSLOTS];
|
||||
@ -187,6 +190,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
bool _needsRebuild;
|
||||
NSString* _osdShaderSource;
|
||||
simd::float3 _meshCenter;
|
||||
float _meshSize;
|
||||
NSMutableArray<NSString*>* _loadedModels;
|
||||
int _patchCounts[DISPATCHSLOTS];
|
||||
}
|
||||
@ -300,26 +304,62 @@ struct PipelineConfig {
|
||||
return config;
|
||||
}
|
||||
|
||||
-(void)_processArgs {
|
||||
|
||||
NSEnumerator *argsArray =
|
||||
[[[NSProcessInfo processInfo] arguments] objectEnumerator];
|
||||
|
||||
std::vector<char *> argsVector;
|
||||
for (id arg in argsArray) {
|
||||
argsVector.push_back((char *)[arg UTF8String]);
|
||||
}
|
||||
|
||||
ArgOptions args;
|
||||
|
||||
args.Parse(argsVector.size(), argsVector.data());
|
||||
|
||||
// Parse remaining args
|
||||
const std::vector<const char *> &rargs = args.GetRemainingArgs();
|
||||
for (size_t i = 0; i < rargs.size(); ++i) {
|
||||
|
||||
if (!strcmp(rargs[i], "-lg")) {
|
||||
self.legacyGregoryEnabled = true;
|
||||
} else {
|
||||
args.PrintUnrecognizedArgWarning(rargs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
self.yup = args.GetYUp();
|
||||
self.useAdaptive = args.GetAdaptive();
|
||||
self.refinementLevel = args.GetLevel();
|
||||
|
||||
ViewerArgsUtils::PopulateShapes(args, &g_defaultShapes);
|
||||
}
|
||||
|
||||
-(instancetype)initWithDelegate:(id<OSDRendererDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.useSmoothCornerPatch = false;
|
||||
self.useSmoothCornerPatch = true;
|
||||
self.useSingleCreasePatch = true;
|
||||
self.useInfinitelySharpPatch = false;
|
||||
self.useStageIn = !TARGET_OS_EMBEDDED;
|
||||
self.endCapMode = kEndCapBSplineBasis;
|
||||
self.useScreenspaceTessellation = true;
|
||||
self.useInfinitelySharpPatch = true;
|
||||
self.useStageIn = true;
|
||||
self.endCapMode = kEndCapGregoryBasis;
|
||||
self.useScreenspaceTessellation = false;
|
||||
self.useFractionalTessellation = false;
|
||||
self.usePatchClipCulling = false;
|
||||
self.usePatchIndexBuffer = false;
|
||||
self.usePatchBackfaceCulling = false;
|
||||
self.usePrimitiveBackfaceCulling = false;
|
||||
self.useAdaptive = true;
|
||||
self.yup = false;
|
||||
self.kernelType = kMetal;
|
||||
self.refinementLevel = 2;
|
||||
self.tessellationLevel = 1;
|
||||
self.shadingMode = kShadingPatchType;
|
||||
self.displayStyle = kDisplayStyleWireOnShaded;
|
||||
self.legacyGregoryEnabled = true;
|
||||
self.legacyGregoryEnabled = false;
|
||||
|
||||
[self _processArgs];
|
||||
|
||||
_frameCount = 0;
|
||||
_animationFrames = 0;
|
||||
@ -409,6 +449,10 @@ struct PipelineConfig {
|
||||
return renderEncoder;
|
||||
}
|
||||
|
||||
-(void)fitFrame {
|
||||
_cameraData.dollyDistance = _meshSize;
|
||||
}
|
||||
|
||||
-(void)_renderMesh:(id<MTLRenderCommandEncoder>)renderCommandEncoder {
|
||||
|
||||
auto patchVertexBuffer = _mesh->BindVertexBuffer();
|
||||
@ -476,7 +520,8 @@ struct PipelineConfig {
|
||||
if (pipelineConfig.useTessellation) {
|
||||
[renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
|
||||
|
||||
[renderCommandEncoder setTessellationFactorBuffer:_tessFactorsBuffer offset:_tessFactorOffsets[patchType] instanceStride:0];
|
||||
[renderCommandEncoder setTessellationFactorBuffer:_tessFactorsBuffer offset:_tessFactorsOffsets[patchType] instanceStride:0];
|
||||
[renderCommandEncoder setVertexBufferOffset:_perPatchTessFactorsOffsets[patchType] atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX];
|
||||
|
||||
if (!pipelineConfig.drawIndexed) {
|
||||
[renderCommandEncoder setVertexBufferOffset:_perPatchVertexOffsets[patchType] atIndex:OSD_PERPATCHVERTEX_BUFFER_INDEX];
|
||||
@ -619,20 +664,24 @@ struct PipelineConfig {
|
||||
[computeCommandEncoder setBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
|
||||
|
||||
[computeCommandEncoder setBuffer:_perPatchTessFactorsBuffer offset:0 atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX];
|
||||
|
||||
for (auto& patch : _mesh->GetPatchTable()->GetPatchArrays())
|
||||
{
|
||||
auto patchType = patch.desc.GetType();
|
||||
PipelineConfig pipelineConfig = [self _lookupPipelineConfig:patchType useSingleCreasePatch:_useSingleCreasePatch];
|
||||
|
||||
// Don't compute tess factors when not using tessellation
|
||||
if (!pipelineConfig.useTessellation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[computeCommandEncoder setComputePipelineState:_computePipelines[patchType]];
|
||||
|
||||
[computeCommandEncoder setBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:CONTROL_INDICES_BUFFER_INDEX];
|
||||
|
||||
if (pipelineConfig.useTessellation) {
|
||||
[computeCommandEncoder setBuffer:_tessFactorsBuffer offset:_tessFactorOffsets[patchType] atIndex:PATCH_TESSFACTORS_INDEX];
|
||||
[computeCommandEncoder setBuffer:_tessFactorsBuffer offset:_tessFactorsOffsets[patchType] atIndex:PATCH_TESSFACTORS_INDEX];
|
||||
[computeCommandEncoder setBuffer:_perPatchTessFactorsBuffer offset:_perPatchTessFactorsOffsets[patchType] atIndex:OSD_PERPATCHTESSFACTORS_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:_perPatchVertexBuffer offset:_perPatchVertexOffsets[patchType] atIndex:OSD_PERPATCHVERTEX_BUFFER_INDEX];
|
||||
}
|
||||
if (pipelineConfig.useLegacyBuffers) {
|
||||
@ -668,7 +717,6 @@ struct PipelineConfig {
|
||||
|
||||
auto shapeDesc = &g_defaultShapes[[_loadedModels indexOfObject:_currentModel]];
|
||||
_shape.reset(Shape::parseObj(shapeDesc->data.c_str(), shapeDesc->scheme));
|
||||
const auto scheme = shapeDesc->scheme;
|
||||
|
||||
// create Far mesh (topology)
|
||||
Sdc::SchemeType sdctype = GetSdcType(*_shape);
|
||||
@ -746,7 +794,6 @@ struct PipelineConfig {
|
||||
}
|
||||
|
||||
_vertexData.resize(refBaseLevel.GetNumVertices() * numElements);
|
||||
_meshCenter = simd::float3{0,0,0};
|
||||
|
||||
for(int i = 0; i < refBaseLevel.GetNumVertices(); ++i)
|
||||
{
|
||||
@ -755,14 +802,24 @@ struct PipelineConfig {
|
||||
_vertexData[i * numElements + 2] = _shape->verts[i * 3 + 2];
|
||||
}
|
||||
|
||||
for(auto vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); ++vertexIdx)
|
||||
{
|
||||
_meshCenter[0] += _vertexData[vertexIdx * numElements + 0];
|
||||
_meshCenter[1] += _vertexData[vertexIdx * numElements + 1];
|
||||
_meshCenter[2] += _vertexData[vertexIdx * numElements + 2];
|
||||
// compute model bounding
|
||||
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
float max[3] = {-FLT_MAX,-FLT_MAX,-FLT_MAX};
|
||||
for (int i = 0; i < refBaseLevel.GetNumVertices(); ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
float v = _vertexData[i*numElements+j];
|
||||
min[j] = std::min(min[j], v);
|
||||
max[j] = std::max(max[j], v);
|
||||
}
|
||||
}
|
||||
|
||||
_meshCenter /= (_shape->verts.size() / 3);
|
||||
_meshSize = 0.0f;
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
_meshCenter[j] = (min[j] + max[j]) * 0.5f;
|
||||
_meshSize += (max[j]-min[j])*(max[j]-min[j]);
|
||||
}
|
||||
_meshSize = sqrt(_meshSize);
|
||||
|
||||
_mesh->UpdateVertexBuffer(_vertexData.data(), 0, refBaseLevel.GetNumVertices());
|
||||
_mesh->Refine();
|
||||
_mesh->Synchronize();
|
||||
@ -879,7 +936,8 @@ struct PipelineConfig {
|
||||
|
||||
-(void)_rebuildBuffers {
|
||||
auto totalPatches = 0;
|
||||
auto totalPatchDataSize = 0;
|
||||
auto totalPerPatchVertexSize = 0;
|
||||
auto totalPerPatchTessFactorsSize = 0;
|
||||
auto totalTessFactorsSize = 0;
|
||||
|
||||
if (_usePatchIndexBuffer)
|
||||
@ -906,9 +964,11 @@ struct PipelineConfig {
|
||||
{
|
||||
_patchIndexBuffers[patchType].alloc(_context.device, patch.GetNumPatches(), @"patch indices", MTLResourceStorageModePrivate);
|
||||
}
|
||||
_perPatchVertexOffsets[patchType] = totalPatchDataSize;
|
||||
_tessFactorOffsets[patchType] = totalTessFactorsSize;
|
||||
totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * pipelineConfig.numControlPointsPerPatchToDraw;
|
||||
_perPatchTessFactorsOffsets[patchType] = totalPerPatchTessFactorsSize;
|
||||
_perPatchVertexOffsets[patchType] = totalPerPatchVertexSize;
|
||||
_tessFactorsOffsets[patchType] = totalTessFactorsSize;
|
||||
totalPerPatchTessFactorsSize += 2 * 4 * sizeof(float) * patch.GetNumPatches();
|
||||
totalPerPatchVertexSize += elementFloats * sizeof(float) * patch.GetNumPatches() * pipelineConfig.numControlPointsPerPatchToDraw;
|
||||
totalTessFactorsSize += patch.GetNumPatches() * (pipelineConfig.useTriangleTessellation
|
||||
? sizeof(MTLTriangleTessellationFactorsHalf)
|
||||
: sizeof(MTLQuadTessellationFactorsHalf));
|
||||
@ -918,8 +978,8 @@ struct PipelineConfig {
|
||||
}
|
||||
|
||||
_tessFactorsBuffer.alloc(_context.device, totalTessFactorsSize, @"tessellation factors buffer", MTLResourceStorageModePrivate);
|
||||
_perPatchVertexBuffer.alloc(_context.device, totalPatchDataSize, @"per patch data", MTLResourceStorageModePrivate);
|
||||
_perPatchTessFactorsBuffer.alloc(_context.device, 2 * 4 * sizeof(float) * totalPatches, @"hs constant data", MTLResourceStorageModePrivate);
|
||||
_perPatchVertexBuffer.alloc(_context.device, totalPerPatchVertexSize, @"per patch data", MTLResourceStorageModePrivate);
|
||||
_perPatchTessFactorsBuffer.alloc(_context.device, totalPerPatchTessFactorsSize, @"per patch tess factors", MTLResourceStorageModePrivate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1178,6 +1238,25 @@ struct PipelineConfig {
|
||||
vertexDesc.attributes[i].format = MTLVertexFormatFloat3;
|
||||
vertexDesc.attributes[i].offset = i * sizeof(float) * 3;
|
||||
}
|
||||
|
||||
if(_useScreenspaceTessellation)
|
||||
{
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 4 * 2;
|
||||
|
||||
// PatchInput :: float4 tessOuterLo [[attribute(5)]];
|
||||
// OsdPerPatchTessFactors :: float4 tessOuterLo;
|
||||
vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
|
||||
vertexDesc.attributes[5].format = MTLVertexFormatFloat4;
|
||||
vertexDesc.attributes[5].offset = 0;
|
||||
|
||||
// PatchInput :: float4 tessOuterHi [[attribute(6)]];
|
||||
// OsdPerPatchTessFactors :: float4 tessOuterHi;
|
||||
vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
|
||||
vertexDesc.attributes[6].format = MTLVertexFormatFloat4;
|
||||
vertexDesc.attributes[6].offset = sizeof(float) * 4;
|
||||
}
|
||||
break;
|
||||
case Far::PatchDescriptor::QUADS:
|
||||
//Quads cannot use stage in, due to the need for re-indexing.
|
||||
@ -1277,14 +1356,15 @@ struct PipelineConfig {
|
||||
translate(pData->ModelViewMatrix, 0, 0, -_cameraData.dollyDistance);
|
||||
rotate(pData->ModelViewMatrix, _cameraData.rotationY, 1, 0, 0);
|
||||
rotate(pData->ModelViewMatrix, _cameraData.rotationX, 0, 1, 0);
|
||||
rotate(pData->ModelViewMatrix, -90, 1, 0, 0); // z-up model
|
||||
if (!_yup) {
|
||||
rotate(pData->ModelViewMatrix, -90, 1, 0, 0);
|
||||
}
|
||||
translate(pData->ModelViewMatrix, -_meshCenter[0], -_meshCenter[1], -_meshCenter[2]);
|
||||
inverseMatrix(pData->ModelViewInverseMatrix, pData->ModelViewMatrix);
|
||||
|
||||
identity(pData->ProjectionMatrix);
|
||||
perspective(pData->ProjectionMatrix, 45.0, _cameraData.aspectRatio, 0.01f, 500.0);
|
||||
multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix);
|
||||
|
||||
}
|
||||
|
||||
-(void)_initializeBuffers {
|
||||
@ -1293,9 +1373,9 @@ struct PipelineConfig {
|
||||
}
|
||||
|
||||
-(void)_initializeCamera {
|
||||
_cameraData.dollyDistance = 4;
|
||||
_cameraData.rotationY = 0;
|
||||
_cameraData.rotationX = 0;
|
||||
_cameraData.dollyDistance = 5;
|
||||
_cameraData.aspectRatio = 1;
|
||||
}
|
||||
|
||||
|
@ -833,7 +833,12 @@ PatchBuilder::GetIrregularPatchCornerSpans(int levelIndex, Index faceIndex,
|
||||
|
||||
// Sharpen the span if a corner or subject to inf-sharp features:
|
||||
if (vTag._corner) {
|
||||
cornerSpans[i]._sharp = true;
|
||||
// Corners tagged in FVar space need additional qualification:
|
||||
if (isFVarMisMatch) {
|
||||
cornerSpans[i]._sharp = (cornerSpans[i]._numFaces == 1) || isNonManifold;
|
||||
} else {
|
||||
cornerSpans[i]._sharp = true;
|
||||
}
|
||||
} else if (isNonManifold) {
|
||||
cornerSpans[i]._sharp = vTag._infSharp;
|
||||
} else if (testInfSharpFeatures) {
|
||||
@ -1592,8 +1597,13 @@ SourcePatch::GetCornerRingPoints(int corner, int ringPoints[]) const {
|
||||
}
|
||||
} else {
|
||||
if (_corners[corner]._sharesWithNext) {
|
||||
ringPoints[ringSize++] = _corners[cNext]._val2Interior
|
||||
? cPrev : _localRingOffsets[cNext];
|
||||
if (_corners[cNext]._val2Interior) {
|
||||
ringPoints[ringSize++] = cPrev;
|
||||
} else if (_localRingSizes[cNext] == 0) {
|
||||
ringPoints[ringSize++] = _localRingOffsets[cPrev];
|
||||
} else {
|
||||
ringPoints[ringSize++] = _localRingOffsets[cNext];
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(ringSize == _ringSizes[corner]);
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
/// face indices and not the base face indices (see Far::PtexIndices for more
|
||||
/// details).
|
||||
///
|
||||
/// @param patchFaceId The index of the face
|
||||
/// @param patchFaceId The index of the patch (Ptex) face
|
||||
///
|
||||
/// @param u Local u parameter
|
||||
///
|
||||
|
@ -168,7 +168,7 @@ public:
|
||||
StencilTableReal<REAL> const *GetLocalPointStencilTable() const;
|
||||
|
||||
/// \brief Tests if the precision of the stencil table to compute local point
|
||||
/// vertex values matches the given floating point type <REAL>.
|
||||
/// vertex values matches the given floating point type \<REAL\>.
|
||||
template <typename REAL> bool LocalPointStencilPrecisionMatchesType() const;
|
||||
|
||||
/// \brief Updates local point vertex values.
|
||||
@ -198,7 +198,7 @@ public:
|
||||
StencilTableReal<REAL> const *GetLocalPointVaryingStencilTable() const;
|
||||
|
||||
/// \brief Tests if the precision of the stencil table to compute local point
|
||||
/// varying values matches the given floating point type <REAL>.
|
||||
/// varying values matches the given floating point type \<REAL\>.
|
||||
template <typename REAL> bool LocalPointVaryingStencilPrecisionMatchesType() const;
|
||||
|
||||
/// \brief Updates local point varying values.
|
||||
@ -228,7 +228,7 @@ public:
|
||||
StencilTableReal<REAL> const * GetLocalPointFaceVaryingStencilTable(int channel = 0) const;
|
||||
|
||||
/// \brief Tests if the precision of the stencil table to compute local point
|
||||
/// face-varying values matches the given floating point type <REAL>.
|
||||
/// face-varying values matches the given floating point type \<REAL\>.
|
||||
template <typename REAL> bool LocalPointFaceVaryingStencilPrecisionMatchesType() const;
|
||||
|
||||
/// \brief Updates local point face-varying values.
|
||||
|
@ -44,12 +44,20 @@ public:
|
||||
///
|
||||
struct Options {
|
||||
|
||||
/// \brief Choice for approximating irregular patches (end-caps)
|
||||
///
|
||||
/// This enum specifies how irregular patches (end-caps) are approximated.
|
||||
/// A basis is chosen, rather than a specific patch type, and has a
|
||||
/// corresponding patch type for each subdivision scheme, i.e. a quad and
|
||||
/// triangular patch type exists for each basis. These choices provide a
|
||||
/// trade-off between surface quality and performance.
|
||||
///
|
||||
enum EndCapType {
|
||||
ENDCAP_NONE = 0, ///< no endcap
|
||||
ENDCAP_BILINEAR_BASIS, ///< use bilinear quads (4 cp) as end-caps
|
||||
ENDCAP_BSPLINE_BASIS, ///< use BSpline basis patches (16 cp) as end-caps
|
||||
ENDCAP_GREGORY_BASIS, ///< use Gregory basis patches (20 cp) as end-caps
|
||||
ENDCAP_LEGACY_GREGORY ///< use legacy (2.x) Gregory patches (4 cp + valence table) as end-caps
|
||||
ENDCAP_NONE = 0, ///< unspecified
|
||||
ENDCAP_BILINEAR_BASIS, ///< use linear patches (simple quads or tris)
|
||||
ENDCAP_BSPLINE_BASIS, ///< use BSpline-like patches (same patch type as regular)
|
||||
ENDCAP_GREGORY_BASIS, ///< use Gregory patches (highest quality, recommended default)
|
||||
ENDCAP_LEGACY_GREGORY ///< legacy option for 2.x style Gregory patches (Catmark only)
|
||||
};
|
||||
|
||||
Options(unsigned int maxIsolation=10) :
|
||||
@ -73,10 +81,10 @@ public:
|
||||
fvarChannelIndices(0)
|
||||
{ }
|
||||
|
||||
/// \brief Get endcap patch type
|
||||
/// \brief Get endcap basis type
|
||||
EndCapType GetEndCapType() const { return (EndCapType)endCapType; }
|
||||
|
||||
/// \brief Set endcap patch type
|
||||
/// \brief Set endcap basis type
|
||||
void SetEndCapType(EndCapType e) { endCapType = e; }
|
||||
|
||||
/// \brief Set precision of vertex patches
|
||||
@ -175,7 +183,7 @@ public:
|
||||
// It is no longer used internally and is being kept here to respect preservation
|
||||
// of the public interface, but it will be deprecated at the earliest opportunity.
|
||||
//
|
||||
/// \brief Obsolete internal struct accidentally exposed for public use -- due to
|
||||
/// \brief Obsolete internal struct not intended for public use -- due to
|
||||
/// be deprecated.
|
||||
//
|
||||
struct PatchFaceTag {
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
/// @param localPointStencilTable
|
||||
/// StencilTable for the change of basis patch points.
|
||||
///
|
||||
/// @param factorize If factorize set to true, endcap stencils will be
|
||||
/// @param factorize If factorize is set to true, endcap stencils will be
|
||||
/// factorized with supporting vertices from baseStencil
|
||||
/// table so that the endcap points can be computed
|
||||
/// directly from control vertices.
|
||||
@ -140,7 +140,7 @@ public:
|
||||
/// @param localPointStencilTable
|
||||
/// StencilTable for the change of basis patch points.
|
||||
///
|
||||
/// @param factorize If factorize set to true, endcap stencils will be
|
||||
/// @param factorize If factorize is set to true, endcap stencils will be
|
||||
/// factorized with supporting vertices from baseStencil
|
||||
/// table so that the endcap points can be computed
|
||||
/// directly from control vertices.
|
||||
@ -166,7 +166,7 @@ public:
|
||||
///
|
||||
/// @param channel face-varying channel
|
||||
///
|
||||
/// @param factorize If factorize sets to true, endcap stencils will be
|
||||
/// @param factorize If factorize is set to true, endcap stencils will be
|
||||
/// factorized with supporting vertices from baseStencil
|
||||
/// table so that the endcap points can be computed
|
||||
/// directly from control vertices.
|
||||
|
@ -255,16 +255,16 @@ kernel void eval_patches(
|
||||
as_type<float>(patchCoords[current*5+3]),
|
||||
as_type<float>(patchCoords[current*5+4]));
|
||||
|
||||
OsdPatchArray patchArray = OsdPatchArrayInit(patchArrays[current*6+0],
|
||||
patchArrays[current*6+1],
|
||||
patchArrays[current*6+2],
|
||||
patchArrays[current*6+3],
|
||||
patchArrays[current*6+4],
|
||||
patchArrays[current*6+5]);
|
||||
OsdPatchArray patchArray = OsdPatchArrayInit(patchArrays[patchCoord.arrayIndex*6+0],
|
||||
patchArrays[patchCoord.arrayIndex*6+1],
|
||||
patchArrays[patchCoord.arrayIndex*6+2],
|
||||
patchArrays[patchCoord.arrayIndex*6+3],
|
||||
patchArrays[patchCoord.arrayIndex*6+4],
|
||||
patchArrays[patchCoord.arrayIndex*6+5]);
|
||||
|
||||
OsdPatchParam patchParam = OsdPatchParamInit(patchParams[current*3+0],
|
||||
patchParams[current*3+1],
|
||||
as_type<float>(patchParams[current*3+2]));
|
||||
OsdPatchParam patchParam = OsdPatchParamInit(patchParams[patchCoord.patchIndex*3+0],
|
||||
patchParams[patchCoord.patchIndex*3+1],
|
||||
as_type<float>(patchParams[patchCoord.patchIndex*3+2]));
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(patchParam)
|
||||
? patchArray.regDesc : patchArray.desc;
|
||||
|
@ -34,8 +34,8 @@
|
||||
#include <opensubdiv/far/primvarRefiner.h>
|
||||
#include <opensubdiv/far/stencilTableFactory.h>
|
||||
#include <opensubdiv/far/patchTableFactory.h>
|
||||
|
||||
#include "../../regression/common/far_utils.h"
|
||||
// XXX: revisit the directory structure for examples/tests
|
||||
#include "../../examples/common/stopwatch.h"
|
||||
|
||||
#include "init_shapes.h"
|
||||
@ -44,8 +44,33 @@
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
struct Result {
|
||||
struct TestOptions {
|
||||
TestOptions() :
|
||||
refineLevel(2),
|
||||
refineAdaptive(true),
|
||||
createPatches(true),
|
||||
createStencils(true),
|
||||
endCapType(Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS) { }
|
||||
|
||||
int refineLevel;
|
||||
bool refineAdaptive;
|
||||
bool createPatches;
|
||||
bool createStencils;
|
||||
|
||||
Far::PatchTableFactory::Options::EndCapType endCapType;
|
||||
};
|
||||
|
||||
struct TestResult {
|
||||
TestResult() :
|
||||
level(-1),
|
||||
timeTotal(0),
|
||||
timeRefine(0),
|
||||
timePatchFactory(0),
|
||||
timeStencilFactory(0),
|
||||
timeAppendStencil(0) { }
|
||||
|
||||
std::string name;
|
||||
int level;
|
||||
double timeTotal;
|
||||
double timeRefine;
|
||||
double timePatchFactory;
|
||||
@ -54,74 +79,76 @@ struct Result {
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
static Result
|
||||
doPerf(std::string const & name,
|
||||
Shape const * shape,
|
||||
int level,
|
||||
bool adaptive,
|
||||
Far::PatchTableFactory::Options::EndCapType endCapType)
|
||||
{
|
||||
static TestResult
|
||||
RunPerfTest(Shape const & shape, TestOptions const & options) {
|
||||
|
||||
typedef Far::StencilTableReal<REAL> FarStencilTable;
|
||||
typedef Far::StencilTableFactoryReal<REAL> FarStencilTableFactory;
|
||||
|
||||
Sdc::SchemeType sdcType = GetSdcType(*shape);
|
||||
Sdc::Options sdcOptions = GetSdcOptions(*shape);
|
||||
Sdc::SchemeType sdcType = GetSdcType(shape);
|
||||
Sdc::Options sdcOptions = GetSdcOptions(shape);
|
||||
|
||||
Result result;
|
||||
result.name = name;
|
||||
TestResult result;
|
||||
result.level = options.refineLevel;
|
||||
|
||||
Stopwatch s;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Configure the patch table factory options
|
||||
Far::PatchTableFactory::Options poptions(level);
|
||||
poptions.SetEndCapType(endCapType);
|
||||
Far::PatchTableFactory::Options poptions(options.refineLevel);
|
||||
poptions.SetEndCapType(options.endCapType);
|
||||
poptions.SetPatchPrecision<REAL>();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Instantiate a FarTopologyRefiner from the descriptor and refine
|
||||
s.Start();
|
||||
Far::TopologyRefiner * refiner = Far::TopologyRefinerFactory<Shape>::Create(
|
||||
*shape, Far::TopologyRefinerFactory<Shape>::Options(sdcType, sdcOptions));
|
||||
{
|
||||
if (adaptive) {
|
||||
Far::TopologyRefiner::AdaptiveOptions options =
|
||||
poptions.GetRefineAdaptiveOptions();
|
||||
refiner->RefineAdaptive(options);
|
||||
} else {
|
||||
Far::TopologyRefiner::UniformOptions options(level);
|
||||
refiner->RefineUniform(options);
|
||||
}
|
||||
shape, Far::TopologyRefinerFactory<Shape>::Options(sdcType, sdcOptions));
|
||||
assert(refiner);
|
||||
|
||||
s.Start();
|
||||
if (options.refineAdaptive) {
|
||||
Far::TopologyRefiner::AdaptiveOptions rOptions =
|
||||
poptions.GetRefineAdaptiveOptions();
|
||||
refiner->RefineAdaptive(rOptions);
|
||||
} else {
|
||||
Far::TopologyRefiner::UniformOptions rOptions(options.refineLevel);
|
||||
refiner->RefineUniform(rOptions);
|
||||
}
|
||||
s.Stop();
|
||||
result.timeRefine = s.GetElapsed();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Create patch table
|
||||
s.Start();
|
||||
Far::PatchTable const * patchTable = NULL;
|
||||
{
|
||||
if (options.createPatches) {
|
||||
s.Start();
|
||||
patchTable = Far::PatchTableFactory::Create(*refiner, poptions);
|
||||
s.Stop();
|
||||
result.timePatchFactory = s.GetElapsed();
|
||||
} else {
|
||||
result.timePatchFactory = 0;
|
||||
}
|
||||
s.Stop();
|
||||
result.timePatchFactory = s.GetElapsed();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Create stencil table
|
||||
s.Start();
|
||||
FarStencilTable const * vertexStencils = NULL;
|
||||
{
|
||||
if (options.createStencils) {
|
||||
s.Start();
|
||||
|
||||
typename FarStencilTableFactory::Options options;
|
||||
vertexStencils = FarStencilTableFactory::Create(*refiner, options);
|
||||
|
||||
s.Stop();
|
||||
result.timeStencilFactory = s.GetElapsed();
|
||||
} else {
|
||||
result.timeStencilFactory = 0;
|
||||
}
|
||||
s.Stop();
|
||||
result.timeStencilFactory = s.GetElapsed();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// append local points to stencils
|
||||
s.Start();
|
||||
{
|
||||
if (options.createPatches && options.createStencils) {
|
||||
s.Start();
|
||||
|
||||
if (FarStencilTable const *vertexStencilsWithLocalPoints =
|
||||
FarStencilTableFactory::AppendLocalPointStencilTable(
|
||||
*refiner, vertexStencils,
|
||||
@ -129,25 +156,128 @@ doPerf(std::string const & name,
|
||||
delete vertexStencils;
|
||||
vertexStencils = vertexStencilsWithLocalPoints;
|
||||
}
|
||||
|
||||
s.Stop();
|
||||
result.timeAppendStencil = s.GetElapsed();
|
||||
} else {
|
||||
result.timeAppendStencil = 0;
|
||||
}
|
||||
s.Stop();
|
||||
result.timeAppendStencil = s.GetElapsed();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
result.timeTotal = s.GetTotalElapsed();
|
||||
|
||||
delete vertexStencils;
|
||||
delete patchTable;
|
||||
delete refiner;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct PrintOptions {
|
||||
PrintOptions() :
|
||||
csvFormat(false),
|
||||
refineTime(true),
|
||||
patchTime(true),
|
||||
stencilTime(true),
|
||||
appendTime(true),
|
||||
totalTime(true) { }
|
||||
|
||||
bool csvFormat;
|
||||
bool refineTime;
|
||||
bool patchTime;
|
||||
bool stencilTime;
|
||||
bool appendTime;
|
||||
bool totalTime;
|
||||
};
|
||||
|
||||
static void
|
||||
PrintShape(ShapeDesc const & shapeDesc, PrintOptions const & ) {
|
||||
|
||||
static char const * g_schemeNames[3] = { "bilinear", "catmark", "loop" };
|
||||
|
||||
char const * shapeName = shapeDesc.name.c_str();
|
||||
Scheme shapeScheme = shapeDesc.scheme;
|
||||
|
||||
printf("%s (%s):\n", shapeName, g_schemeNames[shapeScheme]);
|
||||
}
|
||||
|
||||
static void
|
||||
PrintResult(TestResult const & result, PrintOptions const & options) {
|
||||
|
||||
// If only printing the total, combine on same line as level:
|
||||
if (!options.refineTime && !options.patchTime &&
|
||||
!options.stencilTime && !options.appendTime) {
|
||||
printf(" level %d: %f\n", result.level, result.timeTotal);
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" level %d:\n", result.level);
|
||||
|
||||
if (options.refineTime) {
|
||||
printf(" TopologyRefiner::Refine %f %5.2f%%\n",
|
||||
result.timeRefine,
|
||||
result.timeRefine/result.timeTotal*100);
|
||||
}
|
||||
if (options.patchTime) {
|
||||
printf(" PatchTableFactory::Create %f %5.2f%%\n",
|
||||
result.timePatchFactory,
|
||||
result.timePatchFactory/result.timeTotal*100);
|
||||
}
|
||||
if (options.stencilTime) {
|
||||
printf(" StencilTableFactory::Create %f %5.2f%%\n",
|
||||
result.timeStencilFactory,
|
||||
result.timeStencilFactory/result.timeTotal*100);
|
||||
}
|
||||
if (options.appendTime) {
|
||||
printf(" StencilTableFactory::Append %f %5.2f%%\n",
|
||||
result.timeAppendStencil,
|
||||
result.timeAppendStencil/result.timeTotal*100);
|
||||
}
|
||||
if (options.totalTime) {
|
||||
printf(" Total %f\n",
|
||||
result.timeTotal);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintHeaderCSV(PrintOptions const & options) {
|
||||
|
||||
// spreadsheet header row
|
||||
printf("shape");
|
||||
printf(",level");
|
||||
if (options.refineTime) printf(",refine");
|
||||
if (options.patchTime) printf(",patch");
|
||||
if (options.stencilTime) printf(",stencilFactory");
|
||||
if (options.appendTime) printf(",stencilAppend");
|
||||
if (options.totalTime) printf(",total");
|
||||
printf("\n");
|
||||
}
|
||||
static void
|
||||
PrintResultCSV(TestResult const & result, PrintOptions const & options) {
|
||||
|
||||
// spreadsheet data row
|
||||
printf("%s", result.name.c_str());
|
||||
printf(",%d", result.level);
|
||||
if (options.refineTime) printf(",%f", result.timeRefine);
|
||||
if (options.patchTime) printf(",%f", result.timePatchFactory);
|
||||
if (options.stencilTime) printf(",%f", result.timeStencilFactory);
|
||||
if (options.appendTime) printf(",%f", result.timeAppendStencil);
|
||||
if (options.totalTime) printf(",%f", result.timeTotal);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static int
|
||||
parseIntArg(char const * argString, int dfltValue = 0) {
|
||||
char *argEndptr;
|
||||
int argValue = strtol(argString, &argEndptr, 10);
|
||||
if (*argEndptr != 0) {
|
||||
printf("Warning: non-integer option parameter '%s' ignored\n",
|
||||
argString);
|
||||
fprintf(stderr,
|
||||
"Warning: non-integer option parameter '%s' ignored\n",
|
||||
argString);
|
||||
argValue = dfltValue;
|
||||
}
|
||||
return argValue;
|
||||
@ -155,30 +285,23 @@ parseIntArg(char const * argString, int dfltValue = 0) {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool adaptive = true;
|
||||
int level = 8;
|
||||
TestOptions testOptions;
|
||||
PrintOptions printOptions;
|
||||
std::vector<std::string> objFiles;
|
||||
Scheme defaultScheme = kCatmark;
|
||||
Far::PatchTableFactory::Options::EndCapType endCapType =
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
|
||||
int minLevel = 1;
|
||||
int maxLevel = 2;
|
||||
bool runDouble = false;
|
||||
bool spreadsheet = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strstr(argv[i], ".obj")) {
|
||||
std::ifstream ifs(argv[i]);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
g_shapes.push_back(
|
||||
ShapeDesc(argv[i], ss.str(), defaultScheme));
|
||||
}
|
||||
objFiles.push_back(std::string(argv[i]));
|
||||
} else if (!strcmp(argv[i], "-a")) {
|
||||
adaptive = true;
|
||||
testOptions.refineAdaptive = true;
|
||||
} else if (!strcmp(argv[i], "-u")) {
|
||||
adaptive = false;
|
||||
testOptions.refineAdaptive = false;
|
||||
} else if (!strcmp(argv[i], "-l")) {
|
||||
if (++i < argc) level = parseIntArg(argv[i], 8);
|
||||
if (++i < argc) maxLevel = parseIntArg(argv[i], maxLevel);
|
||||
} else if (!strcmp(argv[i], "-bilinear")) {
|
||||
defaultScheme = kBilinear;
|
||||
} else if (!strcmp(argv[i], "-catmark")) {
|
||||
@ -188,22 +311,57 @@ int main(int argc, char **argv)
|
||||
} else if (!strcmp(argv[i], "-e")) {
|
||||
char const * type = argv[++i];
|
||||
if (!strcmp(type, "linear")) {
|
||||
endCapType =
|
||||
testOptions.endCapType =
|
||||
Far::PatchTableFactory::Options::ENDCAP_BILINEAR_BASIS;
|
||||
} else if (!strcmp(type, "regular")) {
|
||||
endCapType =
|
||||
testOptions.endCapType =
|
||||
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS;
|
||||
} else if (!strcmp(type, "gregory")) {
|
||||
endCapType =
|
||||
testOptions.endCapType =
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
|
||||
} else {
|
||||
printf("Unknown endcap type %s\n", type);
|
||||
fprintf(stderr, "Error: Unknown endcap type %s\n", type);
|
||||
return 1;
|
||||
}
|
||||
} else if (!strcmp(argv[i], "-double")) {
|
||||
runDouble = true;
|
||||
} else if (!strcmp(argv[i], "-spreadsheet")) {
|
||||
spreadsheet = true;
|
||||
} else if (!strcmp(argv[i], "-nopatches")) {
|
||||
testOptions.createPatches = false;
|
||||
|
||||
printOptions.patchTime = false;
|
||||
printOptions.appendTime = false;
|
||||
} else if (!strcmp(argv[i], "-nostencils")) {
|
||||
testOptions.createStencils = false;
|
||||
|
||||
printOptions.stencilTime = false;
|
||||
printOptions.appendTime = false;
|
||||
} else if (!strcmp(argv[i], "-total")) {
|
||||
printOptions.refineTime = false;
|
||||
printOptions.patchTime = false;
|
||||
printOptions.stencilTime = false;
|
||||
printOptions.appendTime = false;
|
||||
} else if (!strcmp(argv[i], "-csv")) {
|
||||
printOptions.csvFormat = true;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Warning: unrecognized argument '%s' ignored\n", argv[i]);
|
||||
}
|
||||
}
|
||||
assert(minLevel <= maxLevel);
|
||||
|
||||
if (!objFiles.empty()) {
|
||||
for (size_t i = 0; i < objFiles.size(); ++i) {
|
||||
char const * objFile = objFiles[i].c_str();
|
||||
std::ifstream ifs(objFile);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
g_shapes.push_back(ShapeDesc(objFile, ss.str(), defaultScheme));
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Warning: cannot open shape file '%s'\n", objFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,67 +369,38 @@ int main(int argc, char **argv)
|
||||
initShapes();
|
||||
}
|
||||
|
||||
std::vector< std::vector<Result> > resultsByLevel(level+1);
|
||||
|
||||
for (int i = 0; i < (int)g_shapes.size(); ++i) {
|
||||
std::string const & name = g_shapes[i].name;
|
||||
Shape const * shape = Shape::parseObj(g_shapes[i]);
|
||||
|
||||
for (int lv = 1; lv <= level; ++lv) {
|
||||
Result result;
|
||||
if (runDouble) {
|
||||
result = doPerf<double>(name, shape, lv, adaptive, endCapType);
|
||||
} else {
|
||||
result = doPerf<float>(name, shape, lv, adaptive, endCapType);
|
||||
}
|
||||
printf("---- %s, level %d ----\n", result.name.c_str(), lv);
|
||||
printf("TopologyRefiner::Refine %f %5.2f%%\n",
|
||||
result.timeRefine,
|
||||
result.timeRefine/result.timeTotal*100);
|
||||
printf("StencilTableFactory::Create %f %5.2f%%\n",
|
||||
result.timeStencilFactory,
|
||||
result.timeStencilFactory/result.timeTotal*100);
|
||||
printf("PatchTableFactory::Create %f %5.2f%%\n",
|
||||
result.timePatchFactory,
|
||||
result.timePatchFactory/result.timeTotal*100);
|
||||
printf("StencilTableFactory::Append %f %5.2f%%\n",
|
||||
result.timeAppendStencil,
|
||||
result.timeAppendStencil/result.timeTotal*100);
|
||||
printf("Total %f\n",
|
||||
result.timeTotal);
|
||||
if (spreadsheet) {
|
||||
resultsByLevel[lv].push_back(result);
|
||||
}
|
||||
}
|
||||
// For each shape, run tests for all specified levels -- printing the
|
||||
// results in the specified format:
|
||||
//
|
||||
if (printOptions.csvFormat) {
|
||||
PrintHeaderCSV(printOptions);
|
||||
}
|
||||
if (spreadsheet) {
|
||||
for (int lv=1; lv<(int)resultsByLevel.size(); ++lv) {
|
||||
std::vector<Result> const & results = resultsByLevel[lv];
|
||||
if (lv == 1) {
|
||||
// spreadsheet header row
|
||||
printf("level,");
|
||||
for (int s=0; s<(int)results.size(); ++s) {
|
||||
Result const & result = results[s];
|
||||
printf("%s total,", result.name.c_str());
|
||||
printf("%s refine,", result.name.c_str());
|
||||
printf("%s patchFactory,", result.name.c_str());
|
||||
printf("%s stencilFactory,", result.name.c_str());
|
||||
printf("%s stencilAppend,", result.name.c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
// spreadsheet data row
|
||||
printf("%d,", lv);
|
||||
for (int s=0; s<(int)results.size(); ++s) {
|
||||
Result const & result = results[s];
|
||||
printf("%f,", result.timeTotal);
|
||||
printf("%f,", result.timeRefine);
|
||||
printf("%f,", result.timePatchFactory);
|
||||
printf("%f,", result.timeStencilFactory);
|
||||
printf("%f,", result.timeAppendStencil);
|
||||
}
|
||||
printf("\n");
|
||||
for (size_t i = 0; i < g_shapes.size(); ++i) {
|
||||
ShapeDesc const & shapeDesc = g_shapes[i];
|
||||
Shape const * shape = Shape::parseObj(shapeDesc);
|
||||
|
||||
if (!printOptions.csvFormat) {
|
||||
PrintShape(shapeDesc, printOptions);
|
||||
}
|
||||
|
||||
for (int levelIndex = minLevel; levelIndex <= maxLevel; ++levelIndex) {
|
||||
testOptions.refineLevel = levelIndex;
|
||||
|
||||
TestResult result;
|
||||
if (runDouble) {
|
||||
result = RunPerfTest<double>(*shape, testOptions);
|
||||
} else {
|
||||
result = RunPerfTest<float>(*shape, testOptions);
|
||||
}
|
||||
result.name = shapeDesc.name;
|
||||
|
||||
if (printOptions.csvFormat) {
|
||||
PrintResultCSV(result, printOptions);
|
||||
} else {
|
||||
PrintResult(result, printOptions);
|
||||
}
|
||||
}
|
||||
delete shape;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,7 @@
|
||||
#include "loop_pole360.h"
|
||||
#include "loop_saddle_edgecorner.h"
|
||||
#include "loop_saddle_edgeonly.h"
|
||||
#include "loop_tetrahedron.h"
|
||||
#include "loop_toroidal_tet.h"
|
||||
#include "loop_triangle_edgecorner.h"
|
||||
#include "loop_triangle_edgeonly.h"
|
||||
|
@ -46,9 +46,9 @@ static const std::string catmark_xord_boundary =
|
||||
"vt 0.076795 0.850000\n"
|
||||
"vt 0.076795 0.750000\n"
|
||||
"\n"
|
||||
"f 1/1 2/2 3/3 4/4 \n"
|
||||
"f 1/1 4/4 5/5 6/6 \n"
|
||||
"f 1/1 6/6 7/7 8/8 \n"
|
||||
"f 1/1 2/2 3/3 4/4\n"
|
||||
"f 6/6 1/1 4/4 5/5\n"
|
||||
"f 6/6 7/7 8/8 1/1\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 2: top-right\n"
|
||||
@ -76,9 +76,9 @@ static const std::string catmark_xord_boundary =
|
||||
"vt 0.565224 0.750000\n"
|
||||
"\n"
|
||||
"f 9/9 10/10 11/11 12/12\n"
|
||||
"f 9/9 12/12 13/13 14/14\n"
|
||||
"f 9/9 14/14 15/15 16/16\n"
|
||||
"f 9/9 16/16 17/17 18/18\n"
|
||||
"f 14/14 9/9 12/12 13/13\n"
|
||||
"f 15/15 16/16 9/9 14/14\n"
|
||||
"f 16/16 17/17 18/18 9/9\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 3: bottom-left\n"
|
||||
@ -110,9 +110,9 @@ static const std::string catmark_xord_boundary =
|
||||
"vt 0.059789 0.250000\n"
|
||||
"\n"
|
||||
"f 19/19 20/20 21/21 22/22\n"
|
||||
"f 19/19 22/22 23/23 24/24\n"
|
||||
"f 19/19 24/24 25/25 26/26\n"
|
||||
"f 19/19 26/26 27/27 28/28\n"
|
||||
"f 24/24 19/19 22/22 23/23\n"
|
||||
"f 25/25 26/26 19/19 24/24\n"
|
||||
"f 26/26 27/27 28/28 19/19\n"
|
||||
"f 19/19 28/28 29/29 30/30\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
@ -149,9 +149,9 @@ static const std::string catmark_xord_boundary =
|
||||
"vt 0.556815 0.250000\n"
|
||||
"\n"
|
||||
"f 31/31 32/32 33/33 34/34\n"
|
||||
"f 31/31 34/34 35/35 36/36\n"
|
||||
"f 31/31 36/36 37/37 38/38\n"
|
||||
"f 31/31 38/38 39/39 40/40\n"
|
||||
"f 36/36 31/31 34/34 35/35\n"
|
||||
"f 37/37 38/38 31/31 36/36\n"
|
||||
"f 38/38 39/39 40/40 31/31\n"
|
||||
"f 31/31 40/40 41/41 42/42\n"
|
||||
"f 31/31 42/42 43/43 44/44\n"
|
||||
"\n"
|
||||
|
@ -44,9 +44,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.132500 0.765048\n"
|
||||
"vt 0.245000 0.700096\n"
|
||||
"\n"
|
||||
"f 1/1 2/2 3/3 4/4 \n"
|
||||
"f 1/1 4/4 5/5 6/6 \n"
|
||||
"f 1/1 6/6 7/7 2/2 \n"
|
||||
"f 1/1 2/2 3/3 4/4\n"
|
||||
"f 6/6 1/1 4/4 5/5\n"
|
||||
"f 6/6 7/7 2/2 1/1\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 2: top-middle\n"
|
||||
@ -76,10 +76,10 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.621353 0.741832\n"
|
||||
"\n"
|
||||
"f 8/8 9/9 10/10 11/11\n"
|
||||
"f 8/8 11/11 12/12 13/13\n"
|
||||
"f 8/8 13/13 14/14 15/15\n"
|
||||
"f 8/8 15/15 16/16 17/17\n"
|
||||
"f 8/8 17/17 18/18 9/9 \n"
|
||||
"f 13/13 8/8 11/11 12/12\n"
|
||||
"f 14/14 15/15 8/8 13/13\n"
|
||||
"f 15/15 16/16 17/17 8/8\n"
|
||||
"f 8/8 17/17 18/18 9/9\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 3: top-right\n"
|
||||
@ -113,9 +113,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.959904 0.755000\n"
|
||||
"\n"
|
||||
"f 19/19 20/20 21/21 22/22\n"
|
||||
"f 19/19 22/22 23/23 24/24\n"
|
||||
"f 19/19 24/24 25/25 26/26\n"
|
||||
"f 19/19 26/26 27/27 28/28\n"
|
||||
"f 24/24 19/19 22/22 23/23\n"
|
||||
"f 25/25 26/26 19/19 24/24\n"
|
||||
"f 26/26 27/27 28/28 19/19\n"
|
||||
"f 19/19 28/28 29/29 30/30\n"
|
||||
"f 19/19 30/30 31/31 20/20\n"
|
||||
"\n"
|
||||
@ -155,9 +155,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.305145 0.434918\n"
|
||||
"\n"
|
||||
"f 32/32 33/33 34/34 35/35\n"
|
||||
"f 32/32 35/35 36/36 37/37\n"
|
||||
"f 32/32 37/37 38/38 39/39\n"
|
||||
"f 32/32 39/39 40/40 41/41\n"
|
||||
"f 37/37 32/32 35/35 36/36\n"
|
||||
"f 38/38 39/39 32/32 37/37\n"
|
||||
"f 39/39 40/40 41/41 32/32\n"
|
||||
"f 32/32 41/41 42/42 43/43\n"
|
||||
"f 32/32 43/43 44/44 45/45\n"
|
||||
"f 32/32 45/45 46/46 33/33\n"
|
||||
@ -202,9 +202,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.638582 0.442598\n"
|
||||
"\n"
|
||||
"f 47/47 48/48 49/49 50/50\n"
|
||||
"f 47/47 50/50 51/51 52/52\n"
|
||||
"f 47/47 52/52 53/53 54/54\n"
|
||||
"f 47/47 54/54 55/55 56/56\n"
|
||||
"f 52/52 47/47 50/50 51/51\n"
|
||||
"f 53/53 54/54 47/47 52/52\n"
|
||||
"f 54/54 55/55 56/56 47/47\n"
|
||||
"f 47/47 56/56 57/57 58/58\n"
|
||||
"f 47/47 58/58 59/59 60/60\n"
|
||||
"f 47/47 60/60 61/61 62/62\n"
|
||||
@ -254,9 +254,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.970954 0.448697\n"
|
||||
"\n"
|
||||
"f 64/64 65/65 66/66 67/67\n"
|
||||
"f 64/64 67/67 68/68 69/69\n"
|
||||
"f 64/64 69/69 70/70 71/71\n"
|
||||
"f 64/64 71/71 72/72 73/73\n"
|
||||
"f 69/69 64/64 67/67 68/68\n"
|
||||
"f 70/70 71/71 64/64 69/69\n"
|
||||
"f 71/71 72/72 73/73 64/64\n"
|
||||
"f 64/64 73/73 74/74 75/75\n"
|
||||
"f 64/64 75/75 76/76 77/77\n"
|
||||
"f 64/64 77/77 78/78 79/79\n"
|
||||
@ -310,16 +310,16 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.285413 0.086147\n"
|
||||
"vt 0.312659 0.123648\n"
|
||||
"\n"
|
||||
"f 83/83 84/84 85/85 86/86 \n"
|
||||
"f 83/83 86/86 87/87 88/88 \n"
|
||||
"f 83/83 88/88 89/89 90/90 \n"
|
||||
"f 83/83 90/90 91/91 92/92 \n"
|
||||
"f 83/83 92/92 93/93 94/94 \n"
|
||||
"f 83/83 94/94 95/95 96/96 \n"
|
||||
"f 83/83 96/96 97/97 98/98 \n"
|
||||
"f 83/83 84/84 85/85 86/86\n"
|
||||
"f 88/88 83/83 86/86 87/87\n"
|
||||
"f 89/89 90/90 83/83 88/88\n"
|
||||
"f 90/90 91/91 92/92 83/83\n"
|
||||
"f 83/83 92/92 93/93 94/94\n"
|
||||
"f 83/83 94/94 95/95 96/96\n"
|
||||
"f 83/83 96/96 97/97 98/98\n"
|
||||
"f 83/83 98/98 99/99 100/100\n"
|
||||
"f 83/83 100/100 101/101 102/102\n"
|
||||
"f 83/83 102/102 103/103 84/84 \n"
|
||||
"f 83/83 102/102 103/103 84/84\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 8: bottom-middle\n"
|
||||
@ -373,9 +373,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.643924 0.127740\n"
|
||||
"\n"
|
||||
"f 104/104 105/105 106/106 107/107\n"
|
||||
"f 104/104 107/107 108/108 109/109\n"
|
||||
"f 104/104 109/109 110/110 111/111\n"
|
||||
"f 104/104 111/111 112/112 113/113\n"
|
||||
"f 109/109 104/104 107/107 108/108\n"
|
||||
"f 110/110 111/111 104/104 109/109\n"
|
||||
"f 111/111 112/112 113/113 104/104\n"
|
||||
"f 104/104 113/113 114/114 115/115\n"
|
||||
"f 104/104 115/115 116/116 117/117\n"
|
||||
"f 104/104 117/117 118/118 119/119\n"
|
||||
@ -440,9 +440,9 @@ static const std::string catmark_xord_interior =
|
||||
"vt 0.974889 0.131177\n"
|
||||
"\n"
|
||||
"f 127/127 128/128 129/129 130/130\n"
|
||||
"f 127/127 130/130 131/131 132/132\n"
|
||||
"f 127/127 132/132 133/133 134/134\n"
|
||||
"f 127/127 134/134 135/135 136/136\n"
|
||||
"f 132/132 127/127 130/130 131/131\n"
|
||||
"f 133/133 134/134 127/127 132/132\n"
|
||||
"f 134/134 135/135 136/136 127/127\n"
|
||||
"f 127/127 136/136 137/137 138/138\n"
|
||||
"f 127/127 138/138 139/139 140/140\n"
|
||||
"f 127/127 140/140 141/141 142/142\n"
|
||||
|
47
regression/shapes/loop_tetrahedron.h
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright 2019 DreamWorks Animation LLC.
|
||||
//
|
||||
// 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_tetrahedron =
|
||||
"#\n"
|
||||
"# Tetrahedron oriented within an axially aligned cube:\n"
|
||||
"#\n"
|
||||
"v -1 -1 1\n"
|
||||
"v 1 -1 -1\n"
|
||||
"v 1 1 1\n"
|
||||
"v -1 1 -1\n"
|
||||
"\n"
|
||||
"vt 0.375 0.217\n"
|
||||
"vt 0.75 0.0\n"
|
||||
"vt 0.375 0.65\n"
|
||||
"vt 0.0 0.0\n"
|
||||
"vt 0.25 1.0\n"
|
||||
"vt 0.625 0.35\n"
|
||||
"vt 1.0 1.0\n"
|
||||
"\n"
|
||||
"f 1/1 2/2 3/3\n"
|
||||
"f 1/1 3/3 4/4\n"
|
||||
"f 1/1 4/4 2/2\n"
|
||||
"f 4/5 3/6 2/7\n"
|
||||
"\n"
|
||||
;
|
@ -24,7 +24,7 @@
|
||||
|
||||
static const std::string loop_xord_boundary =
|
||||
"#\n"
|
||||
"# Nine shapes ordered left->right and top->bottom in the XZ and UV planes\n"
|
||||
"# Four shapes ordered left->right and top->bottom in the XZ and UV planes\n"
|
||||
"#\n"
|
||||
"# Shape 1: top-left\n"
|
||||
"#\n"
|
||||
@ -42,10 +42,10 @@ static const std::string loop_xord_boundary =
|
||||
"vt 0.108579 0.891421\n"
|
||||
"vt 0.050000 0.750000\n"
|
||||
"\n"
|
||||
"f 1/1 2/2 3/3 \n"
|
||||
"f 1/1 3/3 4/4 \n"
|
||||
"f 1/1 4/4 5/5 \n"
|
||||
"f 1/1 5/5 6/6 \n"
|
||||
"f 1/1 2/2 3/3\n"
|
||||
"f 4/4 1/1 3/3\n"
|
||||
"f 4/4 5/5 1/1\n"
|
||||
"f 1/1 5/5 6/6\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 2: top-right\n"
|
||||
@ -66,9 +66,9 @@ static const std::string loop_xord_boundary =
|
||||
"vt 0.588197 0.867557\n"
|
||||
"vt 0.550000 0.750000\n"
|
||||
"\n"
|
||||
"f 7/7 8/8 9/9 \n"
|
||||
"f 7/7 9/9 10/10\n"
|
||||
"f 7/7 10/10 11/11\n"
|
||||
"f 7/7 8/8 9/9\n"
|
||||
"f 10/10 7/7 9/9\n"
|
||||
"f 10/10 11/11 7/7\n"
|
||||
"f 7/7 11/11 12/12\n"
|
||||
"f 7/7 12/12 13/13\n"
|
||||
"\n"
|
||||
@ -94,8 +94,8 @@ static const std::string loop_xord_boundary =
|
||||
"vt 0.050000 0.250000\n"
|
||||
"\n"
|
||||
"f 14/14 15/15 16/16\n"
|
||||
"f 14/14 16/16 17/17\n"
|
||||
"f 14/14 17/17 18/18\n"
|
||||
"f 17/17 14/14 16/16\n"
|
||||
"f 17/17 18/18 14/14\n"
|
||||
"f 14/14 18/18 19/19\n"
|
||||
"f 14/14 19/19 20/20\n"
|
||||
"f 14/14 20/20 21/21\n"
|
||||
@ -126,8 +126,8 @@ static const std::string loop_xord_boundary =
|
||||
"vt 0.550000 0.250000\n"
|
||||
"\n"
|
||||
"f 22/22 23/23 24/24\n"
|
||||
"f 22/22 24/24 25/25\n"
|
||||
"f 22/22 25/25 26/26\n"
|
||||
"f 25/25 22/22 24/24\n"
|
||||
"f 25/25 26/26 22/22\n"
|
||||
"f 22/22 26/26 27/27\n"
|
||||
"f 22/22 27/27 28/28\n"
|
||||
"f 22/22 28/28 29/29\n"
|
||||
|
@ -38,9 +38,9 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.116 0.932\n"
|
||||
"vt 0.116 0.703\n"
|
||||
"\n"
|
||||
"f 1/1 2/2 3/3 \n"
|
||||
"f 1/1 3/3 4/4 \n"
|
||||
"f 1/1 4/4 2/2 \n"
|
||||
"f 1/1 2/2 3/3\n"
|
||||
"f 4/4 1/1 3/3\n"
|
||||
"f 4/4 2/2 1/1\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 2: top-middle, valence-4 ring\n"
|
||||
@ -57,10 +57,10 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.368 0.818\n"
|
||||
"vt 0.500 0.685\n"
|
||||
"\n"
|
||||
"f 5/5 6/6 7/7 \n"
|
||||
"f 5/5 7/7 8/8 \n"
|
||||
"f 5/5 8/8 9/9 \n"
|
||||
"f 5/5 9/9 6/6 \n"
|
||||
"f 5/5 6/6 7/7\n"
|
||||
"f 8/8 5/5 7/7\n"
|
||||
"f 8/8 9/9 5/5\n"
|
||||
"f 5/5 9/9 6/6\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 3: top-right, valence-5 ring\n"
|
||||
@ -79,11 +79,11 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.711 0.740\n"
|
||||
"vt 0.859 0.692\n"
|
||||
"\n"
|
||||
"f 10/10 11/11 12/12 \n"
|
||||
"f 10/10 12/12 13/13 \n"
|
||||
"f 10/10 13/13 14/14 \n"
|
||||
"f 10/10 14/14 15/15 \n"
|
||||
"f 10/10 15/15 11/11 \n"
|
||||
"f 10/10 11/11 12/12\n"
|
||||
"f 13/13 10/10 12/12\n"
|
||||
"f 13/13 14/14 10/10\n"
|
||||
"f 10/10 14/14 15/15\n"
|
||||
"f 10/10 15/15 11/11\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 4: center-left, valence-7 ring\n"
|
||||
@ -106,13 +106,13 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.153 0.371\n"
|
||||
"vt 0.265 0.397\n"
|
||||
"\n"
|
||||
"f 16/16 17/17 18/18 \n"
|
||||
"f 16/16 18/18 19/19 \n"
|
||||
"f 16/16 19/19 20/20 \n"
|
||||
"f 16/16 20/20 21/21 \n"
|
||||
"f 16/16 21/21 22/22 \n"
|
||||
"f 16/16 22/22 23/23 \n"
|
||||
"f 16/16 23/23 17/17 \n"
|
||||
"f 16/16 17/17 18/18\n"
|
||||
"f 19/19 16/16 18/18\n"
|
||||
"f 19/19 20/20 16/16\n"
|
||||
"f 16/16 20/20 21/21\n"
|
||||
"f 16/16 21/21 22/22\n"
|
||||
"f 16/16 22/22 23/23\n"
|
||||
"f 16/16 23/23 17/17\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 5: center-middle, valence-8 ring\n"
|
||||
@ -137,14 +137,14 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.500 0.368\n"
|
||||
"vt 0.594 0.406\n"
|
||||
"\n"
|
||||
"f 24/24 25/25 26/26 \n"
|
||||
"f 24/24 26/26 27/27 \n"
|
||||
"f 24/24 27/27 28/28 \n"
|
||||
"f 24/24 28/28 29/29 \n"
|
||||
"f 24/24 29/29 30/30 \n"
|
||||
"f 24/24 30/30 31/31 \n"
|
||||
"f 24/24 31/31 32/32 \n"
|
||||
"f 24/24 32/32 25/25 \n"
|
||||
"f 24/24 25/25 26/26\n"
|
||||
"f 27/27 24/24 26/26\n"
|
||||
"f 27/27 28/28 24/24\n"
|
||||
"f 24/24 28/28 29/29\n"
|
||||
"f 24/24 29/29 30/30\n"
|
||||
"f 24/24 30/30 31/31\n"
|
||||
"f 24/24 31/31 32/32\n"
|
||||
"f 24/24 32/32 25/25\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 6: center-right, valence-9 ring\n"
|
||||
@ -171,15 +171,15 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.841 0.370\n"
|
||||
"vt 0.919 0.415\n"
|
||||
"\n"
|
||||
"f 33/33 34/34 35/35 \n"
|
||||
"f 33/33 35/35 36/36 \n"
|
||||
"f 33/33 36/36 37/37 \n"
|
||||
"f 33/33 37/37 38/38 \n"
|
||||
"f 33/33 38/38 39/39 \n"
|
||||
"f 33/33 39/39 40/40 \n"
|
||||
"f 33/33 40/40 41/41 \n"
|
||||
"f 33/33 41/41 42/42 \n"
|
||||
"f 33/33 42/42 34/34 \n"
|
||||
"f 33/33 34/34 35/35\n"
|
||||
"f 36/36 33/33 35/35\n"
|
||||
"f 36/36 37/37 33/33\n"
|
||||
"f 33/33 37/37 38/38\n"
|
||||
"f 33/33 38/38 39/39\n"
|
||||
"f 33/33 39/39 40/40\n"
|
||||
"f 33/33 40/40 41/41\n"
|
||||
"f 33/33 41/41 42/42\n"
|
||||
"f 33/33 42/42 34/34\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 7: bottom-left, valence-10 ring\n"
|
||||
@ -208,16 +208,16 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.223 0.056\n"
|
||||
"vt 0.289 0.105\n"
|
||||
"\n"
|
||||
"f 43/43 44/44 45/45 \n"
|
||||
"f 43/43 45/45 46/46 \n"
|
||||
"f 43/43 46/46 47/47 \n"
|
||||
"f 43/43 47/47 48/48 \n"
|
||||
"f 43/43 48/48 49/49 \n"
|
||||
"f 43/43 49/49 50/50 \n"
|
||||
"f 43/43 50/50 51/51 \n"
|
||||
"f 43/43 51/51 52/52 \n"
|
||||
"f 43/43 52/52 53/53 \n"
|
||||
"f 43/43 53/53 44/44 \n"
|
||||
"f 43/43 44/44 45/45\n"
|
||||
"f 46/46 43/43 45/45\n"
|
||||
"f 46/46 47/47 43/43\n"
|
||||
"f 43/43 47/47 48/48\n"
|
||||
"f 43/43 48/48 49/49\n"
|
||||
"f 43/43 49/49 50/50\n"
|
||||
"f 43/43 50/50 51/51\n"
|
||||
"f 43/43 51/51 52/52\n"
|
||||
"f 43/43 52/52 53/53\n"
|
||||
"f 43/43 53/53 44/44\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 8: bottom-middle, valence-11 ring\n"
|
||||
@ -248,17 +248,17 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.555 0.062\n"
|
||||
"vt 0.611 0.111\n"
|
||||
"\n"
|
||||
"f 54/54 55/55 56/56 \n"
|
||||
"f 54/54 56/56 57/57 \n"
|
||||
"f 54/54 57/57 58/58 \n"
|
||||
"f 54/54 58/58 59/59 \n"
|
||||
"f 54/54 59/59 60/60 \n"
|
||||
"f 54/54 60/60 61/61 \n"
|
||||
"f 54/54 61/61 62/62 \n"
|
||||
"f 54/54 62/62 63/63 \n"
|
||||
"f 54/54 63/63 64/64 \n"
|
||||
"f 54/54 64/64 65/65 \n"
|
||||
"f 54/54 65/65 55/55 \n"
|
||||
"f 54/54 55/55 56/56\n"
|
||||
"f 57/57 54/54 56/56\n"
|
||||
"f 57/57 58/58 54/54\n"
|
||||
"f 54/54 58/58 59/59\n"
|
||||
"f 54/54 59/59 60/60\n"
|
||||
"f 54/54 60/60 61/61\n"
|
||||
"f 54/54 61/61 62/62\n"
|
||||
"f 54/54 62/62 63/63\n"
|
||||
"f 54/54 63/63 64/64\n"
|
||||
"f 54/54 64/64 65/65\n"
|
||||
"f 54/54 65/65 55/55\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# Shape 9: bottom-right, valence-12 ring\n"
|
||||
@ -291,17 +291,17 @@ static const std::string loop_xord_interior =
|
||||
"vt 0.884 0.068\n"
|
||||
"vt 0.932 0.116\n"
|
||||
"\n"
|
||||
"f 66/66 67/67 68/68 \n"
|
||||
"f 66/66 68/68 69/69 \n"
|
||||
"f 66/66 69/69 70/70 \n"
|
||||
"f 66/66 70/70 71/71 \n"
|
||||
"f 66/66 71/71 72/72 \n"
|
||||
"f 66/66 72/72 73/73 \n"
|
||||
"f 66/66 73/73 74/74 \n"
|
||||
"f 66/66 74/74 75/75 \n"
|
||||
"f 66/66 75/75 76/76 \n"
|
||||
"f 66/66 76/76 77/77 \n"
|
||||
"f 66/66 77/77 78/78 \n"
|
||||
"f 66/66 78/78 67/67 \n"
|
||||
"f 66/66 67/67 68/68\n"
|
||||
"f 69/69 66/66 68/68\n"
|
||||
"f 69/69 70/70 66/66\n"
|
||||
"f 66/66 70/70 71/71\n"
|
||||
"f 66/66 71/71 72/72\n"
|
||||
"f 66/66 72/72 73/73\n"
|
||||
"f 66/66 73/73 74/74\n"
|
||||
"f 66/66 74/74 75/75\n"
|
||||
"f 66/66 75/75 76/76\n"
|
||||
"f 66/66 76/76 77/77\n"
|
||||
"f 66/66 77/77 78/78\n"
|
||||
"f 66/66 78/78 67/67\n"
|
||||
"\n"
|
||||
;
|
||||
|