diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..a4f7391
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,14 @@
+
+
+## Description
+
+
+## Motivation and Context
+
+
+
+## Checklist:
+
+
+- [ ] The changes introduced by this pull request are covered by existing or newly introduced tests.
+- [ ] I have updated the [changelog](https://github.com/janbridley/svg3d/blob/main/changelog.md).
diff --git a/.github/workflows/pypi-test-and-publish.yaml b/.github/workflows/pypi-test-and-publish.yaml
new file mode 100644
index 0000000..579bc92
--- /dev/null
+++ b/.github/workflows/pypi-test-and-publish.yaml
@@ -0,0 +1,77 @@
+name: Build and Publish
+
+on:
+ push:
+ tags:
+ - "v*"
+ branches:
+ - "main"
+ - "breaking"
+ pull_request:
+
+jobs:
+ build:
+ name: Build Distribution
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4.2.2
+ with:
+ persist-credentials: false
+ - name: Set up Python
+ uses: actions/setup-python@v5.4.0
+ with:
+ python-version: "3.x"
+
+ - name: Install pypa/build
+ run: python3 -m pip install build --user
+ - name: Build a binary wheel and a source tarball
+ run: python3 -m build
+ - name: Store the distribution packages
+ uses: actions/upload-artifact@v4.4.3
+ with:
+ name: python-package-distributions
+ path: dist/
+
+ publish-to-testpypi:
+ name: Publish to TestPyPI
+ needs: [build]
+ runs-on: ubuntu-latest
+ environment:
+ name: testpypi
+ url: https://test.pypi.org/p/svg3d
+ permissions:
+ id-token: write
+
+ steps:
+ - name: Download all the dists
+ uses: actions/download-artifact@v4.1.8
+ with:
+ name: python-package-distributions
+ path: dist/
+ - name: Publish distribution to TestPyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ repository-url: https://test.pypi.org/legacy/
+ verbose: true
+ skip-existing: true
+
+ publish-to-pypi:
+ name: Publish to PyPI
+ if: startsWith(github.ref, 'refs/tags/v')
+ needs: [build]
+ runs-on: ubuntu-latest
+ environment:
+ name: pypi
+ url: https://pypi.org/p/svg3d
+ permissions:
+ id-token: write
+
+ steps:
+ - name: Download all the dists
+ uses: actions/download-artifact@v4.1.8
+ with:
+ name: python-package-distributions
+ path: dist/
+ - name: Publish to PyPI
+ uses: pypa/gh-action-pypi-publish@v1.12.2
diff --git a/1AI0.mtl b/1AI0.mtl
deleted file mode 100644
index a34a6bb..0000000
--- a/1AI0.mtl
+++ /dev/null
@@ -1,128 +0,0 @@
-newmtl 0x4259ff1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.259 0.349 1
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x1b9e771
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.106 0.62 0.467
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xff26181
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 1 0.149 0.094
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xffffff1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 1 1 1
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xffff3e1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 1 1 0.243
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xd95f021
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.851 0.373 0.008
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x7570b31
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.459 0.439 0.702
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xe7298a1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.906 0.161 0.541
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x66a61e1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.4 0.651 0.118
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xe6ab021
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.902 0.671 0.008
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xa6761d1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.651 0.463 0.114
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x6666661
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.4 0.4 0.4
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0xe41a1c1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.894 0.102 0.11
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x377eb81
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.216 0.494 0.722
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x4daf4a1
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.302 0.686 0.29
-Ks 0.25 0.25 0.25
-d 1
-newmtl 0x984ea31
-illum 2
-Ns 163
-Ni 0.001
-Ka 0 0 0
-Kd 0.596 0.306 0.639
-Ks 0.25 0.25 0.25
-d 1
diff --git a/README.rst b/README.rst
index 1e7970b..0ca7107 100644
--- a/README.rst
+++ b/README.rst
@@ -2,23 +2,23 @@
.. container:: row
- .. image:: doc/source/_static/cube-wireframe.svg
+ .. image:: https://raw.githubusercontent.com/janbridley/svg3d/refs/heads/main/doc/source/_static/cube-wireframe.svg
:alt: Cube Wireframe
:width: 17%
- .. image:: doc/source/_static/cycle-compact.svg
+ .. image:: https://raw.githubusercontent.com/janbridley/svg3d/refs/heads/main/doc/source/_static/cycle-compact.svg
:alt: Alternation Cycle
:width: 17%
- .. image:: doc/source/_static/CrumpledDevelopable-tri-compact.svg
+ .. image:: https://raw.githubusercontent.com/janbridley/svg3d/refs/heads/main/doc/source/_static/CrumpledDevelopable-tri-compact.svg
:alt: Keenan CrumpledDevelopable
:width: 17%
- .. image:: doc/source/_static/oloid_64-tri-compact.svg
+ .. image:: https://raw.githubusercontent.com/janbridley/svg3d/refs/heads/main/doc/source/_static/oloid_64-tri-compact.svg
:alt: Keenan Oloid
:width: 17%
- .. image:: doc/source/_static/bunny-tri-compact.svg
+ .. image:: https://raw.githubusercontent.com/janbridley/svg3d/refs/heads/main/doc/source/_static/bunny-tri-compact.svg
:alt: Stanford Bunny
:width: 17%
@@ -43,8 +43,14 @@ Many thanks to the `Keenan 3D Model repository `__.
+This project adheres to `Semantic Versioning `__.
+
+## v0.1.2
+
+### Fixed
+
+- Image links in README.rst
+
+## v0.1.1
+
+### Added
+
+- Added public ReadtheDocs page.
+- Additional examples
+
+## v0.1.0
+
+### Changed:
+- Removed `pyrr` dependency by implementing matrix methods
+- `Mesh` class is now more verstaile, and supports initialization from `Coxeter` objects
+
+### Added:
+- Added `isometric`, `dimetric`, and `trimetric` convenience functions to `View` class.
+- Support meshes with nonuniform degree (e.g. mixed tri-quad meshes). Faces are padded out to the largest polygon's size in the projection step, and are filtered back down before drawing the SVG.
+- `get_lookat_matrix` and `get_projection_matrix` methods to replace calls to `pyrr` required by the old version
+- Additional tests and CI
+- New `Shader` submodule, which supports a few basic lighting models and provides an interface for future development
+
+### Removed:
+- `Camera` class has been replaced with `view.look_at` and `view.projection`
+- `Scene` class has been removed in favor of basic Python iterables.
+- `extras` from original svg3d
diff --git a/pyproject.toml b/pyproject.toml
index 221ec67..8f5a044 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
[project]
name = "svg3d"
-version = "0.1.0"
-requires-python = ">=3.6"
+version = "0.1.2"
+requires-python = ">=3.10"
description = "Minimal library for rendering polyhedra as SVG wireframes."
-readme = "README.md"
+readme = "README.rst"
license = { file = "LICENSE" }
authors = [
{name = "Jen Bradley", email = "jenbrad@umich.edu"},
diff --git a/svg3d/io.py b/svg3d/io.py
deleted file mode 100644
index 28a2d39..0000000
--- a/svg3d/io.py
+++ /dev/null
@@ -1,46 +0,0 @@
-class OBJ:
- @classmethod
- def _parse_line(cls, line):
- """Parse a line into 'words', each containing one or more pieces of data."""
-
- return [word.split("/") for word in line.split()]
- # return line.split()
-
- @classmethod
- def _parse_mtl_into_colors(cls, filename: str, keys: tuple[str] = ("Kd",)):
- """Extract diffuse color values (Kd) from an obj .mtl file.
-
- https://paulbourke.net/dataformats/mtl/
- """
- with open(filename) as f:
- _materials = {}
- key = None
-
- for line in f:
- words = cls._parse_line(line)
- if not words:
- continue
-
- if words[0] == ["newmtl"]:
- key = words[1]
- print(key)
- _materials[key] = {}
- continue
- elif words[0][0] in keys:
- _materials[key][words[0]] = words[1:]
-
- print(_materials)
-
- # def __init__(self, filename: str):
- # vertices, faces = [], []
-
- # with open(filename) as f:
- # for line in f:
- # words = self._parse_line(line)
-
- # if not words: continue
-
-
-if __name__ == "__main__":
- materials = OBJ._parse_mtl_into_colors(filename="1AI0.mtl")
- print("MATS", materials)
diff --git a/svg3d/svg3d.py b/svg3d/svg3d.py
index 37f6435..8d6c069 100644
--- a/svg3d/svg3d.py
+++ b/svg3d/svg3d.py
@@ -10,7 +10,8 @@
"""
import warnings
-from typing import TYPE_CHECKING, Callable
+from collections.abc import Callable
+from typing import TYPE_CHECKING
import numpy as np
import svgwrite