mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-24 04:20:21 +00:00
Revamped Python bindings that use SWIG
This commit is contained in:
parent
2b12ffc447
commit
5f5c22a078
@ -201,6 +201,8 @@ find_package(OpenCL 1.1)
|
||||
find_package(CUDA 4.0)
|
||||
find_package(GLFW 2.7.0)
|
||||
find_package(PTex 2.0)
|
||||
find_package(PythonInterp)
|
||||
find_package(SWIG)
|
||||
|
||||
if (NOT APPLE AND OPENGL_FOUND)
|
||||
find_package(GLEW REQUIRED)
|
||||
@ -323,6 +325,30 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(PYTHON_FOUND AND SWIG_FOUND)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE} -c "import numpy; print numpy.get_include()"
|
||||
OUTPUT_VARIABLE NUMPY_INCLUDE_PATH
|
||||
RESULT_VARIABLE NUMPY_ERR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NUMPY_ERR)
|
||||
message(WARNING "Unable to import numpy.")
|
||||
else()
|
||||
add_custom_command(
|
||||
COMMENT "Building Python bindings with distutils"
|
||||
TARGET ${target} POST_BUILD
|
||||
WORKING_DIRECTORY python
|
||||
DEPENDS opensubdiv
|
||||
COMMAND ${PYTHON_EXECUTABLE} setup.py build osddir='${LIBRARY_OUTPUT_PATH}'
|
||||
)
|
||||
install(CODE "execute_process("
|
||||
"WORKING_DIRECTORY python "
|
||||
"COMMAND ${PYTHON_EXECUTABLE} setup.py install")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Link examples & regressions dynamically against Osd
|
||||
set( OSD_LINK_TARGET osd_dynamic_cpu osd_dynamic_gpu )
|
||||
|
||||
|
50
python/LICENSE
Normal file
50
python/LICENSE
Normal file
@ -0,0 +1,50 @@
|
||||
Microsoft Public License (Ms-PL)
|
||||
|
||||
This license governs use of the accompanying software. If you use the
|
||||
software, you accept this license. If you do not accept the license,
|
||||
do not use the software.
|
||||
|
||||
Definitions
|
||||
|
||||
The terms "reproduce," "reproduction," "derivative works," and
|
||||
"distribution" have the same meaning here as under U.S. copyright law.
|
||||
A "contribution" is the original software, or any additions or changes
|
||||
to the software. A "contributor" is any person that distributes its
|
||||
contribution under this license. "Licensed patents" are a
|
||||
contributor's patent claims that read directly on its contribution.
|
||||
|
||||
Grant of Rights
|
||||
|
||||
(A) Copyright Grant- Subject to the terms of this license, including
|
||||
the license conditions and limitations in section 3, each contributor
|
||||
grants you a non-exclusive, worldwide, royalty-free copyright license
|
||||
to reproduce its contribution, prepare derivative works of its
|
||||
contribution, and distribute its contribution or any derivative works
|
||||
that you create. (B) Patent Grant- Subject to the terms of this
|
||||
license, including the license conditions and limitations in section
|
||||
3, each contributor grants you a non-exclusive, worldwide,
|
||||
royalty-free license under its licensed patents to make, have made,
|
||||
use, sell, offer for sale, import, and/or otherwise dispose of its
|
||||
contribution in the software or derivative works of the contribution
|
||||
in the software.
|
||||
|
||||
Conditions and Limitations
|
||||
|
||||
(A) No Trademark License- This license does not grant you rights to
|
||||
use any contributors' name, logo, or trademarks. (B) If you bring a
|
||||
patent claim against any contributor over patents that you claim are
|
||||
infringed by the software, your patent license from such contributor
|
||||
to the software ends automatically. (C) If you distribute any portion
|
||||
of the software, you must retain all copyright, patent, trademark, and
|
||||
attribution notices that are present in the software. (D) If you
|
||||
distribute any portion of the software in source code form, you may do
|
||||
so only under this license by including a complete copy of this
|
||||
license with your distribution. If you distribute any portion of the
|
||||
software in compiled or object code form, you may only do so under a
|
||||
license that complies with this license. (E) The software is licensed
|
||||
"as-is." You bear the risk of using it. The contributors give no
|
||||
express warranties, guarantees, or conditions. You may have additional
|
||||
consumer rights under your local laws which this license cannot
|
||||
change. To the extent permitted under your local laws, the
|
||||
contributors exclude the implied warranties of merchantability,
|
||||
fitness for a particular purpose and non-infringement.
|
43
python/README.md
Normal file
43
python/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Instructions
|
||||
|
||||
The OpenSubdiv Python wrapper has been tested with Python 2.6 and Python 2.7.
|
||||
Make sure you have the numpy module installed before you begin.
|
||||
|
||||
First, try building the extension with:
|
||||
|
||||
./setup.py build osddir='../build/lib'
|
||||
|
||||
You'll need to replace `../build/lib` with the folder that has `libosdCPU.a` et al.
|
||||
|
||||
This creates a build folder with a platform-specific subfolder, such as:
|
||||
|
||||
./build/lib.macosx-10.8-intel-2.7
|
||||
|
||||
Next, try out the unit tests:
|
||||
|
||||
./setup.py test
|
||||
|
||||
You can clean, build, and test in one go like this:
|
||||
|
||||
./setup.py clean --all build test
|
||||
|
||||
If you'd like, you can try out an OpenGL demo. For this, you need to have PyQt and PyOpenGL installed.
|
||||
|
||||
./setup.py install --user demo
|
||||
|
||||
You can also install the module globally with:
|
||||
|
||||
sudo ./setup.py install
|
||||
|
||||
After installing the module, you can generate and view the Sphinx-generated documentation like so:
|
||||
|
||||
./setup.py doc
|
||||
open ./doc/_build/html/index.html
|
||||
|
||||
# To Do Items
|
||||
|
||||
- Add support for face varying data by augmenting _FaceAdapter in adapters.py
|
||||
- Exercise this in the demo by getting it down to GPU (maybe do "discard" for certain faces)
|
||||
- Instead of using OsdCpuVertexBuffer, create a "NumpyCpuVertexBuffer" that wraps a numpy array
|
||||
- Add an API that looks very similar to the RIB parameters for RiHierarchicalSubdiv
|
||||
- Remove all the caveats that are listed in the Sphinx docs :)
|
12
python/demo/README.md
Normal file
12
python/demo/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
This folder defines a small demo application that uses PyQt and newish version of PyOpenGL.
|
||||
|
||||
![Screenshot](http://raw.github.com/prideout/OpenSubdiv/master/python/demo/screenshot.png)
|
||||
|
||||
- **main.py** All calls to the OSD wrapper go here. This creates a `QApplication` and periodically pushes new VBO data into the renderer. (see below)
|
||||
- **renderer.py** Defines the renderer; implements `draw` and `init`. All OpenGL calls are made in this file, and there's no dependency on Qt or OSD.
|
||||
- **canvas.py** Inherits from `QGLWidget` and calls out to the renderer object (see above)
|
||||
- **shaders.py** Implements a miniature FX format by extracting named strings from a file and pasting them together
|
||||
- **simple.glsl** Specifies the GLSL shaders for the demo using the miniature FX format
|
||||
- **utility.py** Some linear algebra stuff to make it easier to use Modern OpenGL
|
||||
- **window.py** Inherits from `QMainWindow`, instances a canvas object
|
||||
- **\_\_init\_\_.py** Exports `main` into the package namespace to make it easy to run the demo from `setup.py`
|
60
python/demo/__init__.py
Normal file
60
python/demo/__init__.py
Normal file
@ -0,0 +1,60 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from main import main
|
||||
from interactive import interactive
|
||||
|
97
python/demo/canvas.py
Normal file
97
python/demo/canvas.py
Normal file
@ -0,0 +1,97 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4.QtOpenGL import *
|
||||
from OpenGL.GL import *
|
||||
from time import time
|
||||
|
||||
# Set this to 'None' to refresh as rapidly as possible
|
||||
# (assuming that vsync is disabled.)
|
||||
ThrottleFps = 60
|
||||
|
||||
class Canvas(QGLWidget):
|
||||
def __init__(self, parent, client):
|
||||
self.client = client
|
||||
f = QGLFormat(QGL.SampleBuffers)
|
||||
if hasattr(QGLFormat, 'setVersion'):
|
||||
f.setVersion(3, 2)
|
||||
f.setProfile(QGLFormat.CoreProfile)
|
||||
else:
|
||||
pass
|
||||
if f.sampleBuffers():
|
||||
f.setSamples(16)
|
||||
c = QGLContext(f, None)
|
||||
QGLWidget.__init__(self, c, parent)
|
||||
self.timer = QtCore.QTimer()
|
||||
self.timer.timeout.connect(self.updateGL)
|
||||
interval = 1000.0 / ThrottleFps if ThrottleFps else 0
|
||||
self.timer.start(interval)
|
||||
self.setMinimumSize(500, 500)
|
||||
|
||||
def paintGL(self):
|
||||
self.client.draw()
|
||||
|
||||
def updateGL(self):
|
||||
self.client.draw()
|
||||
self.update()
|
||||
|
||||
def resizeGL(self, w, h):
|
||||
self.client.resize(w, h)
|
||||
|
||||
def initializeGL(self):
|
||||
self.client.init()
|
136
python/demo/interactive.py
Normal file
136
python/demo/interactive.py
Normal file
@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from window import Window
|
||||
from renderer import Renderer
|
||||
import sys
|
||||
import numpy as np
|
||||
import osd
|
||||
import utility
|
||||
|
||||
from time import time
|
||||
import math
|
||||
|
||||
def interactive():
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
renderer = Renderer()
|
||||
win = Window(renderer)
|
||||
win.raise_()
|
||||
|
||||
cage = [ 0.0, -1.414214, 1.0, # 0
|
||||
1.414214, 0.0, 1.0, # 1
|
||||
-1.414214, 0.0, 1.0, # 2
|
||||
0.0, 1.414214, 1.0, # 3
|
||||
-1.414214, 0.0, -1.0, # 4
|
||||
0.0, 1.414214, -1.0, # 5
|
||||
0.0, -1.414214, -1.0, # 6
|
||||
1.414214, 0.0, -1.0 ] # 7
|
||||
|
||||
cage = np.array(cage, np.float32).reshape((-1, 3))
|
||||
|
||||
faces = [ (0,1,3,2), # 0
|
||||
(2,3,5,4), # 1
|
||||
(4,5,7,6), # 2
|
||||
(6,7,1,0), # 3
|
||||
(1,7,5,3), # 4
|
||||
(6,0,2,4) ] # 5
|
||||
|
||||
topo = osd.Topology(faces)
|
||||
|
||||
dtype = [('x', np.float32),
|
||||
('y', np.float32),
|
||||
('z', np.float32)]
|
||||
|
||||
def updateTopo(numLevels = 4):
|
||||
global subdivider
|
||||
topo.reset()
|
||||
topo.finalize()
|
||||
subdivider = osd.Subdivider(
|
||||
topo,
|
||||
vertexLayout = dtype,
|
||||
indexType = np.uint32,
|
||||
levels = numLevels)
|
||||
quads = subdivider.getRefinedQuads()
|
||||
renderer.updateIndicesVbo(quads)
|
||||
|
||||
def updateCoarseVertices():
|
||||
global subdivider
|
||||
subdivider.setCoarseVertices(cage)
|
||||
subdivider.refine()
|
||||
pts = subdivider.getRefinedVertices()
|
||||
renderer.updatePointsVbo(pts)
|
||||
|
||||
updateTopo()
|
||||
updateCoarseVertices()
|
||||
|
||||
renderer.drawHook = updateCoarseVertices
|
||||
|
||||
# Start an interactive session
|
||||
import code
|
||||
from time import time
|
||||
timer = QtCore.QTimer()
|
||||
code.interact(local=dict(globals(), **locals()))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
interactive()
|
147
python/demo/main.py
Normal file
147
python/demo/main.py
Normal file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from window import Window
|
||||
from renderer import Renderer
|
||||
import sys
|
||||
import numpy as np
|
||||
import osd
|
||||
|
||||
def main():
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
renderer = Renderer()
|
||||
win = Window(renderer)
|
||||
win.raise_()
|
||||
|
||||
verts = [ 0.0, -1.414214, 1.0, # 0
|
||||
1.414214, 0.0, 1.0, # 1
|
||||
-1.414214, 0.0, 1.0, # 2
|
||||
0.0, 1.414214, 1.0, # 3
|
||||
-1.414214, 0.0, -1.0, # 4
|
||||
0.0, 1.414214, -1.0, # 5
|
||||
0.0, -1.414214, -1.0, # 6
|
||||
1.414214, 0.0, -1.0 ] # 7
|
||||
|
||||
verts = np.array(verts, np.float32).reshape((-1, 3))
|
||||
|
||||
faces = [ (0,1,3,2), # 0
|
||||
(2,3,5,4), # 1
|
||||
(4,5,7,6), # 2
|
||||
(6,7,1,0), # 3
|
||||
(1,7,5,3), # 4
|
||||
(6,0,2,4) ] # 5
|
||||
|
||||
dtype = np.dtype([
|
||||
('Px', np.float32),
|
||||
('Py', np.float32),
|
||||
('Pz', np.float32)])
|
||||
|
||||
topo = osd.Topology(faces)
|
||||
topo.boundaryMode = osd.BoundaryMode.EDGE_ONLY
|
||||
for v in (2, 3, 4, 5):
|
||||
topo.vertices[v].sharpness = 2.0
|
||||
for e in xrange(4):
|
||||
topo.faces[3].edges[e].sharpness = 3
|
||||
topo.finalize()
|
||||
|
||||
subdivider = osd.Subdivider(
|
||||
topo,
|
||||
vertexLayout = dtype,
|
||||
indexType = np.uint32,
|
||||
levels = 4)
|
||||
subdivider.setCoarseVertices(verts)
|
||||
subdivider.refine()
|
||||
inds = subdivider.getRefinedQuads()
|
||||
renderer.updateIndicesVbo(inds)
|
||||
|
||||
def animateVerts():
|
||||
from time import time
|
||||
import math
|
||||
t = 4 * time()
|
||||
t = 0
|
||||
t = 0.5 + 0.5 * math.sin(t)
|
||||
t = 0.25 + t * 0.75
|
||||
a = np.array([ 0.0, -1.414214, 1.0])
|
||||
b = np.array([ 1.414214, 0.0, 1.0])
|
||||
c = np.array([ 0.0, -1.414214, -1.0])
|
||||
d = np.array([1.414214, 0.0, -1.0 ])
|
||||
center = (a + b + c + d) / 4
|
||||
center = np.multiply(center, 1-t)
|
||||
verts[0] = center + np.multiply(a, t)
|
||||
verts[1] = center + np.multiply(b, t)
|
||||
verts[6] = center + np.multiply(c, t)
|
||||
verts[7] = center + np.multiply(d, t)
|
||||
|
||||
def updateAnimation():
|
||||
animateVerts()
|
||||
subdivider.setCoarseVertices(verts)
|
||||
subdivider.refine()
|
||||
pts = subdivider.getRefinedVertices()
|
||||
renderer.updatePointsVbo(pts)
|
||||
|
||||
updateAnimation()
|
||||
renderer.drawHook = updateAnimation
|
||||
retcode = app.exec_()
|
||||
sys.exit(retcode)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
154
python/demo/renderer.py
Normal file
154
python/demo/renderer.py
Normal file
@ -0,0 +1,154 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
from OpenGL.GL import *
|
||||
from shaders import *
|
||||
from utility import *
|
||||
from canvas import *
|
||||
|
||||
class Renderer:
|
||||
def __init__(self):
|
||||
self.indexCount = 0
|
||||
|
||||
def draw(self):
|
||||
|
||||
if hasattr(self, "drawHook"):
|
||||
self.drawHook()
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
if not self.indexCount:
|
||||
return
|
||||
|
||||
theta = time() * math.pi / 2
|
||||
eye = V3(0, 0, 10)
|
||||
target = V3(0, 0, 0)
|
||||
up = V3(0, 1, 0)
|
||||
view = look_at(eye, target, up)
|
||||
|
||||
model = np.identity(4, 'f')
|
||||
model = rotation(-1.1 + theta, [0,1,0])
|
||||
|
||||
objToEye = view * model
|
||||
eyeToClip = perspective(15, self.aspect, 5, 200)
|
||||
normalM = np.identity(3, 'f')
|
||||
normalM[:3,:3] = objToEye[:3,:3]
|
||||
|
||||
glUseProgram(self.programs['BareBones'])
|
||||
glUniformMatrix4fv(U("Projection"), 1, True, eyeToClip)
|
||||
glUniformMatrix4fv(U("Modelview"), 1, True, objToEye)
|
||||
glUniformMatrix3fv(U("NormalMatrix"), 1, True, normalM)
|
||||
glBindVertexArray(self.vao)
|
||||
|
||||
# Since quads are deprecated we use LINES_ADJACENCY
|
||||
# simply because they're 4 verts per prim, and we can
|
||||
# expand them to triangles in the GS.
|
||||
glDrawElements(
|
||||
GL_LINES_ADJACENCY,
|
||||
self.indexCount,
|
||||
GL_UNSIGNED_INT,
|
||||
None)
|
||||
|
||||
def resize(self, w, h):
|
||||
self.aspect = float(w) / float(h)
|
||||
glViewport(0, 0, w, h)
|
||||
|
||||
def init(self):
|
||||
print glGetString(GL_VERSION)
|
||||
glClearColor(0.0, 0.25, 0.5, 1.0)
|
||||
self.programs = load_shaders()
|
||||
|
||||
try:
|
||||
self.vao = glGenVertexArrays(1)
|
||||
except:
|
||||
import sys
|
||||
print "glGenVertexArrays isn't available, so you might need a newer version of PyOpenGL."
|
||||
sys.exit(1)
|
||||
|
||||
self.pointsVbo = glGenBuffers(1)
|
||||
self.normalsVbo = None
|
||||
self.indicesVbo = glGenBuffers(1)
|
||||
glBindVertexArray(self.vao)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.indicesVbo)
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.pointsVbo)
|
||||
glVertexAttribPointer(Attribs.POSITION, 3, GL_FLOAT, GL_FALSE, 12, None)
|
||||
glEnableVertexAttribArray(Attribs.POSITION)
|
||||
|
||||
glEnable(GL_CULL_FACE)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
def updatePointsVbo(self, points):
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.pointsVbo)
|
||||
glBufferData(GL_ARRAY_BUFFER, points, GL_STATIC_DRAW)
|
||||
|
||||
def updateNormalsVbo(self, normals):
|
||||
if not self.normalsVbo:
|
||||
self.normalsVbo = glGenBuffers(1)
|
||||
glBindVertexArray(self.vao)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.normalsVbo)
|
||||
glVertexAttribPointer(Attribs.NORMAL, 3, GL_FLOAT, GL_FALSE, 12, None)
|
||||
glEnableVertexAttribArray(Attribs.NORMAL)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.normalsVbo)
|
||||
glBufferData(GL_ARRAY_BUFFER, normals, GL_STATIC_DRAW)
|
||||
|
||||
def updateIndicesVbo(self, indices):
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.indicesVbo)
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)
|
||||
self.indexCount = len(indices)
|
BIN
python/demo/screenshot.png
Normal file
BIN
python/demo/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
149
python/demo/shaders.py
Normal file
149
python/demo/shaders.py
Normal file
@ -0,0 +1,149 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from OpenGL.GL import *
|
||||
|
||||
ProgramFiles = ['demo/simple.glsl']
|
||||
|
||||
Programs = {
|
||||
"BareBones" : {
|
||||
"GL_VERTEX_SHADER" : "simple.xforms simple.vert",
|
||||
"GL_GEOMETRY_SHADER" : "simple.xforms simple.geom",
|
||||
"GL_FRAGMENT_SHADER" : "simple.xforms simple.frag"
|
||||
}
|
||||
}
|
||||
|
||||
class Attribs:
|
||||
POSITION = 0
|
||||
NORMAL = 1
|
||||
|
||||
def load_shaders(
|
||||
glslFiles = ProgramFiles,
|
||||
attribs = Attribs,
|
||||
programMap = Programs):
|
||||
"""Parse a series of simple text files, each of which is composed
|
||||
series of shader snippets. The given 'attribs' class defines an
|
||||
enumeration of attribute slots to bind (aka semantics).
|
||||
|
||||
In each text file, lines starting with two dash characters start a new
|
||||
shader snippet with the given name. For example:
|
||||
-- S1
|
||||
uniform float foo;
|
||||
-- Prefix
|
||||
#version 150
|
||||
-- S2
|
||||
uniform float bar;
|
||||
"""
|
||||
|
||||
import os.path
|
||||
|
||||
# First parse the file to populate 'snippetMap'
|
||||
class ParserState:
|
||||
HEADER = 0
|
||||
SOURCE = 1
|
||||
parserState = ParserState.HEADER
|
||||
snippetMap = {}
|
||||
for glslFile in glslFiles:
|
||||
basename = os.path.basename(glslFile)
|
||||
snippetPrefix = os.path.splitext(basename)[0] + '.'
|
||||
for line in open(glslFile):
|
||||
if line.startswith('--'):
|
||||
if parserState is ParserState.HEADER:
|
||||
parserState = ParserState.SOURCE
|
||||
elif len(source):
|
||||
snippetMap[snippetName] = ''.join(source)
|
||||
snippetName = snippetPrefix + line[2:].strip()
|
||||
source = []
|
||||
continue
|
||||
if parserState is ParserState.HEADER:
|
||||
pass
|
||||
else:
|
||||
source.append(line)
|
||||
if len(source):
|
||||
snippetMap[snippetName] = ''.join(source)
|
||||
|
||||
# Now, glue together the strings and feed them to OpenGL
|
||||
stagePrefix = "#version 150\n"
|
||||
programs = {}
|
||||
for key, val in programMap.items():
|
||||
programHandle = glCreateProgram()
|
||||
for stageName, snippetList in val.items():
|
||||
snippets = map(snippetMap.get, snippetList.split())
|
||||
stageSource = stagePrefix + ''.join(snippets)
|
||||
stage = getattr(OpenGL.GL, stageName)
|
||||
sHandle = glCreateShader(stage)
|
||||
glShaderSource(sHandle, stageSource)
|
||||
glCompileShader(sHandle)
|
||||
success = glGetShaderiv(sHandle, GL_COMPILE_STATUS)
|
||||
if not success:
|
||||
print 'Error in', stageName, snippetList
|
||||
infolog = glGetShaderInfoLog(sHandle)
|
||||
raise SystemExit(infolog)
|
||||
glAttachShader(programHandle, sHandle)
|
||||
for attrib in dir(attribs):
|
||||
if attrib.startswith('__'):
|
||||
continue
|
||||
slot = getattr(attribs, attrib)
|
||||
name = attrib[0] + attrib[1:].lower()
|
||||
glBindAttribLocation(programHandle, slot, name)
|
||||
glLinkProgram(programHandle)
|
||||
success = glGetProgramiv(programHandle, GL_LINK_STATUS);
|
||||
if not success:
|
||||
infolog = glGetProgramInfoLog(programHandle)
|
||||
raise SystemExit(infolog)
|
||||
programs[key] = programHandle
|
||||
return programs
|
143
python/demo/simple.glsl
Normal file
143
python/demo/simple.glsl
Normal file
@ -0,0 +1,143 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
-- xforms
|
||||
|
||||
uniform mat4 Projection;
|
||||
uniform mat4 Modelview;
|
||||
uniform mat3 NormalMatrix;
|
||||
|
||||
-- vert
|
||||
|
||||
in vec4 Position;
|
||||
in vec3 Normal;
|
||||
out vec4 vPosition;
|
||||
out vec3 vNormal;
|
||||
void main()
|
||||
{
|
||||
vPosition = Position;
|
||||
vNormal = Normal;
|
||||
gl_Position = Projection * Modelview * Position;
|
||||
}
|
||||
|
||||
-- geom
|
||||
|
||||
in vec4 vPosition[4];
|
||||
in vec3 vNormal[4];
|
||||
out vec3 gNormal;
|
||||
const bool facets = true;
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
void emit(int index)
|
||||
{
|
||||
if (!facets) {
|
||||
gNormal = NormalMatrix * vNormal[index];
|
||||
}
|
||||
gl_Position = Projection * Modelview * vPosition[index];
|
||||
gl_Position.z = 1 - gl_Position.z;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if (facets) {
|
||||
vec3 A = vPosition[0].xyz;
|
||||
vec3 B = vPosition[1].xyz;
|
||||
vec3 C = vPosition[2].xyz;
|
||||
gNormal = NormalMatrix * normalize(cross(B - A, C - A));
|
||||
}
|
||||
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(3);
|
||||
emit(2);
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
-- frag
|
||||
|
||||
in vec3 gNormal;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform vec4 LightPosition = vec4(0.75, -0.25, 1, 1);
|
||||
uniform vec3 AmbientMaterial = vec3(0.2, 0.1, 0.1);
|
||||
uniform vec4 DiffuseMaterial = vec4(1.0, 209.0/255.0, 54.0/255.0, 1.0);
|
||||
uniform vec3 SpecularMaterial = vec3(0.4, 0.4, 0.3);
|
||||
uniform float Shininess = 200.0;
|
||||
uniform float Fresnel = 0.1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 N = normalize(gNormal);
|
||||
vec3 L = normalize((LightPosition).xyz);
|
||||
|
||||
vec3 Eye = vec3(0, 0, 1);
|
||||
vec3 H = normalize(L + Eye);
|
||||
|
||||
float df = max(0.0, dot(N, L));
|
||||
float sf = pow(max(0.0, dot(N, H)), Shininess);
|
||||
float rfTheta = Fresnel + (1-Fresnel) * pow(1-dot(N,Eye), 5);
|
||||
|
||||
vec3 color = AmbientMaterial +
|
||||
df * DiffuseMaterial.rgb +
|
||||
sf * SpecularMaterial +
|
||||
rfTheta;
|
||||
|
||||
FragColor = vec4(color, DiffuseMaterial.a);
|
||||
}
|
135
python/demo/utility.py
Normal file
135
python/demo/utility.py
Normal file
@ -0,0 +1,135 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from OpenGL.GL import *
|
||||
from time import time
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
from numpy import linalg as LA
|
||||
|
||||
# Provide a terse way to get a uniform location from its name
|
||||
def U(name):
|
||||
p = glGetIntegerv(GL_CURRENT_PROGRAM)
|
||||
return glGetUniformLocation(p, name)
|
||||
|
||||
# Provide a terse way to create a f32 numpy 3-tuple
|
||||
def V3(x, y, z):
|
||||
return np.array([x, y, z], 'f')
|
||||
|
||||
def translation(direction):
|
||||
M = np.identity(4, 'f')
|
||||
M[:3, 3] = direction[:3]
|
||||
return M
|
||||
|
||||
def unit_vector(data, axis=None, out=None):
|
||||
if out is None:
|
||||
data = np.array(data, dtype=np.float32, copy=True)
|
||||
if data.ndim == 1:
|
||||
data /= math.sqrt(np.dot(data, data))
|
||||
return data
|
||||
else:
|
||||
if out is not data:
|
||||
out[:] = np.array(data, copy=False)
|
||||
data = out
|
||||
length = np.atleast_1d(np.sum(data*data, axis))
|
||||
np.sqrt(length, length)
|
||||
if axis is not None:
|
||||
length = np.expand_dims(length, axis)
|
||||
data /= length
|
||||
if out is None:
|
||||
return data
|
||||
|
||||
def rotation3(angle, direction):
|
||||
sina = math.sin(angle)
|
||||
cosa = math.cos(angle)
|
||||
direction = unit_vector(direction[:3])
|
||||
R = np.diag([cosa, cosa, cosa])
|
||||
R += np.outer(direction, direction) * (1.0 - cosa)
|
||||
direction *= sina
|
||||
R += np.array([[ 0.0, -direction[2], direction[1]],
|
||||
[ direction[2], 0.0, -direction[0]],
|
||||
[-direction[1], direction[0], 0.0]])
|
||||
return R
|
||||
|
||||
def rotation(angle, direction):
|
||||
R = rotation3(angle, direction)
|
||||
M = np.identity(4, 'f')
|
||||
M[:3, :3] = R
|
||||
return M
|
||||
|
||||
def look_at(eye, target, up):
|
||||
F = target[:3] - eye[:3]
|
||||
f = F / LA.norm(F)
|
||||
U = up / LA.norm(up)
|
||||
s = np.cross(f, U)
|
||||
u = np.cross(s, f)
|
||||
M = np.matrix(np.identity(4))
|
||||
M[:3,:3] = [s,u,-f]
|
||||
T = translation(-eye)
|
||||
return np.matrix(M * T, 'f')
|
||||
|
||||
def perspective(fovy, aspect, f, n):
|
||||
s = 1.0/math.tan(math.radians(fovy)/2.0)
|
||||
sx, sy = s / aspect, s
|
||||
zz = (f+n)/(n-f)
|
||||
zw = 2*f*n/(n-f)
|
||||
m = np.matrix([[sx,0,0,0],
|
||||
[0,sy,0,0],
|
||||
[0,0,zz,zw],
|
||||
[0,0,-1,0]], 'f')
|
||||
return m
|
72
python/demo/window.py
Normal file
72
python/demo/window.py
Normal file
@ -0,0 +1,72 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from canvas import Canvas
|
||||
|
||||
class Window(QtGui.QMainWindow):
|
||||
def __init__(self, client):
|
||||
super(Window, self).__init__()
|
||||
self.canvas = Canvas(self, client)
|
||||
self.setCentralWidget(self.canvas)
|
||||
self.setGeometry(300, 300, 250, 150)
|
||||
self.setWindowTitle('PyQt')
|
||||
self.show()
|
||||
|
||||
def keyPressEvent(self, e):
|
||||
if e.key() == QtCore.Qt.Key_Escape:
|
||||
self.close()
|
153
python/doc/Makefile
Normal file
153
python/doc/Makefile
Normal file
@ -0,0 +1,153 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenSubdiv.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenSubdiv.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/OpenSubdiv"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenSubdiv"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
244
python/doc/conf.py
Normal file
244
python/doc/conf.py
Normal file
@ -0,0 +1,244 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# OpenSubdiv documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Nov 21 15:45:14 2012.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'OpenSubdiv'
|
||||
copyright = u'2012, Pixar Animation Studios'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'OpenSubdivdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'OpenSubdiv.tex', u'OpenSubdiv Documentation',
|
||||
u'Pixar Animation Studios', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'opensubdiv', u'OpenSubdiv Documentation',
|
||||
[u'Pixar Animation Studios'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'OpenSubdiv', u'OpenSubdiv Documentation',
|
||||
u'Pixar Animation Studios', 'OpenSubdiv', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
autodoc_member_order = 'bysource'
|
69
python/doc/index.rst
Normal file
69
python/doc/index.rst
Normal file
@ -0,0 +1,69 @@
|
||||
.. OpenSubdiv documentation master file, created by
|
||||
sphinx-quickstart on Wed Nov 21 15:45:14 2012.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Overview and Design Philosophy
|
||||
=======
|
||||
|
||||
The Python module for OpenSubdiv does not provide one-to-one wrapping of the native C++ APIs: Osd, Hbr, and Far. Rather, the ``osd`` module is a higher-level utility layer composed of a small handful of classes and free functions.
|
||||
|
||||
We do not yet support rendering or GPU-accelerated subdivision from Python, but a demo is provided that renders a subdivided surface using ``PyOpenGL`` and ``QGLWidget``. The demo uses a "modern" OpenGL context (Core Profile).
|
||||
|
||||
These bindings leverage numpy_ arrays for passing data. The numpy library is a de facto standard for encapsulating large swaths of typed data in Python. However, for special attributes (such as sharpness), the OpenSubdiv wrapper exposes Pythonic interfaces, using properties and list accessors. For example::
|
||||
|
||||
import osd
|
||||
import numpy as np
|
||||
faceList = np.array([[0,1,2,3],[0,1,6,7]])
|
||||
topo = osd.Topology(faceList)
|
||||
topo.vertices[2].sharpness = 1.3
|
||||
topo.faces[0].edges[3].sharpness = 0.6
|
||||
|
||||
After constructing a :class:`osd.Topology` object, clients should finalize it and pass it into a :class:`osd.Subdivider` instance::
|
||||
|
||||
topo.finalize()
|
||||
subdivider = osd.Subdivider(
|
||||
topo,
|
||||
vertexLayout = [np.float32] * 3,
|
||||
indexType = np.uint32,
|
||||
levels = 4)
|
||||
|
||||
The final step is to perform actual refinement. This often occurs inside an animation loop or callback function::
|
||||
|
||||
subdivider.setCage(positions)
|
||||
subdivider.refine()
|
||||
pts = subdivider.getRefinedVertices()
|
||||
|
||||
.. _numpy: http://www.numpy.org
|
||||
|
||||
Topology Class
|
||||
==============
|
||||
|
||||
.. autoclass:: osd.Topology
|
||||
:members:
|
||||
|
||||
Subdivider Class
|
||||
==============
|
||||
|
||||
.. autoclass:: osd.Subdivider
|
||||
:members:
|
||||
|
||||
Enumerations
|
||||
==============
|
||||
|
||||
.. autoclass:: osd.InterpolateBoundary
|
||||
:members:
|
||||
|
||||
.. autoclass:: osd.Sharpness
|
||||
:members:
|
||||
|
||||
Caveats
|
||||
=======
|
||||
|
||||
- Hierarchical edits are not yet supported
|
||||
- Face varying data is not yet supported
|
||||
- Feature adaptive subdivision is not yet supported
|
||||
- CUDA and GLSL tessellation shaders are not yet supported
|
||||
- Only the Catmull-Clark scheme is supported (no loop or linear schemes)
|
||||
- Vertex data must be 32-bit floats although API is in place to accept heterogenous interpolation data
|
||||
- Index data must be 32-bit unsigned integers although API is in place to accept other types
|
60
python/osd/__init__.py
Normal file
60
python/osd/__init__.py
Normal file
@ -0,0 +1,60 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from common import *
|
||||
from topology import Topology
|
||||
from subdivider import Subdivider
|
141
python/osd/adapters.py
Normal file
141
python/osd/adapters.py
Normal file
@ -0,0 +1,141 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
# Helper classes that present mesh data as a Pythonic list-like
|
||||
# objects with properties. In general we prefer clients to use numpy
|
||||
# arrays for data. However, for OSD-specific data such as sharpness,
|
||||
# we provide these adapter classes.
|
||||
|
||||
class VertexListAdapter(object):
|
||||
def __init__(self, shim):
|
||||
self.shim = shim
|
||||
self.length = shim.getNumVertices()
|
||||
def __getitem__(self, index):
|
||||
if index >= self.length:
|
||||
raise IndexError("Index out of bounds")
|
||||
return _VertexAdapter(self.shim, index)
|
||||
def __len__(self):
|
||||
return self.length
|
||||
|
||||
class _VertexAdapter(object):
|
||||
def __init__(self, shim, index):
|
||||
self.shim = shim
|
||||
self.index = index
|
||||
@property
|
||||
def sharpness(self):
|
||||
return self.shim.getVertexSharpness(
|
||||
self.index)
|
||||
@sharpness.setter
|
||||
def sharpness(self, value):
|
||||
self.shim.setVertexSharpness(
|
||||
self.index,
|
||||
value)
|
||||
|
||||
class FaceListAdapter(object):
|
||||
def __init__(self, shim):
|
||||
self.shim = shim
|
||||
self.length = shim.getNumFaces()
|
||||
def __getitem__(self, index):
|
||||
if index >= self.length:
|
||||
raise IndexError("Index out of bounds")
|
||||
return _FaceAdapter(self.shim, index)
|
||||
def __len__(self):
|
||||
return self.length
|
||||
|
||||
class _FaceAdapter(object):
|
||||
def __init__(self, shim, faceIndex):
|
||||
self.shim = shim
|
||||
self.faceIndex = faceIndex
|
||||
self._edgeListAdapter = _EdgeListAdapter(self.shim, faceIndex)
|
||||
@property
|
||||
def hole(self):
|
||||
return self.shim.getFaceHole(self.faceIndex)
|
||||
@hole.setter
|
||||
def hole(self, value):
|
||||
self.shim.setFaceHole(self.faceIndex, value)
|
||||
@property
|
||||
def edges(self):
|
||||
return self._edgeListAdapter
|
||||
|
||||
class _EdgeListAdapter(object):
|
||||
def __init__(self, shim, faceIndex):
|
||||
self.shim = shim
|
||||
self.faceIndex = faceIndex
|
||||
self.length = shim.getNumEdges(faceIndex)
|
||||
def __getitem__(self, edgeIndex):
|
||||
if edgeIndex >= self.length:
|
||||
raise IndexError("Index out of bounds")
|
||||
return _EdgeAdapter(self.shim, self.faceIndex, edgeIndex)
|
||||
def __len__(self):
|
||||
return self.length
|
||||
|
||||
class _EdgeAdapter(object):
|
||||
def __init__(self, shim, faceIndex, edgeIndex):
|
||||
self.shim = shim
|
||||
self.faceIndex = faceIndex
|
||||
self.edgeIndex = edgeIndex
|
||||
@property
|
||||
def sharpness(self):
|
||||
return self.shim.getEdgeSharpness(
|
||||
self.faceIndex,
|
||||
self.edgeIndex)
|
||||
@sharpness.setter
|
||||
def sharpness(self, value):
|
||||
self.shim.setEdgeSharpness(
|
||||
self.faceIndex,
|
||||
self.edgeIndex,
|
||||
value)
|
98
python/osd/buffer.h
Normal file
98
python/osd/buffer.h
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
namespace shim {
|
||||
|
||||
typedef std::vector<unsigned char> Buffer;
|
||||
|
||||
enum DataType {
|
||||
invalid,
|
||||
int8,
|
||||
uint8,
|
||||
int16,
|
||||
uint16,
|
||||
int32,
|
||||
uint32,
|
||||
int64,
|
||||
uint64,
|
||||
int128,
|
||||
uint128,
|
||||
int256,
|
||||
uint256,
|
||||
float16,
|
||||
float32,
|
||||
float64,
|
||||
float80,
|
||||
float96,
|
||||
float128,
|
||||
};
|
||||
|
||||
struct HomogeneousBuffer {
|
||||
shim::Buffer Buffer;
|
||||
shim::DataType Type;
|
||||
};
|
||||
|
||||
typedef std::vector<shim::DataType> Layout;
|
||||
|
||||
struct HeterogeneousBuffer {
|
||||
shim::Buffer Buffer;
|
||||
shim::Layout Layout;
|
||||
};
|
||||
}
|
94
python/osd/common.py
Normal file
94
python/osd/common.py
Normal file
@ -0,0 +1,94 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
class TopoError(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class OsdTypeError(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(self, message)
|
||||
|
||||
# From hbr/mesh.h
|
||||
class BoundaryMode:
|
||||
"Subdivision boundary rules for :class:`osd.Topology` construction."
|
||||
|
||||
NONE = 0
|
||||
"Boundary edges are corner verts are not processed specially."
|
||||
|
||||
EDGE_ONLY = 1
|
||||
"Boundary edges are marked infinitely sharp."
|
||||
|
||||
EDGE_AND_CORNER = 2
|
||||
'''Boundary edges are marked infinitely sharp, and vertices with
|
||||
valence=2 are marked infinitely sharp.'''
|
||||
|
||||
ALWAYS_SHARP = 3
|
||||
"Unused."
|
||||
|
||||
class Sharpness:
|
||||
'''Provides some floating-point constants that clients can
|
||||
optionally use to set sharpness.'''
|
||||
|
||||
SMOOTH = 0
|
||||
"As smooth as possible."
|
||||
|
||||
SHARP = 1
|
||||
"Moderately sharp."
|
||||
|
||||
INFINITELY_SHARP = 2
|
||||
"As sharp as possible."
|
82
python/osd/internal.h
Normal file
82
python/osd/internal.h
Normal file
@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#include <Python.h>
|
||||
#include <numpy/arrayobject.h>
|
||||
#include <common/mutex.h>
|
||||
#include <far/meshFactory.h>
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex;
|
||||
typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
|
||||
typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge;
|
||||
|
||||
struct TopologyImpl {
|
||||
OsdHbrMesh *hmesh;
|
||||
std::vector<OsdHbrFace*> faces;
|
||||
size_t numVertices;
|
||||
};
|
||||
|
||||
struct SubdividerImpl {
|
||||
OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farMesh;
|
||||
OpenSubdiv::OsdCpuComputeContext* computeContext;
|
||||
OpenSubdiv::OsdCpuVertexBuffer* vertexBuffer;
|
||||
};
|
251
python/osd/osdshim.i
Normal file
251
python/osd/osdshim.i
Normal file
@ -0,0 +1,251 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
%module shim
|
||||
|
||||
%{
|
||||
#include "subdivider.h"
|
||||
#include "topology.h"
|
||||
%}
|
||||
|
||||
%header %{
|
||||
#include <numpy/arrayobject.h>
|
||||
#include <iostream>
|
||||
|
||||
static shim::DataType
|
||||
_ShimTypeFromNumpyType(int numpyType)
|
||||
{
|
||||
using namespace std;
|
||||
switch (numpyType) {
|
||||
case PyArray_FLOAT32: return shim::float32;
|
||||
case PyArray_UINT32: return shim::uint32;
|
||||
case PyArray_INT32: return shim::int32;
|
||||
case PyArray_INT8: return shim::int8;
|
||||
case PyArray_UBYTE: return shim::uint8;
|
||||
case PyArray_VOID:
|
||||
cerr << "Expected a type but got VOID." << endl;
|
||||
abort();
|
||||
return shim::invalid;
|
||||
case PyArray_STRING:
|
||||
case PyArray_UNICODE:
|
||||
cerr << "Strings are not expected here." << endl;
|
||||
return shim::invalid;
|
||||
case PyArray_OBJECT:
|
||||
cerr << "Complex type not allowed here." << endl;
|
||||
return shim::invalid;
|
||||
}
|
||||
cerr << "Unsupported numpy type " << numpyType << endl;
|
||||
abort();
|
||||
return shim::invalid;
|
||||
}
|
||||
|
||||
static shim::DataType
|
||||
_ShimTypeFromNumpyType(PyTypeObject* item)
|
||||
{
|
||||
std::string numpyType = ((PyTypeObject*) item)->tp_name;
|
||||
if (numpyType == "numpy.float32") return shim::float32;
|
||||
if (numpyType == "numpy.uint32") return shim::uint32;
|
||||
if (numpyType == "numpy.int32") return shim::int32;
|
||||
if (numpyType == "numpy.uint8") return shim::uint8;
|
||||
std::cerr << "Unsupported numpy type " << numpyType << std::endl;
|
||||
return shim::invalid;
|
||||
}
|
||||
|
||||
static shim::Layout
|
||||
_ShimLayoutFromObject(PyObject* obj)
|
||||
{
|
||||
using namespace std;
|
||||
shim::Layout layout;
|
||||
if (!obj) {
|
||||
cerr << "Missing type.\n";
|
||||
} else if (PyArray_DescrCheck(obj)) {
|
||||
PyArray_Descr* descr = (PyArray_Descr*) obj;
|
||||
int numpyType = descr->type_num;
|
||||
if (numpyType != PyArray_VOID) {
|
||||
shim::DataType dtype = _ShimTypeFromNumpyType(numpyType);
|
||||
layout.push_back(dtype);
|
||||
} else if (PyDataType_HASFIELDS(descr)) {
|
||||
PyObject* rawTypes = PyDict_Values(descr->fields);
|
||||
Py_ssize_t count = PySequence_Size(rawTypes);
|
||||
|
||||
// Each field value is a type-offset pair. We don't honor
|
||||
// the offsets, so just extract the type and move on.
|
||||
for (Py_ssize_t i = 0; i < count; ++i) {
|
||||
PyObject* pair = PySequence_ITEM(rawTypes, i);
|
||||
PyObject* item = PySequence_ITEM(pair, 0);
|
||||
shim::Layout newTypes = _ShimLayoutFromObject(item);
|
||||
layout.insert(layout.end(), newTypes.begin(), newTypes.end());
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(pair);
|
||||
}
|
||||
|
||||
Py_DECREF(rawTypes);
|
||||
} else {
|
||||
cerr << "Please provide a record-style numpy type with fields." << endl;
|
||||
}
|
||||
} else if (PyType_Check(obj)) {
|
||||
layout.push_back( _ShimTypeFromNumpyType((PyTypeObject*) obj) );
|
||||
} else if (PySequence_Check(obj)) {
|
||||
Py_ssize_t count = PySequence_Size(obj);
|
||||
for (Py_ssize_t i = 0; i < count; ++i) {
|
||||
PyObject* item = PySequence_ITEM(obj, i);
|
||||
shim::Layout newTypes = _ShimLayoutFromObject(item);
|
||||
layout.insert(layout.end(), newTypes.begin(), newTypes.end());
|
||||
Py_DECREF(item);
|
||||
}
|
||||
} else {
|
||||
int dtype = (int) PyInt_AsLong(obj);
|
||||
if (dtype == -1) {
|
||||
cerr << "Got a " << obj->ob_type->tp_name << " but wanted a data type." << endl;
|
||||
} else if (dtype != shim::invalid) {
|
||||
layout.push_back(_ShimTypeFromNumpyType(dtype));
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%init %{
|
||||
import_array();
|
||||
%}
|
||||
|
||||
%typemap(in) const shim::HomogeneousBuffer& {
|
||||
if (!PyArray_CheckExact($input)) {
|
||||
std::cerr << "This requires a numpy array." << std::endl;
|
||||
}
|
||||
$1 = new shim::HomogeneousBuffer();
|
||||
int byteCount = PyArray_NBYTES($input);
|
||||
unsigned char* begin = (unsigned char*) PyArray_BYTES($input);
|
||||
unsigned char* end = begin + byteCount;
|
||||
$1->Buffer.assign(begin, end);
|
||||
int dtype = PyArray_TYPE($input);
|
||||
$1->Type = _ShimTypeFromNumpyType(dtype);
|
||||
}
|
||||
|
||||
%typemap(in) shim::Layout {
|
||||
$1 = _ShimLayoutFromObject($input);
|
||||
}
|
||||
|
||||
%typemap(in) shim::DataType {
|
||||
using namespace std;
|
||||
shim::Layout layout = _ShimLayoutFromObject($input);
|
||||
if (layout.size() < 1) {
|
||||
cerr << "Can't convert PyObject " << $input << " to a shim data type." << endl;
|
||||
$1 = shim::invalid;
|
||||
} else if (layout.size() > 1) {
|
||||
cerr << "Complex data type not allowed here." << endl;
|
||||
$1 = shim::invalid;
|
||||
} else {
|
||||
$1 = layout[0];
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(in) const shim::HeterogeneousBuffer& {
|
||||
using namespace std;
|
||||
if (!PyArray_CheckExact($input)) {
|
||||
cerr << "This requires a numpy array." << endl;
|
||||
}
|
||||
$1 = new shim::HeterogeneousBuffer();
|
||||
int byteCount = PyArray_NBYTES($input);
|
||||
unsigned char* begin = (unsigned char*) PyArray_BYTES($input);
|
||||
unsigned char* end = begin + byteCount;
|
||||
|
||||
$1->Buffer.assign(begin, end);
|
||||
$1->Layout = _ShimLayoutFromObject((PyObject*) PyArray_DESCR($input));
|
||||
}
|
||||
|
||||
%typemap(in) shim::Buffer* INOUT {
|
||||
$1 = new shim::Buffer();
|
||||
}
|
||||
|
||||
%typemap(argout) shim::Buffer* INOUT {
|
||||
using namespace std;
|
||||
PyObject* obj = (PyObject*) PyArray_DESCR($input);
|
||||
shim::Layout layout = _ShimLayoutFromObject(obj);
|
||||
if (layout.size() == 0) {
|
||||
cerr << "Unknown type for Buffer processing." << endl;
|
||||
} else if (layout[0] == shim::float32) {
|
||||
npy_intp numFloats = (npy_intp) ($1->size() / sizeof(float));
|
||||
float* ptrFloats = (float*) &(*$1)[0];
|
||||
|
||||
$result = PyArray_SimpleNew(1, &numFloats, PyArray_FLOAT32);
|
||||
memcpy(PyArray_BYTES($result), ptrFloats, $1->size());
|
||||
|
||||
// SimpleNewFromData would avoid a copy but we'd need to keep
|
||||
// the buffer around in our shim class. It's not
|
||||
// impossible...
|
||||
//$result = PyArray_SimpleNewFromData(
|
||||
// 1, &numFloats, PyArray_FLOAT, (void*) ptrFloats);
|
||||
|
||||
} else if (layout[0] == shim::uint32) {
|
||||
npy_intp numInts = (npy_intp) ($1->size() / sizeof(unsigned int));
|
||||
unsigned int* ptrInts = (unsigned int*) &(*$1)[0];
|
||||
$result = PyArray_SimpleNew(1, &numInts, PyArray_UINT32);
|
||||
memcpy(PyArray_BYTES($result), ptrInts, $1->size());
|
||||
} else {
|
||||
cerr << layout[0] << " is not an understood shim type."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(freearg) shim::Buffer* INOUT {
|
||||
delete $1;
|
||||
}
|
||||
|
||||
%include "subdivider.h"
|
||||
%include "topology.h"
|
106
python/osd/subdivider.cpp
Normal file
106
python/osd/subdivider.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "internal.h"
|
||||
#include "subdivider.h"
|
||||
#include "topology.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace shim;
|
||||
|
||||
OpenSubdiv::OsdCpuComputeController* g_osdComputeController = 0;
|
||||
|
||||
shim::Subdivider::Subdivider(
|
||||
const Topology& topo,
|
||||
Layout refinedLayout,
|
||||
DataType refinedIndexType,
|
||||
int subdivisionLevels)
|
||||
{
|
||||
self = new SubdividerImpl();
|
||||
|
||||
if (!g_osdComputeController) {
|
||||
g_osdComputeController = new OpenSubdiv::OsdCpuComputeController();
|
||||
}
|
||||
|
||||
size_t numFloatsPerVertex = 0;
|
||||
Layout::const_iterator it;
|
||||
for (it = refinedLayout.begin(); it != refinedLayout.end(); ++it) {
|
||||
if (*it != float32) {
|
||||
cerr << "Unsupported vertex type." << endl;
|
||||
break;
|
||||
}
|
||||
++numFloatsPerVertex;
|
||||
}
|
||||
OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(
|
||||
topo.self->hmesh,
|
||||
subdivisionLevels);
|
||||
self->farMesh = meshFactory.Create();
|
||||
self->computeContext = OpenSubdiv::OsdCpuComputeContext::Create(
|
||||
self->farMesh);
|
||||
|
||||
self->vertexBuffer = OpenSubdiv::OsdCpuVertexBuffer::Create(
|
||||
numFloatsPerVertex, self->farMesh->GetNumVertices());
|
||||
}
|
||||
|
||||
shim::Subdivider::~Subdivider()
|
||||
{
|
||||
delete self->computeContext;
|
||||
delete self->farMesh;
|
||||
delete self->vertexBuffer;
|
||||
delete self;
|
||||
}
|
||||
|
||||
void
|
||||
shim::Subdivider::setCoarseVertices(const HeterogeneousBuffer& cage)
|
||||
{
|
||||
float* pFloats = (float*) &cage.Buffer[0];
|
||||
int numFloats = cage.Buffer.size() / sizeof(float);
|
||||
self->vertexBuffer->UpdateData(pFloats, numFloats);
|
||||
}
|
||||
|
||||
void
|
||||
shim::Subdivider::refine()
|
||||
{
|
||||
g_osdComputeController->Refine(self->computeContext, self->vertexBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
shim::Subdivider::getRefinedVertices(Buffer* refinedVertices)
|
||||
{
|
||||
float* pFloats = self->vertexBuffer->BindCpuBuffer();
|
||||
|
||||
int numFloats = self->vertexBuffer->GetNumElements() *
|
||||
self->vertexBuffer->GetNumVertices();
|
||||
|
||||
unsigned char* srcBegin = (unsigned char*) pFloats;
|
||||
unsigned char* srcEnd = srcBegin + numFloats * 4;
|
||||
refinedVertices->assign(srcBegin, srcEnd);
|
||||
}
|
||||
|
||||
void
|
||||
shim::Subdivider::getRefinedQuads(Buffer* refinedQuads)
|
||||
{
|
||||
OpenSubdiv::FarPatchTables const * patchTables =
|
||||
self->farMesh->GetPatchTables();
|
||||
|
||||
if (patchTables) {
|
||||
cerr << "Feature adaptive not supported" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *tables =
|
||||
self->farMesh->GetSubdivisionTables();
|
||||
|
||||
bool loop = dynamic_cast<const OpenSubdiv::FarLoopSubdivisionTables<
|
||||
OpenSubdiv::OsdVertex>*>(tables);
|
||||
|
||||
if (loop) {
|
||||
cerr << "loop subdivision not supported" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int level = tables->GetMaxLevel();
|
||||
const std::vector<int> &indices = self->farMesh->GetFaceVertices(level-1);
|
||||
int numInts = (int) indices.size();
|
||||
|
||||
unsigned char* srcBegin = (unsigned char*) &indices[0];
|
||||
unsigned char* srcEnd = srcBegin + numInts * 4;
|
||||
refinedQuads->assign(srcBegin, srcEnd);
|
||||
}
|
89
python/osd/subdivider.h
Normal file
89
python/osd/subdivider.h
Normal file
@ -0,0 +1,89 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "buffer.h"
|
||||
|
||||
struct SubdividerImpl;
|
||||
|
||||
namespace shim {
|
||||
|
||||
class Topology;
|
||||
|
||||
class Subdivider {
|
||||
public:
|
||||
|
||||
Subdivider(
|
||||
const Topology& topo,
|
||||
shim::Layout refinedLayout,
|
||||
shim::DataType refinedIndexType,
|
||||
int subdivisionLevels);
|
||||
~Subdivider();
|
||||
|
||||
void setCoarseVertices(const shim::HeterogeneousBuffer& cage);
|
||||
void refine();
|
||||
|
||||
// These argument names must be INOUT to inform SWIG that
|
||||
// they're mutable:
|
||||
void getRefinedVertices(shim::Buffer* INOUT);
|
||||
void getRefinedQuads(shim::Buffer* INOUT);
|
||||
|
||||
private:
|
||||
SubdividerImpl* self;
|
||||
};
|
||||
|
||||
}
|
149
python/osd/subdivider.py
Normal file
149
python/osd/subdivider.py
Normal file
@ -0,0 +1,149 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from osd import *
|
||||
import shim, numpy
|
||||
|
||||
class Subdivider(object):
|
||||
'''Wraps a frozen :class:`osd.Topology` object and efficiently
|
||||
subdivides it into triangles.
|
||||
|
||||
On creation, the :class:`Subdivider` is locked to an immutable,
|
||||
finalized :class:`osd.Topology` object. However, actual
|
||||
subdivision computation can be requested repeatedly using dynamic
|
||||
per-vertex data.
|
||||
|
||||
:param topo: Finalized mesh topology.
|
||||
:type topo: :class:`osd.Topology`
|
||||
:param vertexLayout: Describes the data structure composing each vertex.
|
||||
:type vertexLayout: record-style numpy data type_ object
|
||||
:param indexType: Integer type for the indices returned from `getRefinedTopology`.
|
||||
:type indexType: single numpy type_
|
||||
:param levels: Number of subdivisions.
|
||||
:type levels: integer
|
||||
|
||||
.. note:: In the current implementation, ``vertexLayout`` must be
|
||||
composed of ``numpy.float32``, and ``indexType`` must be
|
||||
``numpy.uint32``.
|
||||
|
||||
.. _types: http://docs.scipy.org/doc/numpy/user/basics.types.html
|
||||
.. _type: http://docs.scipy.org/doc/numpy/user/basics.types.html
|
||||
'''
|
||||
|
||||
def __init__(self, topo, vertexLayout, indexType, levels):
|
||||
if levels < 2:
|
||||
raise TopoError("Subdivision levels must be 2 or greater")
|
||||
if type(vertexLayout) != numpy.dtype:
|
||||
vertexLayout = numpy.dtype(vertexLayout)
|
||||
self.vertexLayout = vertexLayout
|
||||
self.indexType = indexType
|
||||
self.levels = levels
|
||||
self.shim = shim.Subdivider(topo.shim, vertexLayout, indexType, levels)
|
||||
|
||||
# Calls UpdateData on the vertexBuffer.
|
||||
def setCoarseVertices(self, coarseVerts, listType = None):
|
||||
'''Pushes a new set of coarse verts to the mesh without
|
||||
changing topology.
|
||||
|
||||
If a numpy array is supplied for ``coarseVerts``, its
|
||||
``dtype`` must be castable (via view_) to the ``vertexLayout``
|
||||
of the :class:`Subdivider`.
|
||||
|
||||
If a Python list is supplied for ``coarseVerts``, the client
|
||||
must also supply the ``listType`` argument to specify the
|
||||
numpy type of the incoming array before it gets cast to
|
||||
``vertexLayout``.
|
||||
|
||||
.. _view: http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.ndarray.view.html
|
||||
'''
|
||||
if type(coarseVerts) is not numpy.ndarray:
|
||||
if not listType:
|
||||
raise TopoError("listType must be supplied")
|
||||
coarseVerts = numpy.array(coarseVerts, listType)
|
||||
coarseVerts = coarseVerts.view(self.vertexLayout)
|
||||
self.shim.setCoarseVertices(coarseVerts)
|
||||
|
||||
# Calls Refine on the compute controller, passing it the compute
|
||||
# context and vertexBuffer.
|
||||
def refine(self):
|
||||
'''Performs the actual subdivision work.'''
|
||||
self.shim.refine()
|
||||
|
||||
# Calls the strangely-named "BindCpuBuffer" on the
|
||||
# OsdCpuVertexBuffer to get back a float*
|
||||
def getRefinedVertices(self):
|
||||
'''Returns a numpy array representing the vertex data in the
|
||||
subdivided mesh.
|
||||
|
||||
The data is returned in the format specified by the client
|
||||
when instancing the subdivider (``vertexLayout``).
|
||||
'''
|
||||
empty = numpy.empty(0, self.vertexLayout)
|
||||
return self.shim.getRefinedVertices(empty)
|
||||
|
||||
def getRefinedQuads(self):
|
||||
'''Returns a numpy array representing the vertex indices of each quad in
|
||||
subdivided mesh.
|
||||
|
||||
The data is returned in the format specified by the client
|
||||
when instancing the subdivider (``indexType``).
|
||||
'''
|
||||
empty = numpy.empty(0, self.indexType)
|
||||
return self.shim.getRefinedQuads(empty)
|
||||
|
||||
def __del__(self):
|
||||
pass
|
252
python/osd/topology.cpp
Normal file
252
python/osd/topology.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#include "internal.h"
|
||||
#include "topology.h"
|
||||
|
||||
using namespace shim;
|
||||
using namespace std;
|
||||
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||
|
||||
shim::Topology::Topology(
|
||||
const HomogeneousBuffer& indices, const HomogeneousBuffer& valences)
|
||||
{
|
||||
self = new TopologyImpl();
|
||||
self->hmesh = new OsdHbrMesh(&_catmark);
|
||||
|
||||
size_t maxIndex = 0;
|
||||
size_t byteCount = indices.Buffer.size();
|
||||
|
||||
switch (indices.Type) {
|
||||
case int32: {
|
||||
const int *d = (const int*) &indices.Buffer[0];
|
||||
maxIndex = (size_t) *max_element(d, d + byteCount / 4);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cerr << "Unsupported index type " << indices.Type << endl;
|
||||
};
|
||||
|
||||
size_t maxValence = 0;
|
||||
switch (valences.Type) {
|
||||
case uint8: {
|
||||
const unsigned char *d = (const unsigned char*) &valences.Buffer[0];
|
||||
maxValence = (size_t) *max_element(d, d + byteCount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cerr << "Unsupported valence type " << valences.Type << endl;
|
||||
};
|
||||
|
||||
self->numVertices = 1 + (int) maxIndex;
|
||||
OpenSubdiv::OsdVertex vert;
|
||||
for (size_t i = 0; i < self->numVertices; ++i) {
|
||||
OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex>* pVert =
|
||||
self->hmesh->NewVertex((int) i, vert);
|
||||
if (!pVert) {
|
||||
cerr << "Error: Unable to create vertex " << i << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int* pIndices = (int*) &indices.Buffer[0];
|
||||
unsigned char* pValence = (unsigned char*) &valences.Buffer[0];
|
||||
size_t valenceCount = valences.Buffer.size();
|
||||
while (valenceCount--) {
|
||||
int vertsPerFace = *pValence;
|
||||
OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex>* pFace =
|
||||
self->hmesh->NewFace(vertsPerFace, pIndices, 0);
|
||||
if (!pFace) {
|
||||
cerr << "Error: Unable to create face (valence = "
|
||||
<< vertsPerFace << ")\n";
|
||||
}
|
||||
pIndices += vertsPerFace;
|
||||
++pValence;
|
||||
}
|
||||
|
||||
self->hmesh->GetFaces(back_inserter(self->faces));
|
||||
}
|
||||
|
||||
shim::Topology::~Topology()
|
||||
{
|
||||
delete self->hmesh;
|
||||
delete self;
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::copyAnnotationsFrom(const Topology& topo)
|
||||
{
|
||||
int vertexCount = getNumVertices();
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
float s = topo.getVertexSharpness(i);
|
||||
setVertexSharpness(i, s);
|
||||
}
|
||||
|
||||
int faceCount = getNumFaces();
|
||||
for (int faceIndex = 0; faceIndex < faceCount; ++faceIndex) {
|
||||
int numEdges = topo.getNumEdges(faceIndex);
|
||||
for (int edgeIndex = 0; edgeIndex < numEdges; ++edgeIndex) {
|
||||
float s = topo.getEdgeSharpness(faceIndex, edgeIndex);
|
||||
setEdgeSharpness(faceIndex, edgeIndex, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::finalize()
|
||||
{
|
||||
self->hmesh->Finish();
|
||||
}
|
||||
|
||||
BoundaryMode::e
|
||||
shim::Topology::getBoundaryMode() const
|
||||
{
|
||||
OsdHbrMesh::InterpolateBoundaryMethod bm =
|
||||
self->hmesh->GetInterpolateBoundaryMethod();
|
||||
switch (bm) {
|
||||
case OsdHbrMesh::k_InterpolateBoundaryNone:
|
||||
return BoundaryMode::NONE;
|
||||
case OsdHbrMesh::k_InterpolateBoundaryEdgeOnly:
|
||||
return BoundaryMode::EDGE_ONLY;
|
||||
case OsdHbrMesh::k_InterpolateBoundaryEdgeAndCorner:
|
||||
return BoundaryMode::EDGE_AND_CORNER;
|
||||
case OsdHbrMesh::k_InterpolateBoundaryAlwaysSharp:
|
||||
return BoundaryMode::ALWAYS_SHARP;
|
||||
}
|
||||
throw("Bad interpolation method.");
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::setBoundaryMode(BoundaryMode::e bm)
|
||||
{
|
||||
switch (bm) {
|
||||
case BoundaryMode::NONE:
|
||||
self->hmesh->SetInterpolateBoundaryMethod(
|
||||
OsdHbrMesh::k_InterpolateBoundaryNone);
|
||||
break;
|
||||
case BoundaryMode::EDGE_ONLY:
|
||||
self->hmesh->SetInterpolateBoundaryMethod(
|
||||
OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
|
||||
break;
|
||||
case BoundaryMode::EDGE_AND_CORNER:
|
||||
self->hmesh->SetInterpolateBoundaryMethod(
|
||||
OsdHbrMesh::k_InterpolateBoundaryEdgeAndCorner);
|
||||
break;
|
||||
case BoundaryMode::ALWAYS_SHARP:
|
||||
self->hmesh->SetInterpolateBoundaryMethod(
|
||||
OsdHbrMesh::k_InterpolateBoundaryAlwaysSharp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
shim::Topology::getNumVertices() const
|
||||
{
|
||||
return self->numVertices;
|
||||
}
|
||||
|
||||
float
|
||||
shim::Topology::getVertexSharpness(int vertex) const
|
||||
{
|
||||
return self->hmesh->GetVertex(vertex)->GetSharpness();
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::setVertexSharpness(int vertex, float sharpness)
|
||||
{
|
||||
self->hmesh->GetVertex(vertex)->SetSharpness(sharpness);
|
||||
}
|
||||
|
||||
int
|
||||
shim::Topology::getNumFaces() const
|
||||
{
|
||||
return self->hmesh->GetNumFaces();
|
||||
}
|
||||
|
||||
bool
|
||||
shim::Topology::getFaceHole(int faceIndex) const
|
||||
{
|
||||
return self->faces[faceIndex]->IsHole();
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::setFaceHole(int faceIndex, bool isHole)
|
||||
{
|
||||
if (!isHole) {
|
||||
cerr << "Unsetting holeness is not supported." << endl;
|
||||
return;
|
||||
}
|
||||
self->faces[faceIndex]->SetHole();
|
||||
}
|
||||
|
||||
int
|
||||
shim::Topology::getNumEdges(int faceIndex) const
|
||||
{
|
||||
return self->faces[faceIndex]->GetNumVertices();
|
||||
}
|
||||
|
||||
float
|
||||
shim::Topology::getEdgeSharpness(int faceIndex, int edgeIndex) const
|
||||
{
|
||||
return self->faces[faceIndex]->GetEdge(edgeIndex)->GetSharpness();
|
||||
}
|
||||
|
||||
void
|
||||
shim::Topology::setEdgeSharpness(int faceIndex, int edgeIndex, float sharpness)
|
||||
{
|
||||
self->faces[faceIndex]->GetEdge(edgeIndex)->SetSharpness(sharpness);
|
||||
}
|
106
python/osd/topology.h
Normal file
106
python/osd/topology.h
Normal file
@ -0,0 +1,106 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "buffer.h"
|
||||
|
||||
struct TopologyImpl;
|
||||
|
||||
namespace shim {
|
||||
|
||||
struct BoundaryMode {
|
||||
enum e {
|
||||
NONE,
|
||||
EDGE_ONLY,
|
||||
EDGE_AND_CORNER,
|
||||
ALWAYS_SHARP,
|
||||
};
|
||||
};
|
||||
|
||||
class Subdivider;
|
||||
|
||||
class Topology {
|
||||
public:
|
||||
Topology(const shim::HomogeneousBuffer& indices,
|
||||
const shim::HomogeneousBuffer& valences);
|
||||
~Topology();
|
||||
|
||||
void copyAnnotationsFrom(const Topology& topo);
|
||||
|
||||
void finalize();
|
||||
|
||||
BoundaryMode::e getBoundaryMode() const;
|
||||
void setBoundaryMode(BoundaryMode::e bm);
|
||||
|
||||
int getNumVertices() const;
|
||||
float getVertexSharpness(int vertex) const;
|
||||
void setVertexSharpness(int vertex, float sharpness);
|
||||
|
||||
int getNumFaces() const;
|
||||
bool getFaceHole(int face) const;
|
||||
void setFaceHole(int face, bool isHole);
|
||||
|
||||
int getNumEdges(int face) const;
|
||||
float getEdgeSharpness(int face, int edge) const;
|
||||
void setEdgeSharpness(int face, int edge, float sharpness);
|
||||
|
||||
private:
|
||||
TopologyImpl *self;
|
||||
friend class shim::Subdivider;
|
||||
};
|
||||
|
||||
}
|
209
python/osd/topology.py
Normal file
209
python/osd/topology.py
Normal file
@ -0,0 +1,209 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from common import *
|
||||
from adapters import *
|
||||
|
||||
import numpy as np
|
||||
import shim
|
||||
import itertools
|
||||
|
||||
class Topology(object):
|
||||
'''Represents an abstract graph of connected polygons.
|
||||
|
||||
A :class:`Topology` object contains only connectivity information;
|
||||
it does not contain any coordinate data. Instances are simply
|
||||
populated, finalized, and submitted to an instance of
|
||||
:class:`osd.Subdivider`.
|
||||
|
||||
The constructor can take a single two-dimensional numpy array
|
||||
(``indices``), or two one-dimensional numpy arrays
|
||||
(``indices`` and ``valences``). If every face has the same
|
||||
valence, clients can pass in a single integer for
|
||||
``valences``.
|
||||
|
||||
If desired, simple Python lists can be used in lieu of numpy
|
||||
arrays.
|
||||
|
||||
.. note:: Input data is always copied to internal storage,
|
||||
rather than referenced.
|
||||
|
||||
:param indices: Defines each face as a list of vertex indices.
|
||||
:type indices: list or numpy array
|
||||
:param valences: If ``indices`` is 2D, this should be :const:`None`. If every face has the same valence, this can be a single integer. Otherwise this is a list of integers that specify the valence of each face.
|
||||
:type valences: list, number, or numpy array
|
||||
'''
|
||||
|
||||
def __init__(self, indices, valences = None):
|
||||
indices, valences = _flatten_args(indices, valences)
|
||||
valences = _process_valences(indices, valences)
|
||||
_check_topology(indices, valences)
|
||||
|
||||
self.indices = np.array(indices, 'int32')
|
||||
self.valences = np.array(valences, 'uint8')
|
||||
self.shim = shim.Topology(self.indices, self.valences)
|
||||
self.boundaryMode = BoundaryMode.EDGE_ONLY
|
||||
self._vertexListAdapter = VertexListAdapter(self.shim)
|
||||
self._faceListAdapter = FaceListAdapter(self.shim)
|
||||
|
||||
def reset(self):
|
||||
'''Un-finalizes the mesh to allow adjustment of sharpness and
|
||||
custom data.
|
||||
|
||||
This is a costly operation since it effectively recreates the
|
||||
HBR mesh.
|
||||
'''
|
||||
topo = shim.Topology(self.indices, self.valences)
|
||||
topo.copyAnnotationsFrom(self.shim)
|
||||
self._vertexListAdapter = VertexListAdapter(topo)
|
||||
self._faceListAdapter = FaceListAdapter(topo)
|
||||
self.shim = topo
|
||||
|
||||
@property
|
||||
def boundaryMode(self):
|
||||
'''Gets or sets the boundary interpolation method for this
|
||||
mesh to one of the values defined in
|
||||
:class:`osd.BoundaryMode`.
|
||||
'''
|
||||
return self.shim.getBoundaryMode()
|
||||
|
||||
@boundaryMode.setter
|
||||
def boundaryMode(self, value):
|
||||
self.shim.setBoundaryMode(value)
|
||||
|
||||
@property
|
||||
def vertices(self):
|
||||
'''Pythonic read/write access to special attributes (e.g., sharpness) in
|
||||
the HBR mesh.
|
||||
|
||||
This property is not an actual list-of-things; it's a short-lived
|
||||
adapter that allows clients to use Pythonic properties::
|
||||
|
||||
topo = osd.Topology(faces)
|
||||
topo.vertices[2].sharpness = 1.3
|
||||
|
||||
'''
|
||||
return self._vertexListAdapter
|
||||
|
||||
@property
|
||||
def faces(self):
|
||||
'''Pythonic read/write access to face data and edge data in the HBR mesh.
|
||||
|
||||
This property is not an actual list-of-things; it's a short-lived
|
||||
adapter that allows clients to use Pythonic properties::
|
||||
|
||||
topo = osd.Topology(faces)
|
||||
topo.faces[1].edges[0].sharpness = 0.6
|
||||
|
||||
'''
|
||||
return self._faceListAdapter
|
||||
|
||||
def finalize(self):
|
||||
'''Calls finish on the HBR mesh, thus preparing it for subdivision.'''
|
||||
self.shim.finalize()
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
# Checks that no valence is less than 3, and that the sum of all valences
|
||||
# equal to the # of indices.
|
||||
def _check_topology(indices, valences):
|
||||
acc = 0
|
||||
for v in valences:
|
||||
if v < 3:
|
||||
raise TopoError("all valences must be 3 or greater")
|
||||
acc = acc + v
|
||||
if len(indices) != acc:
|
||||
msg = "sum of valences ({0}) isn't equal to the number of indices ({1})"
|
||||
raise TopoError(msg.format(acc, len(indices)))
|
||||
|
||||
# Given a list-of-lists, returns a list pair where the first list has
|
||||
# values and the second list has the original counts.
|
||||
def _flatten(faces):
|
||||
flattened = list(itertools.chain(*faces))
|
||||
lengths = [len(face) for face in faces]
|
||||
return flattened, lengths
|
||||
|
||||
# If indices is two-dimensional, splits it into two lists.
|
||||
# Otherwise returns the lists unchanged.
|
||||
def _flatten_args(indices, valences):
|
||||
try:
|
||||
flattened, lengths = _flatten(indices)
|
||||
if valences is not None:
|
||||
raise OsdTypeError(
|
||||
"valences must be None if indices is two-dimensional")
|
||||
return (flattened, lengths)
|
||||
except TypeError:
|
||||
if valences is None:
|
||||
raise OsdTypeError(
|
||||
"valences must be provided if indices is one-dimensional")
|
||||
return (indices, valences)
|
||||
|
||||
# If valences is a scalar, returns a list of valences.
|
||||
# Otherwise returns the original valence list.
|
||||
def _process_valences(indices, valences):
|
||||
try:
|
||||
v = int(valences)
|
||||
faceCount = len(indices) / v
|
||||
if len(indices) % v is not 0:
|
||||
msg = "Scalar provided for valences argument ({0}) that " \
|
||||
"does evenly divide the number of indices ({1})"
|
||||
raise OsdTypeError(msg.format(len(indices), v))
|
||||
valences = [v] * faceCount
|
||||
except TypeError:
|
||||
pass
|
||||
return valences
|
171
python/setup.py
Executable file
171
python/setup.py
Executable file
@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from distutils.core import setup, Command, Extension
|
||||
import numpy
|
||||
import os, os.path
|
||||
|
||||
np_include_dir = numpy.get_include()
|
||||
np_library_dir = os.path.join(np_include_dir, '../lib')
|
||||
osd_include_dirs = ['../opensubdiv', '../regression']
|
||||
|
||||
def import_build_folder():
|
||||
import sys, distutils.util, os.path
|
||||
build_dir = "build/lib.{0}-{1}.{2}".format(
|
||||
distutils.util.get_platform(),
|
||||
*sys.version_info)
|
||||
if not os.path.exists(build_dir):
|
||||
print "Folder does not exist: " + build_dir
|
||||
print "Perhaps you need to run:"
|
||||
print " python setup.py build"
|
||||
else:
|
||||
sys.path.insert(0, build_dir)
|
||||
|
||||
osd_shim = Extension(
|
||||
'osd._shim',
|
||||
runtime_library_dirs = [osd_lib_path],
|
||||
include_dirs = osd_include_dirs,
|
||||
library_dirs = ['../build/lib', np_library_dir],
|
||||
libraries = ['osdCPU', 'npymath'],
|
||||
swig_opts = ['-c++'],
|
||||
sources = [
|
||||
'osd/osdshim.i',
|
||||
'osd/subdivider.cpp',
|
||||
'osd/topology.cpp'])
|
||||
|
||||
osd_shim.extra_compile_args = \
|
||||
["-Wno-unused-function"]
|
||||
|
||||
os.environ['ARCHFLAGS'] = '-arch ' + os.uname()[4]
|
||||
|
||||
class TestCommand(Command):
|
||||
description = "runs unit tests"
|
||||
user_options = []
|
||||
def initialize_options(self):
|
||||
pass
|
||||
def finalize_options(self):
|
||||
pass
|
||||
def run(self):
|
||||
import_build_folder()
|
||||
import unittest, test
|
||||
suite = unittest.defaultTestLoader.loadTestsFromModule(test)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
class DemoCommand(Command):
|
||||
description = "runs a little PyQt demo of the Python wrapper"
|
||||
user_options = []
|
||||
def initialize_options(self):
|
||||
pass
|
||||
def finalize_options(self):
|
||||
pass
|
||||
def run(self):
|
||||
import_build_folder()
|
||||
import demo
|
||||
demo.main()
|
||||
|
||||
class InteractiveCommand(Command):
|
||||
description = "runs a little PyQt demo of the Python wrapper"
|
||||
user_options = []
|
||||
def initialize_options(self):
|
||||
pass
|
||||
def finalize_options(self):
|
||||
pass
|
||||
def run(self):
|
||||
import_build_folder()
|
||||
import demo
|
||||
demo.interactive()
|
||||
|
||||
class DocCommand(Command):
|
||||
description = "Generate HTML documentation with Sphinx"
|
||||
user_options = []
|
||||
def initialize_options(self):
|
||||
pass
|
||||
def finalize_options(self):
|
||||
pass
|
||||
def run(self):
|
||||
import os
|
||||
os.chdir('doc')
|
||||
os.system('make clean html')
|
||||
|
||||
class BuildCommand(build):
|
||||
description = "Builds the Python bindings"
|
||||
user_options = [
|
||||
('osddir=', 'o',
|
||||
'directory that contains libosdCPU.a etc')]
|
||||
def initialize_options(self):
|
||||
self.osddir = None
|
||||
def finalize_options(self):
|
||||
if self.osddir is None:
|
||||
self.osddir = '../build/lib'
|
||||
def run(self):
|
||||
build.run(self)
|
||||
|
||||
setup(name = "OpenSubdiv",
|
||||
version = "0.1",
|
||||
packages = ['osd'],
|
||||
author = 'Pixar Animation Studios',
|
||||
cmdclass = {
|
||||
'build': BuildCommand,
|
||||
'test': TestCommand,
|
||||
'doc': DocCommand,
|
||||
'interactive': InteractiveCommand,
|
||||
'demo': DemoCommand},
|
||||
include_dirs = [np_include_dir],
|
||||
ext_modules = [osd_shim],
|
||||
description = 'Python Bindings to the Pixar Subdivision Library')
|
58
python/test/__init__.py
Normal file
58
python/test/__init__.py
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
from simple import *
|
197
python/test/simple.py
Executable file
197
python/test/simple.py
Executable file
@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
import numpy as np
|
||||
import unittest, sys
|
||||
import osd
|
||||
|
||||
# Topology of a cube.
|
||||
faces = [ (0,1,3,2),
|
||||
(2,3,5,4),
|
||||
(4,5,7,6),
|
||||
(6,7,1,0),
|
||||
(1,7,5,3),
|
||||
(6,0,2,4) ]
|
||||
|
||||
# Vertex positions and "temperature" as an example of a custom
|
||||
# attribute.
|
||||
verts = [ 0.000000, -1.414214, 1.000000, 71,
|
||||
1.414214, 0.000000, 1.000000, 82,
|
||||
-1.414214, 0.000000, 1.000000, 95,
|
||||
0.000000, 1.414214, 1.000000, 100,
|
||||
-1.414214, 0.000000, -1.000000, 63,
|
||||
0.000000, 1.414214, -1.000000, 77,
|
||||
0.000000, -1.414214, -1.000000, 82,
|
||||
1.414214, 0.000000, -1.000000, 32 ]
|
||||
|
||||
dtype = [('Px', np.float32),
|
||||
('Py', np.float32),
|
||||
('Pz', np.float32),
|
||||
('temperature', np.float32)]
|
||||
|
||||
class SimpleTest(unittest.TestCase):
|
||||
|
||||
def test_usage(self):
|
||||
mesh = osd.Topology(faces)
|
||||
mesh.boundaryMode = osd.BoundaryMode.EDGE_ONLY
|
||||
|
||||
mesh.vertices[0].sharpness = 2.7
|
||||
self.assertAlmostEqual(mesh.vertices[0].sharpness, 2.7)
|
||||
|
||||
self.assertEqual(len(mesh.vertices), len(verts) / len(dtype))
|
||||
self.assertEqual(len(mesh.faces), len(faces))
|
||||
self.assertEqual(len(mesh.faces[0].edges), len(faces[0]))
|
||||
|
||||
mesh.finalize()
|
||||
|
||||
subdivider = osd.Subdivider(
|
||||
mesh,
|
||||
vertexLayout = dtype,
|
||||
indexType = np.uint32,
|
||||
levels = 4)
|
||||
|
||||
subdivider.setCoarseVertices(verts, np.float32)
|
||||
subdivider.refine()
|
||||
|
||||
numQuads = len(subdivider.getRefinedQuads()) / 4
|
||||
numVerts = len(subdivider.getRefinedVertices()) / len(dtype)
|
||||
|
||||
self.assertEqual(numQuads, 1536, "Unexpected number of refined quads")
|
||||
self.assertEqual(numVerts, 2056, "Unexpected number of refined verts")
|
||||
|
||||
# For now, disable the leak test by prepending "do_not_".
|
||||
def do_not_test_leaks(self):
|
||||
self.test_usage()
|
||||
start = _get_heap_usage()
|
||||
history = []
|
||||
for i in xrange(1024):
|
||||
self.test_usage()
|
||||
if ((i+1) % 256) == 0:
|
||||
history.append(_get_heap_usage() - start)
|
||||
print str(history[-1]) + "...",
|
||||
sys.stdout.flush()
|
||||
print
|
||||
total = 0
|
||||
for i in xrange(1, len(history)):
|
||||
delta = history[i] - history[i - 1]
|
||||
if delta <= 0:
|
||||
return
|
||||
total = total + delta
|
||||
avg = total / (len(history) - 1)
|
||||
self.fail("Memory usage is strictly increasing ({0}).".format(avg))
|
||||
|
||||
def test_Topology_creation(self):
|
||||
|
||||
# Input data
|
||||
indices, valences = _flatten(faces)
|
||||
|
||||
# Native list-of-lists, constant valence:
|
||||
mesh = osd.Topology(faces)
|
||||
self.assert_(mesh,
|
||||
"Unable to construct Topology object from a list-of-lists")
|
||||
|
||||
# Native list, constant valence:
|
||||
mesh = osd.Topology(indices, 4)
|
||||
self.assert_(mesh,
|
||||
"Unable to construct Topology object from a list")
|
||||
|
||||
# Native list-of-lists, variable valence:
|
||||
faces2 = faces + [(8,9,10)]
|
||||
mesh = osd.Topology(faces2)
|
||||
self.assert_(mesh,
|
||||
"Unable to construct Topology object from a list of "
|
||||
"variable-sized lists")
|
||||
|
||||
# Two-dimensional numpy array:
|
||||
numpyFaces = np.array(indices, 'uint16').reshape(-1, 4)
|
||||
mesh = osd.Topology(numpyFaces)
|
||||
self.assert_(mesh,
|
||||
"Unable to construct Topology object from a "
|
||||
"two-dimensional numpy array")
|
||||
|
||||
# Native index list and valence list:
|
||||
mesh = osd.Topology(indices, valences)
|
||||
self.assert_(mesh)
|
||||
|
||||
# Numpy index list and valence list:
|
||||
indices = np.array(indices, 'uint16')
|
||||
valences = np.array(valences, 'uint8')
|
||||
mesh = osd.Topology(indices, valences)
|
||||
self.assert_(mesh)
|
||||
|
||||
# Ensure various topology checks
|
||||
self.assertRaises(osd.OsdTypeError, osd.Topology, indices, None)
|
||||
self.assertRaises(osd.OsdTypeError, osd.Topology, faces, valences)
|
||||
faces2 = faces + [(8,9)]
|
||||
self.assertRaises(osd.TopoError, osd.Topology, faces2)
|
||||
valences2 = valences + [3]
|
||||
self.assertRaises(osd.TopoError, osd.Topology, indices, valences2)
|
||||
|
||||
def _get_heap_usage():
|
||||
import resource
|
||||
return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
||||
|
||||
def _flatten(faces):
|
||||
import itertools
|
||||
flattened = list(itertools.chain(*faces))
|
||||
lengths = [len(face) for face in faces]
|
||||
return flattened, lengths
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user