Setup website with docusaurus (#11)

Summary:
Set up landing page, docs page, and html versions of the ipython notebook tutorials.
Pull Request resolved: https://github.com/fairinternal/pytorch3d/pull/11

Reviewed By: gkioxari

Differential Revision: D19730380

Pulled By: nikhilaravi

fbshipit-source-id: 5df8d3f2ac2f8dce4d51f5d14fc336508c2fd0ea
This commit is contained in:
Nikhila Ravi 2020-02-04 17:25:51 -08:00 committed by Facebook Github Bot
parent e290f87ca9
commit 15d3a4557e
48 changed files with 1900 additions and 72 deletions

13
.gitignore vendored
View File

@ -2,3 +2,16 @@ build/
dist/
*.egg-info/
**/__pycache__/
# Docusaurus site
website/yarn.lock
website/build/
website/i18n/
website/node_modules/*
website/npm-debug.log
## Generated for tutorials
website/_tutorials/
website/static/files/
website/pages/tutorials/*
!website/pages/tutorials/index.js

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 272 KiB

After

Width:  |  Height:  |  Size: 272 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

View File

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

View File

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

View File

@ -1,8 +1,13 @@
---
hide_title: true
sidebar_label: Batching
---
# Batching
In deep learning, every optimization step operates on multiple input examples for robust training. Thus, efficient batching is crucial. For image inputs, batching is straighforward; N images are resized to the same height and width and stacked as a 4 dimensional tensor of shape `N x 3 x H x W`. For meshes, batching is less straighforward.
<img src="../figs/batch_intro.png" alt="batch_intro" align="middle"/>
<img src="assets/batch_intro.png" alt="batch_intro" align="middle"/>
## Batch modes for meshes
@ -12,13 +17,13 @@ Assume you want to construct a batch containing two meshes, with `mesh1 = (v1: V
* Padded: The padded representation constructs a tensor by padding the extra values. Specifically, `meshes.verts_padded()` returns a tensor of shape `2 x max(V1, V2) x 3` and pads the extra vertices with `0`s. Similarly, `meshes.faces_padded()` returns a tensor of shape `2 x max(F1, F2) x 3` and pads the extra faces with `-1`s.
* Packed: The packed representation concatenates the examples in the batch into a tensor. In particular, `meshes.verts_packed()` returns a tensor of shape `(V1 + V2) x 3`. Similarly, `meshes.faces_packed()` returns a tensor of shape `(F1 + F2) x 3` for the faces. In the packed mode, auxiliary variables are computed that enable efficient conversion between packed and padded or list modes.
<img src="../figs/batch_modes.gif" alt="batch_modes" height="450" align="middle" />
<img src="assets/batch_modes.gif" alt="batch_modes" height="450" align="middle" />
## Use cases for batch modes
The need for different mesh batch modes is inherent to the way pytorch operators are implemented. To fully utilize the optimized pytorch ops, the [Meshes][meshes] data structure allows for efficient conversion between the different batch modes. This is crucial when aiming for a fast and efficient training cycle. An example of this is [Mesh R-CNN][meshrcnn]. Here, in the same forward pass different parts of the network assume different inputs, which are computed by converting between the different batch modes. In particular, [vert_align][vert_align] assumes a *padded* input tensor while immediately after [graph_conv][graphconv] assumes a *packed* input tensor.
<img src="../figs/meshrcnn.png" alt="meshrcnn" width="700" align="middle" />
<img src="assets/meshrcnn.png" alt="meshrcnn" width="700" align="middle" />
[meshes]: https://github.com/facebookresearch/pytorch3d/blob/master/pytorch3d/structures/meshes.py

View File

@ -1,3 +1,8 @@
---
sidebar_label: Loading from file
hide_title: true
---
# Meshes and IO
The Meshes object represents a batch of triangulated meshes, and is central to

View File

@ -1,4 +1,9 @@
# Differentiable Rendering
---
hide_title: true
sidebar_label: Overview
---
# Rendering Overview
Differentiable rendering is a relatively new and exciting research area in computer vision, bridging the gap between 2D and 3D by allowing 2D image pixels to be related back to 3D properties of a scene.
@ -18,7 +23,7 @@ Our implementation decouples the rasterization and shading steps of rendering. T
## <u>Get started</u>
To learn about more the implementation and start using the renderer refer to [renderer_getting_started.md](renderer_getting_started.md), which also contains the [architecture overview](../figs/architecture_overview.png) and [coordinate transformation conventions](../figs/transformations_overview.png).
To learn about more the implementation and start using the renderer refer to [renderer_getting_started.md](renderer_getting_started.md), which also contains the [architecture overview](assets/architecture_overview.png) and [coordinate transformation conventions](assets/transformations_overview.png).
## <u>Key features</u>
@ -37,7 +42,7 @@ We compared PyTorch3d with SoftRasterizer to measure the effect of both these de
This figure shows how the coarse-to-fine strategy for rasterization results in significant speed up compared to naive rasterization for large image size and large mesh sizes.
<img src="../figs/p3d_naive_vs_coarse.png" width="1000">
<img src="assets/p3d_naive_vs_coarse.png" width="1000">
For small mesh and image sizes, the naive approach is slightly faster. We advise that you understand the data you are using and choose the rasterization setting which suits your performance requirements. It is easy to switch between the naive and coarse-to-fine options by adjusting the `bin_size` value when initializing the [rasterization settings](https://github.com/facebookresearch/pytorch3d/blob/master/pytorch3d/renderer/mesh/rasterizer.py#L26).
@ -50,7 +55,7 @@ This figure shows the effect of the _combination_ of coarse-to-fine rasterizatio
In the SoftRasterizer implementation, in both the forward and backward pass, there is a loop over every single face in the mesh for every pixel in the image. Therefore, the time for the full forward plus backward pass is ~2x the time for the forward pass. For small mesh and image sizes, the SoftRasterizer approach is slightly faster.
<img src="../figs/p3d_vs_softras.png" width="1000">
<img src="assets/p3d_vs_softras.png" width="1000">
@ -66,7 +71,7 @@ We tested with a range of increasingly large meshes and bin sizes.
**Fig 3: PyTorch3d heterogeneous batching compared with SoftRasterizer**
<img src="../figs/fullset_batch_size_16.png" width="700"/>
<img src="assets/fullset_batch_size_16.png" width="700"/>
This shows that for large meshes and large bin width (i.e. more variation in mesh size in the batch) the heterogeneous batching approach in PyTorch3d is faster than either of the workarounds with SoftRasterizer.

View File

@ -1,10 +1,15 @@
---
hide_title: true
sidebar_label: Getting Started
---
# Renderer Getting Started
### Architecture Overview
The renderer is designed to be modular, extensible and support batching and gradients for all inputs. The following figure describes all the components of the rendering pipeline.
<img src="../figs/architecture_overview.png" width="1000">
<img src="assets/architecture_overview.png" width="1000">
##### Fragments
@ -31,7 +36,7 @@ The differentiable renderer API is experimental and subject to change!.
Rendering requires transformations between several different coordinate frames: world space, view/camera space, NDC space and screen space. At each step it is important to know where the camera is located, how the x,y,z axes are aligned and the possible range of values. The following figure outlines the conventions used PyTorch3d.
<img src="../figs/transformations_overview.png" width="1000">
<img src="assets/transformations_overview.png" width="1000">
@ -43,7 +48,7 @@ While we tried to emulate several aspects of OpenGL, the NDC coordinate system i
In OpenGL, the camera at the origin is looking along `-z` axis in camera space, but it is looking along the `+z` axis in NDC space.
<img align="center" src="../figs/opengl_coordframes.png" width="300">
<img align="center" src="assets/opengl_coordframes.png" width="300">
---
### A simple renderer

View File

@ -0,0 +1,13 @@
---
hide_title: true
sidebar_label: Why PyTorch3d
---
# Why PyTorch3d
Our goal with PyTorch3D is to help accelerate research at the intersection of deep learning and 3D. 3D data is more complex than 2D images and while working on projects such as [Mesh R-CNN](https://github.com/facebookresearch/meshrcnn) and [C3DPO](https://github.com/facebookresearch/c3dpo_nrsfm), we encountered several challenges including 3D data representation, batching, and speed. We have developed many useful operators and abstractions for working on 3D deep learning and want to share this with the community to drive novel research in this area.
In PyTorch3D we have included efficient 3D operators, heterogeneous batching capabilities, and a modular differentiable rendering API, to equip researchers in this field with a much needed toolkit to implement cutting-edge research with complex 3D inputs.

View File

@ -11,15 +11,6 @@
"# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href=\"https://colab.research.google.com/github/facebookresearch/pytorch3d/blob/master/docs/tutorials/bundle_adjustment.ipynb\">\n",
" <img align=\"left\" src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/>\n",
"</a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -40,10 +31,10 @@
"where $d(g_i, g_j)$ is a suitable metric that compares the extrinsics of cameras $g_i$ and $g_j$. \n",
"\n",
"Visually, the problem can be described as follows. The picture below depicts the situation at the beginning of our optimization. The ground truth cameras are plotted in green while the randomly initialized estimated cameras are plotted in blue:\n",
"![Initialization](./data/bundle_adjustment_initialization.png)\n",
"![Initialization](data/bundle_adjustment_initialization.png)\n",
"\n",
"Our optimization seeks to align the estimated (blue) cameras with the ground truth (green) cameras, by minimizing the discrepancies between pairs of relative cameras. Thus, the solution to the problem should look as follows:\n",
"![Solution](./data/bundle_adjustment_final.png)\n",
"![Solution](data/bundle_adjustment_final.png)\n",
"\n",
"In practice, the camera extrinsics $g_{ij}$ and $g_i$ are represented using objects from the `SfMPerspectiveCameras` class initialized with the corresponding rotation and translation matrices `R_absolute` and `T_absolute` that define the extrinsic parameters $g = (R, T); R \\in SO(3); T \\in \\mathbb{R}^3$. In order to ensure that `R_absolute` is a valid rotation matrix, we represent it using an exponential map (implemented with `so3_exponential_map`) of the axis-angle representation of the rotation `log_R_absolute`.\n",
"\n",
@ -421,9 +412,9 @@
},
"file_extension": ".py",
"kernelspec": {
"display_name": "pytorch3d (local)",
"display_name": "p3d_dev7",
"language": "python",
"name": "pytorch3d_local"
"name": "p3d_dev7"
},
"language_info": {
"codemirror_mode": {
@ -435,7 +426,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5+"
"version": "3.7.6"
},
"mimetype": "text/x-python",
"name": "python",

File diff suppressed because one or more lines are too long

60
scripts/build_website.sh Normal file
View File

@ -0,0 +1,60 @@
#!/bin/bash
# Copyright (c) Facebook, Inc. and its affiliates.
# run this script from the project root using `./scripts/build_docs.sh`
usage() {
echo "Usage: $0 [-b]"
echo ""
echo "Build PyTorch3D documentation."
echo ""
echo " -b Build static version of documentation (otherwise start server)"
echo ""
exit 1
}
BUILD_STATIC=false
while getopts 'hb' flag; do
case "${flag}" in
h)
usage
;;
b)
BUILD_STATIC=true
;;
*)
usage
;;
esac
done
echo "-----------------------------------"
echo "Building PyTorch3d Docusaurus site"
echo "-----------------------------------"
cd website || exit
yarn
cd ..
echo "-----------------------------------"
echo "Generating tutorials"
echo "-----------------------------------"
cwd=$(pwd)
mkdir -p "website/_tutorials"
mkdir -p "website/static/files"
python scripts/parse_tutorials.py --repo_dir "${cwd}"
cd website || exit
if [[ $BUILD_STATIC == true ]]; then
echo "-----------------------------------"
echo "Building static site"
echo "-----------------------------------"
yarn build
else
echo "-----------------------------------"
echo "Starting local server"
echo "-----------------------------------"
yarn start
fi

111
scripts/parse_tutorials.py Normal file
View File

@ -0,0 +1,111 @@
#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
import argparse
import json
import os
import nbformat
from bs4 import BeautifulSoup
from nbconvert import HTMLExporter, ScriptExporter
TEMPLATE = """const CWD = process.cwd();
const React = require('react');
const Tutorial = require(`${{CWD}}/core/Tutorial.js`);
class TutorialPage extends React.Component {{
render() {{
const {{config: siteConfig}} = this.props;
const {{baseUrl}} = siteConfig;
return <Tutorial baseUrl={{baseUrl}} tutorialID="{}"/>;
}}
}}
module.exports = TutorialPage;
"""
JS_SCRIPTS = """
<script
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js">
</script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js">
</script>
""" # noqa: E501
def gen_tutorials(repo_dir: str) -> None:
"""Generate HTML tutorials for PyTorch3d Docusaurus site from Jupyter notebooks.
Also create ipynb and py versions of tutorial in Docusaurus site for
download.
"""
with open(os.path.join(repo_dir, "website", "tutorials.json"), "r") as infile:
tutorial_config = json.loads(infile.read())
tutorial_ids = {x["id"] for v in tutorial_config.values() for x in v}
for tid in tutorial_ids:
print("Generating {} tutorial".format(tid))
# convert notebook to HTML
ipynb_in_path = os.path.join(repo_dir, "docs", "tutorials", "{}.ipynb".format(tid))
with open(ipynb_in_path, "r") as infile:
nb_str = infile.read()
nb = nbformat.reads(nb_str, nbformat.NO_CONVERT)
# displayname is absent from notebook metadata
nb["metadata"]["kernelspec"]["display_name"] = "python3"
exporter = HTMLExporter()
html, meta = exporter.from_notebook_node(nb)
# pull out html div for notebook
soup = BeautifulSoup(html, "html.parser")
nb_meat = soup.find("div", {"id": "notebook-container"})
del nb_meat.attrs["id"]
nb_meat.attrs["class"] = ["notebook"]
html_out = JS_SCRIPTS + str(nb_meat)
# generate html file
html_out_path = os.path.join(
repo_dir, "website", "_tutorials", "{}.html".format(tid)
)
with open(html_out_path, "w") as html_outfile:
html_outfile.write(html_out)
# generate JS file
script = TEMPLATE.format(tid)
js_out_path = os.path.join(
repo_dir, "website", "pages", "tutorials", "{}.js".format(tid)
)
with open(js_out_path, "w") as js_outfile:
js_outfile.write(script)
# output tutorial in both ipynb & py form
ipynb_out_path = os.path.join(
repo_dir, "website", "static", "files", "{}.ipynb".format(tid)
)
with open(ipynb_out_path, "w") as ipynb_outfile:
ipynb_outfile.write(nb_str)
exporter = ScriptExporter()
script, meta = exporter.from_notebook_node(nb)
py_out_path = os.path.join(
repo_dir, "website", "static", "files", "{}.py".format(tid)
)
with open(py_out_path, "w") as py_outfile:
py_outfile.write(script)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Generate JS, HTML, ipynb, and py files for tutorials."
)
parser.add_argument(
"--repo_dir", metavar="path", required=True, help="Pytorch3D repo directory."
)
args = parser.parse_args()
gen_tutorials(args.repo_dir)

View File

@ -0,0 +1,46 @@
#!/bin/bash
# Copyright (c) Facebook, Inc. and its affiliates.
usage() {
echo "Usage: $0 [-b]"
echo ""
echo "Build and push updated PyTorch3D site."
echo ""
exit 1
}
# Current directory (needed for cleanup later)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Make temporary directory
WORK_DIR=$(mktemp -d)
cd "${WORK_DIR}" || exit
# Clone both master & gh-pages branches
git clone git@github.com:facebookresearch/pytorch3d.git pytorch3d-master
git clone --branch gh-pages git@github.com:facebookresearch/pytorch3d.git pytorch3d-gh-pages
cd pytorch3d-master/website || exit
# Build site, tagged with "latest" version; baseUrl set to /versions/latest/
yarn
cd .. || exit
./scripts/build_website.sh -b
yarn run build
cd "${WORK_DIR}" || exit
rm -rf pytorch3d-gh-pages/*
touch pytorch3d-gh-pages/CNAME
echo "pytorch3d.org" > pytorch3d-gh-pages/CNAME
mv pytorch3d-master/website/build/pytorch3d/* pytorch3d-gh-pages/
cd pytorch3d-gh-pages || exit
git add .
git commit -m 'Update latest version of site'
git push
# Clean up
cd "${SCRIPT_DIR}" || exit
rm -rf "${WORK_DIR}"

2
website/.dockerignore Normal file
View File

@ -0,0 +1,2 @@
*/node_modules
*.log

13
website/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
.DS_Store
node_modules
lib/core/metadata.js
lib/core/MetadataBlog.js
website/translated_docs
website/build/
website/yarn.lock
website/node_modules
website/i18n/*
website/_tutorials/*

260
website/README.md Normal file
View File

@ -0,0 +1,260 @@
This website was created with [Docusaurus](https://docusaurus.io/).
# Building the PyTorch3d website
## Install
1. Make sure all the dependencies for the website are installed:
```sh
# Install dependencies
$ yarn
or
$ npm install docusaurus-init
```
2. Run your dev server:
```sh
# Start the site
$ yarn start
or
$ ./node_modules/docusaurus/lib/start-server.js
```
## Build the tutorials
We convert the ipython notebooks to html using `parse_tutorials.py` which is found in the scripts folder at the root of the PyTorch3D directory.
Before running this script install the following dependencies:
```
pip install nbformat==4.4.0 nbconvert==5.3.1 ipywidgets==7.5.1 tornado==4.2 bs4
```
Install yarn:
```
brew install yarn
# or
curl -o- -L https://yarnpkg.com/install.sh | bash
```
Then run the build script:
```
bash scripts/build_website.sh
```
This will build the docusaurus website and run a script to parse the tutorials and generate:
- `.html` files in the `website/_tutorials` folder
- `.js` files in the `website/pages/tutorials` folder
- `.py`/`.ipynb` files in the `website/static/files` folder
TODO: Add support for latex in markdown in jupyter notebooks and embedded images.
## Add a new tutorial
The tutorials to include in the website are listed in `website/tutorials.json`. If you create a new tutorial add an entry to the list in this file. This is needed in order to generate the sidebar for the tutorials page.
## Edit the landing page
To change the content of the landing page modify: `website/pages/en/index.js`.
## Edit the tutorials page
To change the content of the tutorials home page modify: `website/pages/tutorials/index.js`.
---------------------------------------------------------
## Docusaurus docs
- [Get Started in 5 Minutes](#get-started-in-5-minutes)
- [Directory Structure](#directory-structure)
- [Editing Content](#editing-content)
- [Adding Content](#adding-content)
- [Full Documentation](#full-documentation)
## Directory Structure
Your project file structure should look something like this
```
my-docusaurus/
docs/
doc-1.md
doc-2.md
doc-3.md
website/
blog/
2016-3-11-oldest-post.md
2017-10-24-newest-post.md
core/
node_modules/
pages/
static/
css/
img/
package.json
sidebars.json
siteConfig.js
```
# Editing Content
## Editing an existing docs page
Edit docs by navigating to `docs/` and editing the corresponding document:
`docs/doc-to-be-edited.md`
```markdown
---
id: page-needs-edit
title: This Doc Needs To Be Edited
---
Edit me...
```
For more information about docs, click [here](https://docusaurus.io/docs/en/navigation)
## Editing an existing blog post
Edit blog posts by navigating to `website/blog` and editing the corresponding post:
`website/blog/post-to-be-edited.md`
```markdown
---
id: post-needs-edit
title: This Blog Post Needs To Be Edited
---
Edit me...
```
For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)
# Adding Content
## Adding a new docs page to an existing sidebar
1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`:
```md
---
id: newly-created-doc
title: This Doc Needs To Be Edited
---
My new content here..
```
1. Refer to that doc's ID in an existing sidebar in `website/sidebars.json`:
```javascript
// Add newly-created-doc to the Getting Started category of docs
{
"docs": {
"Getting Started": [
"quick-start",
"newly-created-doc" // new doc here
],
...
},
...
}
```
For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation)
## Adding a new blog post
1. Make sure there is a header link to your blog in `website/siteConfig.js`:
`website/siteConfig.js`
```javascript
headerLinks: [
...
{ blog: true, label: 'Blog' },
...
]
```
2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`:
`website/blog/2018-05-21-New-Blog-Post.md`
```markdown
---
author: Frank Li
authorURL: https://twitter.com/foobarbaz
authorFBID: 503283835
title: New Blog Post
---
Lorem Ipsum...
```
For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)
## Adding items to your site's top navigation bar
1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`:
`website/siteConfig.js`
```javascript
{
headerLinks: [
...
/* you can add docs */
{ doc: 'my-examples', label: 'Examples' },
/* you can add custom pages */
{ page: 'help', label: 'Help' },
/* you can add external links */
{ href: 'https://github.com/facebook/docusaurus', label: 'GitHub' },
...
],
...
}
```
For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation)
## Adding custom pages
1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`:
1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element:
`website/siteConfig.js`
```javascript
{
headerLinks: [
...
{ page: 'my-new-custom-page', label: 'My New Custom Page' },
...
],
...
}
```
For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages).
# Full Documentation
Full documentation can be found on the [website](https://docusaurus.io/).

72
website/core/Footer.js Normal file
View File

@ -0,0 +1,72 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
*/
const PropTypes = require("prop-types");
const React = require('react');
function SocialFooter(props) {
const repoUrl = `https://github.com/${props.config.organizationName}/${props.config.projectName}`;
return (
<div className="footerSection">
<div className="social">
<a
className="github-button" // part of the https://buttons.github.io/buttons.js script in siteConfig.js
href={repoUrl}
data-count-href={`${repoUrl}/stargazers`}
data-show-count="true"
data-count-aria-label="# stargazers on GitHub"
aria-label="Star PyTorch3d on GitHub"
>
{props.config.projectName}
</a>
</div>
</div>
);
}
SocialFooter.propTypes = {
config: PropTypes.object
};
class Footer extends React.Component {
docUrl(doc, language) {
const baseUrl = this.props.config.baseUrl;
const docsUrl = this.props.config.docsUrl;
const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
const langPart = `${language ? `${language}/` : ''}`;
return `${baseUrl}${docsPart}${langPart}${doc}`;
}
pageUrl(doc, language) {
const baseUrl = this.props.config.baseUrl;
return baseUrl + (language ? `${language}/` : '') + doc;
}
render() {
const repoUrl = `https://github.com/${this.props.config.organizationName}/${this.props.config.projectName}`;
return (
<footer className="nav-footer" id="footer">
<section className="sitemap">
<SocialFooter config={this.props.config} />
</section>
<a
href="https://opensource.facebook.com/"
target="_blank"
rel="noreferrer noopener"
className="fbOpenSource">
<img
src={`${this.props.config.baseUrl}img/oss_logo.png`}
alt="Facebook Open Source"
width="170"
height="45"
/>
</a>
<section className="copyright">{this.props.config.copyright}</section>
</footer>
);
}
}
module.exports = Footer;

87
website/core/Tutorial.js Normal file
View File

@ -0,0 +1,87 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* @format
*/
const React = require('react');
const fs = require('fs-extra');
const path = require('path');
const CWD = process.cwd();
const CompLibrary = require(`${CWD}/node_modules/docusaurus/lib/core/CompLibrary.js`);
const Container = CompLibrary.Container;
const TutorialSidebar = require(`${CWD}/core/TutorialSidebar.js`);
function renderDownloadIcon() {
return (
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="file-download"
className="svg-inline--fa fa-file-download fa-w-12"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512">
<path
fill="currentColor"
d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"
/>
</svg>
);
}
class Tutorial extends React.Component {
render() {
const {baseUrl, tutorialID} = this.props;
const htmlFile = `${CWD}/_tutorials/${tutorialID}.html`;
const normalizedHtmlFile = path.normalize(htmlFile);
return (
<div className="docMainWrapper wrapper">
<TutorialSidebar currentTutorialID={tutorialID} />
<Container className="mainContainer">
<div className="tutorialButtonsWrapper">
<div className="colabButtonWrapper">
<a
href={`https://colab.research.google.com/github/facebookresearch/pytorch3d/blob/master/docs/tutorials/${tutorialID}.ipynb`}>
<img align="left" src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
</a>
</div>
<div className="tutorialButtonWrapper buttonWrapper">
<a
className="tutorialButton button"
download
href={`${baseUrl}files/${tutorialID}.ipynb`}
target="_blank">
{renderDownloadIcon()}
{'Download Tutorial Jupyter Notebook'}
</a>
</div>
<div className="tutorialButtonWrapper buttonWrapper">
<a
className="tutorialButton button"
download
href={`${baseUrl}files/${tutorialID}.py`}
target="_blank">
{renderDownloadIcon()}
{'Download Tutorial Source Code'}
</a>
</div>
</div>
<div
className="tutorialBody"
dangerouslySetInnerHTML={{
__html: fs.readFileSync(normalizedHtmlFile, {encoding: 'utf8'}),
}}
/>
</Container>
</div>
);
}
}
module.exports = Tutorial;

View File

@ -0,0 +1,88 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* @format
*/
const React = require('react');
const fs = require('fs-extra');
const path = require('path');
const join = path.join;
const CWD = process.cwd();
const CompLibrary = require(join(
CWD,
'/node_modules/docusaurus/lib/core/CompLibrary.js',
));
const SideNav = require(join(
CWD,
'/node_modules/docusaurus/lib/core/nav/SideNav.js',
));
const Container = CompLibrary.Container;
const OVERVIEW_ID = 'tutorial_overview';
class TutorialSidebar extends React.Component {
render() {
const {currentTutorialID} = this.props;
const current = {
id: currentTutorialID || OVERVIEW_ID,
};
const toc = [
{
type: 'CATEGORY',
title: 'Tutorials',
children: [
{
type: 'LINK',
item: {
permalink: 'tutorials/',
id: OVERVIEW_ID,
title: 'Overview',
},
},
],
},
];
const jsonFile = join(CWD, 'tutorials.json');
const normJsonFile = path.normalize(jsonFile);
const json = JSON.parse(fs.readFileSync(normJsonFile, {encoding: 'utf8'}));
Object.keys(json).forEach(category => {
const categoryItems = json[category];
const items = [];
categoryItems.map(item => {
items.push({
type: 'LINK',
item: {
permalink: `tutorials/${item.id}`,
id: item.id,
title: item.title,
},
});
});
toc.push({
type: 'CATEGORY',
title: category,
children: items,
});
});
return (
<Container className="docsNavContainer" id="docsNav" wrapper={false}>
<SideNav
language={'tutorials'}
root={'tutorials'}
title="Tutorials"
contents={toc}
current={current}
/>
</Container>
);
}
}
module.exports = TutorialSidebar;

14
website/package.json Normal file
View File

@ -0,0 +1,14 @@
{
"scripts": {
"examples": "docusaurus-examples",
"start": "docusaurus-start",
"build": "docusaurus-build",
"publish-gh-pages": "docusaurus-publish",
"write-translations": "docusaurus-write-translations",
"version": "docusaurus-version",
"rename-version": "docusaurus-rename-version"
},
"devDependencies": {
"docusaurus": "^1.14.4"
}
}

51
website/pages/en/help.js Normal file
View File

@ -0,0 +1,51 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
**/
const React = require('react');
const CompLibrary = require('../../core/CompLibrary.js');
const Container = CompLibrary.Container;
const GridBlock = CompLibrary.GridBlock;
function Help(props) {
const {config: siteConfig, language = ''} = props;
const {baseUrl, docsUrl} = siteConfig;
const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
const langPart = `${language ? `${language}/` : ''}`;
const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`;
const supportLinks = [
{
content: `Learn more using the [documentation on this site.](${docUrl(
'doc1.html',
)})`,
title: 'Browse Docs',
},
{
content: 'Ask questions about the documentation and project',
title: 'Join the community',
},
{
content: "Find out what's new with this project",
title: 'Stay up to date',
},
];
return (
<div className="docMainWrapper wrapper">
<Container className="mainContainer documentContainer postContainer">
<div className="post">
<header className="postHeader">
<h1>Need help?</h1>
</header>
<p>This project is maintained by a dedicated group of people.</p>
<GridBlock contents={supportLinks} layout="threeColumn" />
</div>
</Container>
</div>
);
}
module.exports = Help;

223
website/pages/en/index.js Normal file
View File

@ -0,0 +1,223 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
**/
const React = require('react');
const CompLibrary = require('../../core/CompLibrary.js');
const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */
const Container = CompLibrary.Container;
const GridBlock = CompLibrary.GridBlock;
const bash = (...args) => `~~~bash\n${String.raw(...args)}\n~~~`;
class HomeSplash extends React.Component {
render() {
const {siteConfig, language = ''} = this.props;
const {baseUrl, docsUrl} = siteConfig;
const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
const langPart = `${language ? `${language}/` : ''}`;
const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`;
const SplashContainer = props => (
<div className="homeContainer">
<div className="homeSplashFade">
<div className="wrapper homeWrapper">{props.children}</div>
</div>
</div>
);
const Logo = props => (
<div className="splashLogo">
<img src={props.img_src} alt="Project Logo" />
</div>
);
const ProjectTitle = props => (
<h2 className="projectTitle">
<small>{props.tagline}</small>
</h2>
);
const PromoSection = props => (
<div className="section promoSection">
<div className="promoRow">
<div className="pluginRowBlock">{props.children}</div>
</div>
</div>
);
const Button = props => (
<div className="pluginWrapper buttonWrapper">
<a className="button" href={props.href} target={props.target}>
{props.children}
</a>
</div>
);
return (
<SplashContainer>
<Logo img_src={baseUrl + 'img/pytorch3dlogowhite.svg'} />
<div className="inner">
<ProjectTitle tagline={siteConfig.tagline} title={siteConfig.title} />
<PromoSection>
<Button href={docUrl('why_pytorch3d.html')}>Docs</Button>
<Button href={`${baseUrl}tutorials/`}>Tutorials</Button>
<Button href={'#quickstart'}>Get Started</Button>
</PromoSection>
</div>
</SplashContainer>
);
}
}
class Index extends React.Component {
render() {
const {config: siteConfig, language = ''} = this.props;
const {baseUrl} = siteConfig;
const Block = props => (
<Container
padding={['bottom', 'top']}
id={props.id}
background={props.background}>
<GridBlock
align="center"
contents={props.children}
layout={props.layout}
/>
</Container>
);
const Description = () => (
<Block background="light">
{[
{
content:
'This is another description of how this project is useful',
image: `${baseUrl}img/docusaurus.svg`,
imageAlign: 'right',
title: 'Description',
},
]}
</Block>
);
const pre = '```';
const codeExample = `${pre}python
from pytorch3d.utils import ico_sphere
from pytorch3d.io import load_obj
from pytorch3d.structures import Meshes
from pytorch3d.ops import sample_points_from_meshes
from pytorch3d.loss import chamfer_distance
# Use an ico_sphere mesh and load a mesh from an .obj e.g. model.obj
sphere_mesh = ico_sphere(level=3)
verts, faces, _ = load_obj("model.obj")
test_mesh = Meshes(verts=[verts], faces=[faces.verts_idx])
# Differentiably sample 5k points from the surface of each mesh and then compute the loss.
sample_sphere = sample_points_from_meshes(sphere_mesh, 5000)
sample_test = sample_points_from_meshes(test_mesh, 5000)
loss_chamfer, _ = chamfer_distance(sample_sphere, sample_test)
`;
const QuickStart = () => (
<div
className="productShowcaseSection"
id="quickstart"
style={{textAlign: 'center'}}>
<h2>Get Started</h2>
<Container>
<ol>
<li>
<strong>Install PyTorch3D:</strong>
<MarkdownBlock>{bash`conda install pytorch torchvision -c pytorch # OSX only
conda install pytorch3d -c pytorch3d # all systems`}</MarkdownBlock>
</li>
<li>
<strong>Try a few 3D operators </strong>
e.g. compute the chamfer loss between two meshes:
<MarkdownBlock>{codeExample}</MarkdownBlock>
</li>
</ol>
</Container>
</div>
);
const Features = () => (
<div className="productShowcaseSection" style={{textAlign: 'center'}}>
<Block layout="fourColumn">
{[
{
content:
'Supports batching of 3D inputs of different sizes ' +
'such as meshes' ,
image: `${baseUrl}img/batching.svg`,
imageAlign: 'top',
title: 'Heterogeneous Batching',
},
{
content:
'Supports optimized implementations of ' +
'several common functions for 3D data',
image: `${baseUrl}img/ops.png`,
imageAlign: 'top',
title: 'Fast 3D Operators',
},
{
content:
'Modular differentiable rendering API ' +
'with parallel implementations in ' +
'PyTorch, C++ and CUDA' ,
image: `${baseUrl}img/rendering.svg`,
imageAlign: 'top',
title: 'Differentiable Rendering',
},
]}
</Block>
</div>
);
const Showcase = () => {
if ((siteConfig.users || []).length === 0) {
return null;
}
const showcase = siteConfig.users
.filter(user => user.pinned)
.map(user => (
<a href={user.infoLink} key={user.infoLink}>
<img src={user.image} alt={user.caption} title={user.caption} />
</a>
));
const pageUrl = page => baseUrl + (language ? `${language}/` : '') + page;
return (
<div className="productShowcaseSection paddingBottom">
<h2>Who is Using This?</h2>
<p>This project is used by all these people</p>
<div className="logos">{showcase}</div>
<div className="more-users">
<a className="button" href={pageUrl('users.html')}>
More {siteConfig.title} Users
</a>
</div>
</div>
);
};
return (
<div>
<HomeSplash siteConfig={siteConfig} language={language} />
<div className="landingPage mainContainer">
<Features />
<QuickStart />
</div>
</div>
);
}
}
module.exports = Index;

46
website/pages/en/users.js Normal file
View File

@ -0,0 +1,46 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
**/
const React = require('react');
const CompLibrary = require('../../core/CompLibrary.js');
const Container = CompLibrary.Container;
class Users extends React.Component {
render() {
const {config: siteConfig} = this.props;
if ((siteConfig.users || []).length === 0) {
return null;
}
const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js`;
const showcase = siteConfig.users.map(user => (
<a href={user.infoLink} key={user.infoLink}>
<img src={user.image} alt={user.caption} title={user.caption} />
</a>
));
return (
<div className="mainContainer">
<Container padding={['bottom', 'top']}>
<div className="showcaseSection">
<div className="prose">
<h1>Who is Using This?</h1>
<p>This project is used by many folks</p>
</div>
<div className="logos">{showcase}</div>
<p>Are you using this project?</p>
<a href={editUrl} className="button">
Add your company
</a>
</div>
</Container>
</div>
);
}
}
module.exports = Users;

View File

@ -0,0 +1,49 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* @format
**/
const React = require('react');
const CWD = process.cwd();
const CompLibrary = require(`${CWD}/node_modules/docusaurus/lib/core/CompLibrary.js`);
const Container = CompLibrary.Container;
const MarkdownBlock = CompLibrary.MarkdownBlock;
const TutorialSidebar = require(`${CWD}/core/TutorialSidebar.js`);
const bash = (...args) => `~~~bash\n${String.raw(...args)}\n~~~`;
class TutorialHome extends React.Component {
render() {
return (
<div className="docMainWrapper wrapper">
<TutorialSidebar currentTutorialID={null} />
<Container className="mainContainer documentContainer postContainer">
<div className="post">
<header className="postHeader">
<h1 className="postHeaderTitle">Welcome to the PyTorch3D Tutorials</h1>
</header>
<p>
Here you can learn about the structure and applications of Pytorch3D from
examples which are in the form of ipython notebooks.
</p>
<h3> Run interactively </h3>
<p>
At the top of each example you can find a button named <strong>"Open in Colab"</strong> which will open the notebook in <a href="https://colab.research.google.com/notebooks/intro.ipynb"> Google Colaboratory </a> where you can run the code directly in the browser with access to GPU support e.g.
</p>
<img align="center" src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
<p> You can modify the code and experiment with varying different settings.
Remember to install pytorch, torchvision, fvcore and pytorch3d in the first cell of the colab notebook by running: </p>
<MarkdownBlock>{bash`!pip install torch torchvision
!pip install 'git+https://github.com/facebookresearch/pytorch3d.git`}</MarkdownBlock>
<h3> Run locally </h3>
<p> There is also a button to download the notebook and source code to run it locally. </p>
</div>
</Container>
</div>
);
}
}
module.exports = TutorialHome;

7
website/sidebars.json Normal file
View File

@ -0,0 +1,7 @@
{
"docs": {
"Introduction": ["why_pytorch3d"],
"Meshes": ["batching", "meshes_io"],
"Differentiable Renderer": ["renderer", "renderer_getting_started"]
}
}

86
website/siteConfig.js Normal file
View File

@ -0,0 +1,86 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
*/
// See https://docusaurus.io/docs/site-config for all the possible
// site configuration options.
// List of projects/orgs using your project for the users page.
const users = [
{
caption: 'User1',
// You will need to prepend the image path with your baseUrl
// if it is not '/', like: '/test-site/img/image.jpg'.
image: '/img/undraw_open_source.svg',
infoLink: 'https://www.facebook.com',
pinned: true,
},
];
const baseUrl = '/'
const siteConfig = {
title: 'PyTorch3d', // Title for your website.
tagline: 'A library for deep learning with 3D data',
url: 'https://pytorch3d.org', // Your website URL
baseUrl: baseUrl, // Base URL for your project */
projectName: 'pytorch3d',
organizationName: 'facebookresearch',
customDocsPath: 'docs/notes',
headerLinks: [
{doc: 'why_pytorch3d', label: 'Docs'},
{page: 'tutorials', label: 'Tutorials'},
{href: "https://pytorch3d.readthedocs.io/", label: 'API'},
{href: "https://github.com/facebookresearch/pytorch3d", label: 'GitHub'},
],
// If you have users set above, you add it here:
users,
/* path to images for header/footer */
headerIcon: 'img/pytorch3dfavicon.png',
footerIcon: 'img/pytorch3dfavicon.png',
favicon: 'img/pytorch3dfavicon.png',
/* Colors for website */
colors: {
primaryColor: '#812CE5',
secondaryColor: '#FFAF00',
},
// This copyright info is used in /core/Footer.js and blog RSS/Atom feeds.
copyright: `Copyright "\u00A9" ${new Date().getFullYear()} Facebook Inc`,
highlight: {
// Highlight.js theme to use for syntax highlighting in code blocks.
theme: 'default',
},
// Add custom scripts here that would be placed in <script> tags.
scripts: ['https://buttons.github.io/buttons.js'],
// On page navigation for the current documentation page.
onPageNav: 'separate',
// No .html extensions for paths.
cleanUrl: true,
// Open Graph and Twitter card images.
ogImage: 'img/pytorch3dlogoicon.svg',
twitterImage: 'img/pytorch3dlogoicon.svg',
// Google analytics
gaTrackingId: 'UA-157376881-1',
// For sites with a sizable amount of content, set collapsible to true.
// Expand/collapse the links and subcategories under categories.
// docsSideNavCollapsible: true,
// Show documentation's last contributor's name.
enableUpdateBy: true,
// Show documentation's last update time.
// enableUpdateTime: true,
};
module.exports = siteConfig;

View File

@ -0,0 +1,308 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
**/
html body {
font-family: 'Montserrat', sans-serif;
overflow-x: hidden;
}
.fixedHeaderContainer {
background-color: #222222;
}
.fixedHeaderContainer header .headerTitleWithLogo {
display: block;
color: #ffffff;
}
.fixedHeaderContainer header .logo {
height: 50px;
}
.fixedHeaderContainer header a:nth-child(2) {
position: absolute;
right: 0px;
}
.fixedHeaderContainer header a:nth-child(2) h3 {
font-size: 14px;
}
.fixedHeaderContainer header a:nth-child(2) h3::before {
content: 'v: ';
}
.navigationSlider {
margin-right: 80px;
}
.navigationSlider .slidingNav ul {
background: #222222;
}
.navigationSlider .slidingNav ul li a {
color: #c7d4fd;
}
.navigationSlider .slidingNav ul li a:hover,
.navigationSlider .slidingNav ul li a:focus {
color: #ffffff;
background-color: inherit;
}
.navigationSlider .slidingNav ul li.siteNavItemActive > a,
.navigationSlider .slidingNav ul li.siteNavGroupActive > a {
background-color: inherit;
}
.homeContainer {
background: rgb(2, 0, 36);
background: linear-gradient(
0deg,
rgba(2, 0, 36, 1),
rgba(255, 175, 0, 1) 0%,
rgba(129, 44, 229, 1) 100%
);
padding: 30px 0px;
}
.splashLogo {
display: block;
margin: 0 auto;
height: 200px;
width: 800px;
}
.projectTitle {
color: #ffffff;
font-variant: small-caps;
font-weight: 300;
}
.promoSection .button {
border: 2px solid #fff;
color: #ffffff;
font-size: 19px;
margin: 10px;
}
.promoSection .button:hover {
background: inherit;
border: 2px solid #ffffff;
color: #ffffff;
}
.landingPage {
padding: 0px;
}
.productShowcaseSection {
padding: 45px 20px 30px 20px;
}
div.productShowcaseSection {
color: #6c6c6c;
padding-top: 40px;
}
#quickstart {
padding-top: 80px;
}
.productShowcaseSection > h2 {
font-variant: small-caps;
font-weight: 360;
margin: 0px;
padding: 0px;
color: #5b1861;
}
.productShowcaseSection p {
font-weight: 360;
}
# Subtitles for key features
.productShowcaseSection .blockContent > div span p {
font-size: 18px;
}
.productShowcaseSection div.container {
padding: 40px 0px;
}
.productShowcaseSection img {
height: 100px;
}
.gridBlock .fourByGridBlock img {
max-width: 200%;
}
.productShowcaseSection li {
padding: 10px 0;
}
.productShowcaseSection pre {
margin: 10px 0;
}
.productShowcaseSection code {
background: #fff;
}
.container .wrapper .alignCenter h2 {
color: #222222;
}
div#quickstart {
background: #efefef;
}
div#quickstart ol {
margin-bottom: 0px;
}
.nav-footer {
background-color: #222222;
}
.nav-footer .sitemap a {
color: #c7d4fd;
}
.nav-footer .sitemap a:hover {
color: #ffffff;
}
.social {
text-align: center
}
a,
p a {
color: #4872f9;
}
a:hover,
p a:hover {
color: #4872f9;
}
.imageAlignTop .blockImage {
margin-bottom: 20px;
max-width: 200px;
}
/* Style tutorials */
.tutorialBody {
margin-top: -20px;
color: #6c6c6c;
}
.tutorialBody h1 {
margin: 0px;
}
.tutorialBody h1,
.tutorialBody h2,
.tutorialBody h3 {
color: #222222;
}
.tutorialBody pre {
font-family: 'IBM Plex Mono', monospace;
font-size: 14px;
margin: 0px;
}
.tutorialBody .input_prompt,
.tutorialBody .output_prompt {
color: darkred;
font-size: 12px;
}
.tutorialBody .highlight {
background: #f3f4f7;
padding: 10px 20px;
border: lightgray 1px solid;
border-radius: 3px;
}
.tutorialBody .cell {
margin: 20px;
}
.tutorialBody .output_stderr {
background-color: #fdede9;
}
.tutorialBody .anchor-link {
color: lightgray;
}
.tutorialBody iframe {
width: 100%;
height: 100vh;
}
.tutorialButtonWrapper,
.tutorialRuntime {
margin: 20px;
}
.tutorialButtonWrapper {
float: left;
margin: 5px;
}
.colabButtonWrapper {
float: left;
margin: 5px;
}
.colabButtonWrapper img {
padding-right: 0.25em;
}
.tutorialButtonsWrapper {
display: flex;
align-items: center;
}
/* .tutorialButton {
color: #4872f9;
border: 1px solid #4872f9;
}
*/
.tutorialButton svg {
height: 15px;
margin-right: 5px;
}
.tutorialButton:hover {
color: #4872f9;
background-color: inherit;
}
.wrapper {
max-width: 1400px;
}
@media only screen and (min-device-width: 360px) and (max-device-width: 736px) {
}
@media only screen and (min-width: 1024px) {
}
@media only screen and (max-width: 1023px) {
}
@media only screen and (min-width: 1400px) {
}
@media only screen and (min-width: 1500px) {
}

View File

@ -0,0 +1,209 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
**/
.highlight .hll {
background-color: #ffffcc;
}
.highlight .c {
color: #60a0b0;
font-style: italic;
} /* Comment */
.highlight .err {
border: 1px solid #ff0000;
} /* Error */
.highlight .k {
color: #007020;
font-weight: bold;
} /* Keyword */
.highlight .o {
color: #666666;
} /* Operator */
.highlight .cm {
color: #60a0b0;
font-style: italic;
} /* Comment.Multiline */
.highlight .cp {
color: #007020;
} /* Comment.Preproc */
.highlight .c1 {
color: #60a0b0;
font-style: italic;
} /* Comment.Single */
.highlight .cs {
color: #60a0b0;
background-color: #fff0f0;
} /* Comment.Special */
.highlight .gd {
color: #a00000;
} /* Generic.Deleted */
.highlight .ge {
font-style: italic;
} /* Generic.Emph */
.highlight .gr {
color: #ff0000;
} /* Generic.Error */
.highlight .gh {
color: #000080;
font-weight: bold;
} /* Generic.Heading */
.highlight .gi {
color: #00a000;
} /* Generic.Inserted */
.highlight .go {
color: #808080;
} /* Generic.Output */
.highlight .gp {
color: #c65d09;
font-weight: bold;
} /* Generic.Prompt */
.highlight .gs {
font-weight: bold;
} /* Generic.Strong */
.highlight .gu {
color: #800080;
font-weight: bold;
} /* Generic.Subheading */
.highlight .gt {
color: #0040d0;
} /* Generic.Traceback */
.highlight .kc {
color: #007020;
font-weight: bold;
} /* Keyword.Constant */
.highlight .kd {
color: #007020;
font-weight: bold;
} /* Keyword.Declaration */
.highlight .kn {
color: #007020;
font-weight: bold;
} /* Keyword.Namespace */
.highlight .kp {
color: #007020;
} /* Keyword.Pseudo */
.highlight .kr {
color: #007020;
font-weight: bold;
} /* Keyword.Reserved */
.highlight .kt {
color: #902000;
} /* Keyword.Type */
.highlight .m {
color: #40a070;
} /* Literal.Number */
.highlight .s {
color: #4070a0;
} /* Literal.String */
.highlight .na {
color: #4070a0;
} /* Name.Attribute */
.highlight .nb {
color: #007020;
} /* Name.Builtin */
.highlight .nc {
color: #0e84b5;
font-weight: bold;
} /* Name.Class */
.highlight .no {
color: #60add5;
} /* Name.Constant */
.highlight .nd {
color: #555555;
font-weight: bold;
} /* Name.Decorator */
.highlight .ni {
color: #d55537;
font-weight: bold;
} /* Name.Entity */
.highlight .ne {
color: #007020;
} /* Name.Exception */
.highlight .nf {
color: #06287e;
} /* Name.Function */
.highlight .nl {
color: #002070;
font-weight: bold;
} /* Name.Label */
.highlight .nn {
color: #0e84b5;
font-weight: bold;
} /* Name.Namespace */
.highlight .nt {
color: #062873;
font-weight: bold;
} /* Name.Tag */
.highlight .nv {
color: #bb60d5;
} /* Name.Variable */
.highlight .ow {
color: #007020;
font-weight: bold;
} /* Operator.Word */
.highlight .w {
color: #bbbbbb;
} /* Text.Whitespace */
.highlight .mf {
color: #40a070;
} /* Literal.Number.Float */
.highlight .mh {
color: #40a070;
} /* Literal.Number.Hex */
.highlight .mi {
color: #40a070;
} /* Literal.Number.Integer */
.highlight .mo {
color: #40a070;
} /* Literal.Number.Oct */
.highlight .sb {
color: #4070a0;
} /* Literal.String.Backtick */
.highlight .sc {
color: #4070a0;
} /* Literal.String.Char */
.highlight .sd {
color: #4070a0;
font-style: italic;
} /* Literal.String.Doc */
.highlight .s2 {
color: #4070a0;
} /* Literal.String.Double */
.highlight .se {
color: #4070a0;
font-weight: bold;
} /* Literal.String.Escape */
.highlight .sh {
color: #4070a0;
} /* Literal.String.Heredoc */
.highlight .si {
color: #70a0d0;
font-style: italic;
} /* Literal.String.Interpol */
.highlight .sx {
color: #c65d09;
} /* Literal.String.Other */
.highlight .sr {
color: #235388;
} /* Literal.String.Regex */
.highlight .s1 {
color: #4070a0;
} /* Literal.String.Single */
.highlight .ss {
color: #517918;
} /* Literal.String.Symbol */
.highlight .bp {
color: #007020;
} /* Name.Builtin.Pseudo */
.highlight .vc {
color: #bb60d5;
} /* Name.Variable.Class */
.highlight .vg {
color: #bb60d5;
} /* Name.Variable.Global */
.highlight .vi {
color: #bb60d5;
} /* Name.Variable.Instance */
.highlight .il {
color: #40a070;
} /* Literal.Number.Integer.Long */

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="110px" height="100px" viewBox="0 0 110 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
<title>Group 3</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-190.000000, -85.000000)">
<g id="Group-3" transform="translate(190.000000, 85.000000)">
<rect id="Rectangle" fill="#FF7D1E" x="60" y="3" width="44" height="44"></rect>
<ellipse id="Oval" fill="#000000" cx="84.5108694" cy="75.9893615" rx="24.5108694" ry="23.9893615"></ellipse>
<polygon id="Triangle" fill="#FFAF00" points="28.5 53 57 98 0 98"></polygon>
<polygon id="Polygon" fill="#812CE5" points="26.5099999 0 51.7225081 17.9587837 42.0921869 47.0167063 10.9278129 47.0167063 1.29749175 17.9587837"></polygon>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
website/static/img/ops.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="176px" height="175px" viewBox="0 0 176 175" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-413.000000, -451.000000)">
<g id="Group-2" transform="translate(422.000000, 456.000000)">
<g id="Group-4" transform="translate(39.000000, 64.499932)" fill="#FFFFFF" stroke="#812CE5" stroke-linecap="round" stroke-linejoin="round" stroke-width="8">
<path d="M0,22 L20,0" id="Line-4"></path>
<path d="M0,23 L22,42" id="Line-4"></path>
</g>
<g id="Group-4" transform="translate(105.000000, 85.499932) scale(-1, 1) translate(-105.000000, -85.499932) translate(94.000000, 64.499932)" fill="#FFFFFF" stroke="#812CE5" stroke-linecap="round" stroke-linejoin="round" stroke-width="8">
<path d="M0,22 L20,0" id="Line-4"></path>
<path d="M0,23 L22,42" id="Line-4"></path>
</g>
<path d="M72,106.499932 L83,65.4999323" id="Line-4" stroke="#812CE5" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
<path id="Line-9" d="M74.4859874,86.9999949 L75.5383535,87.0032598 C103.773173,87.2063259 125.510981,96.896589 140.284811,116.02653 L159.026859,108.8732 C160.688876,108.238748 162.550533,109.071754 163.184985,110.733771 C163.363327,111.200957 163.430447,111.70325 163.381029,112.200872 L163.381029,112.200872 L158.126597,165.110922 C157.950791,166.881211 156.37317,168.173795 154.602881,167.99799 C153.90933,167.929114 153.256827,167.637149 152.743311,167.165918 L152.743311,167.165918 L113.56793,131.216342 C112.257182,130.013524 112.169687,127.975877 113.372505,126.665129 C113.710612,126.296683 114.12986,126.012017 114.597046,125.833674 L114.597046,125.833674 L130.458207,119.778029 C117.558504,104.578587 99.0874369,97 74.6296296,97 L74.6296296,97 L73.0820878,97.004911 C66.4718147,97.0540006 62.2741863,97.4876879 56.5279179,99.0603259 C47.7855392,101.452939 38.689293,106.123227 28.9324354,113.829564 C14.5080834,125.222466 6.51709607,142.264661 4.98906448,165.330508 C4.80652993,168.085892 2.42487619,170.171599 -0.330508042,169.989064 C-3.08589227,169.80653 -5.17159904,167.424876 -4.98906448,164.669492 C-3.28379511,138.928216 5.94743978,119.240974 22.7342313,105.982127 C33.5277551,97.4569916 43.8289935,92.1680242 53.888193,89.4150238 C60.6332478,87.5690381 65.5743724,87.0613052 72.9723676,87.0054117 L72.9723676,87.0054117 L74.4859874,86.9999949 Z" fill="#FFAF00" fill-rule="nonzero"></path>
<path id="Line-9" d="M76.486002,-5.0000054 L77.5660101,-4.99635656 C106.765823,-4.76855288 129.01092,6.14121529 143.768839,27.5954736 L162.584107,21.0066878 C164.263104,20.4186391 166.100907,21.3030272 166.688956,22.9820238 C166.854254,23.4539832 166.907398,23.9579467 166.844178,24.4540036 L166.844178,24.4540036 L160.12231,77.1977136 C159.897407,78.9624371 158.284495,80.210708 156.519772,79.9858046 C155.828401,79.8976935 155.184258,79.5877189 154.684028,79.1024075 L154.684028,79.1024075 L116.522181,42.0786869 C115.245344,40.8399301 115.214474,38.8006385 116.453231,37.5238017 C116.801441,37.1648878 117.228433,36.8919753 117.700392,36.7266771 L117.700392,36.7266771 L133.937253,31.0392764 C120.964757,13.6380026 102.023945,5 76.6296296,5 L76.6296296,5 L75.1288112,5.004828 C68.513673,5.05473503 64.3301462,5.50847659 58.5948099,7.16413065 C49.8731212,9.68187305 40.7881482,14.601962 31.0337645,22.7285034 C16.5631727,34.784197 8.52566138,52.8648677 6.99016787,77.3134081 C6.81707736,80.0694017 4.44258552,82.1632584 1.68659191,81.9901679 C-1.06940171,81.8170774 -3.16325838,79.4425855 -2.99016787,76.6865919 C-1.29236043,49.6536455 7.89235048,28.9923081 24.6329022,15.0454726 C35.4288998,6.05114514 45.7414116,0.466266085 55.821301,-2.44355631 C62.5896722,-4.39742276 67.5506001,-4.93507734 74.9684167,-4.99426877 L74.9684167,-4.99426877 L76.486002,-5.0000054 Z" fill="#FFAF00" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1 @@
<svg id="CrypTen_Symbol_Logos" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><defs><style>.cls-1{fill:#fff;}</style></defs><title>PyTorch3D_Identity_Symbol</title><path class="cls-1" d="M180.57,50H61.7V250H180.57L238.3,150ZM162.84,233.91H99.77l63.07-36.41Zm-85-5.89V72l85.05,49.11v57.82ZM162.84,102.5,99.77,66.09h63.07Zm16.09,27.88,34,19.62-34,19.62ZM207,128l-28.1-16.23V79.35Zm-28.1,92.63V188.21L207,172Z"/></svg>

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1 @@
<svg id="CrypTen_Horizontal_Logos" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1300 330"><defs><style>.cls-1{fill:#ffb000;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);}</style><linearGradient id="linear-gradient" x1="130.95" y1="257.01" x2="198.97" y2="70.13" gradientUnits="userSpaceOnUse"><stop offset="0.28" stop-color="#ffb000"/><stop offset="0.75" stop-color="#812ce5"/></linearGradient><linearGradient id="linear-gradient-2" x1="173.52" y1="233.48" x2="226.58" y2="87.7" gradientUnits="userSpaceOnUse"><stop offset="0.2" stop-color="#ffb000"/><stop offset="0.85" stop-color="#812ce5"/></linearGradient></defs><title>PyTorch3D_Identity_Horizontal_Lockup</title><path d="M336.72,184.41l-18.53.22v48h-14V96.34h34.23c36,0,53.19,17.44,53.19,42.51C391.65,168.71,370.51,184,336.72,184.41ZM338,109.2H318.19v62.56l19.4-.43c25.72-.44,39.67-10.68,39.67-31.83C377.26,120.1,363.53,109.2,338,109.2Z"/><path d="M452.45,231.5l-8.07,21.58c-9.15,24.42-18.74,31.39-32.26,31.39-7.63,0-13.3-2-19.4-4.58l4.14-12.42c4.8,2.61,9.81,4.36,15.26,4.36,7.63,0,13.3-4.14,20.49-23.11l6.76-17.66-39-98.32H415l31.4,82.41,30.74-82.41h14.17Z"/><path d="M533.87,109.42V232.59h-14V109.42H472V96.34H581.83v13.08Z"/><path d="M617.76,235.42c-27.69,0-48.18-20.49-48.18-52.54,0-31.83,21.36-53,49.27-53s48,20.49,48,52.54C666.81,214.28,645.44,235.42,617.76,235.42Zm.43-93.3c-21.14,0-35.1,16.78-35.1,40.33,0,24.41,14.17,40.76,35.32,40.76s35.1-16.78,35.1-40.33C653.51,158.47,639.34,142.12,618.19,142.12Z"/><path d="M698.48,232.59H685V132.74l13.52-2.83v21.36c6.54-12.86,16.35-21.36,29.43-21.36a36.22,36.22,0,0,1,17.44,4.58l-3.49,12.64a29.68,29.68,0,0,0-15.26-4.36c-10.46,0-20.27,7.85-28.12,25.73Z"/><path d="M796.18,235.42c-30.08,0-48.83-21.58-48.83-52.54,0-31.17,20.71-53,49-53,12.21,0,22.67,3.05,31.18,8.5l-3.49,12.21a50.39,50.39,0,0,0-27.69-8.07c-21.58,0-35.1,16.13-35.1,39.9,0,24.41,14.17,40.33,35.32,40.33a51.66,51.66,0,0,0,27.69-8.29l2.83,12.43A59.72,59.72,0,0,1,796.18,235.42Z"/><path d="M908.65,232.59V168.06c0-17.44-7-25.29-21.37-25.29-11.55,0-22.67,5.89-30.95,14.17v75.65H842.81V85.65l13.52-2.83v63c10.46-10.46,23.54-15.91,34.66-15.91,19.4,0,31.18,12.42,31.18,34.22v68.46Z"/><path class="cls-1" d="M1023.12,194.44c0,25.72-21.8,41-48,41-12.65,0-27-3.92-36-8.94l3.27-12.2A70,70,0,0,0,975.59,223c17.88,0,33.79-9.6,33.79-27.47,0-15-12.42-25.51-32.91-25.51a113.19,113.19,0,0,0-18.75,1.74V160.43c29.86-7.63,46.87-17.22,46.87-33.14,0-13.51-10.68-21.36-26.82-21.36-11.33,0-24.41,5.45-33.35,13.51l-5-11.77C949,99.82,963.82,93.5,978,93.5c24.2,0,40.33,12.65,40.33,32.7,0,16.13-12,27.69-35.53,34.88C1009.17,160.43,1023.12,176.13,1023.12,194.44Z"/><path class="cls-1" d="M1082.33,232.59h-36V96.34h37.06c44.69,0,72.16,27,72.16,67.14C1155.58,206.43,1128.76,232.59,1082.33,232.59Zm.22-123.39h-22.24V219.73H1083c34.88,0,58.64-17.88,58.64-55.16C1141.62,129.91,1119.82,109.2,1082.55,109.2Z"/><path class="cls-2" d="M208.48,73.59H105.06v174H208.48l50.23-87Zm28.14,87L119.06,228.46V92.71Zm-5.12-19.13L138.18,87.59h62.21Zm-31.11,92.13H138.18l93.32-53.88Z"/><rect class="cls-3" x="193.05" y="80.59" width="14" height="160"/></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1 @@
<svg id="CrypTen_Horizontal_Logos" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1300 330"><defs><style>.cls-1{fill:#fff;}</style></defs><title>PyTorch3D_Identity_Horizontal_Lockup</title><path class="cls-1" d="M336.72,184.41l-18.53.22v48h-14V96.34h34.23c36,0,53.19,17.44,53.19,42.51C391.65,168.71,370.51,184,336.72,184.41ZM338,109.2H318.19v62.56l19.4-.43c25.72-.44,39.67-10.68,39.67-31.83C377.26,120.1,363.53,109.2,338,109.2Z"/><path class="cls-1" d="M452.45,231.5l-8.07,21.58c-9.15,24.42-18.74,31.39-32.26,31.39-7.63,0-13.3-2-19.4-4.58l4.14-12.42c4.8,2.61,9.81,4.36,15.26,4.36,7.63,0,13.3-4.14,20.49-23.11l6.76-17.66-39-98.32H415l31.4,82.41,30.74-82.41h14.17Z"/><path class="cls-1" d="M533.87,109.42V232.59h-14V109.42H472V96.34H581.83v13.08Z"/><path class="cls-1" d="M617.76,235.42c-27.69,0-48.18-20.49-48.18-52.54,0-31.83,21.36-53,49.27-53s48,20.49,48,52.54C666.81,214.28,645.44,235.42,617.76,235.42Zm.43-93.3c-21.14,0-35.1,16.78-35.1,40.33,0,24.41,14.17,40.76,35.32,40.76s35.1-16.78,35.1-40.33C653.51,158.47,639.34,142.12,618.19,142.12Z"/><path class="cls-1" d="M698.48,232.59H685V132.74l13.52-2.83v21.36c6.54-12.86,16.35-21.36,29.43-21.36a36.22,36.22,0,0,1,17.44,4.58l-3.49,12.64a29.68,29.68,0,0,0-15.26-4.36c-10.46,0-20.27,7.85-28.12,25.73Z"/><path class="cls-1" d="M796.18,235.42c-30.08,0-48.83-21.58-48.83-52.54,0-31.17,20.71-53,49-53,12.21,0,22.67,3.05,31.18,8.5l-3.49,12.21a50.39,50.39,0,0,0-27.69-8.07c-21.58,0-35.1,16.13-35.1,39.9,0,24.41,14.17,40.33,35.32,40.33a51.66,51.66,0,0,0,27.69-8.29l2.83,12.43A59.72,59.72,0,0,1,796.18,235.42Z"/><path class="cls-1" d="M908.65,232.59V168.06c0-17.44-7-25.29-21.37-25.29-11.55,0-22.67,5.89-30.95,14.17v75.65H842.81V85.65l13.52-2.83v63c10.46-10.46,23.54-15.91,34.66-15.91,19.4,0,31.18,12.42,31.18,34.22v68.46Z"/><path class="cls-1" d="M1023.12,194.44c0,25.72-21.8,41-48,41-12.65,0-27-3.92-36-8.94l3.27-12.2A70,70,0,0,0,975.59,223c17.88,0,33.79-9.6,33.79-27.47,0-15-12.42-25.51-32.91-25.51a113.19,113.19,0,0,0-18.75,1.74V160.43c29.86-7.63,46.87-17.22,46.87-33.14,0-13.51-10.68-21.36-26.82-21.36-11.33,0-24.41,5.45-33.35,13.51l-5-11.77C949,99.82,963.82,93.5,978,93.5c24.2,0,40.33,12.65,40.33,32.7,0,16.13-12,27.69-35.53,34.88C1009.17,160.43,1023.12,176.13,1023.12,194.44Z"/><path class="cls-1" d="M1082.33,232.59h-36V96.34h37.06c44.69,0,72.16,27,72.16,67.14C1155.58,206.43,1128.76,232.59,1082.33,232.59Zm.22-123.39h-22.24V219.73H1083c34.88,0,58.64-17.88,58.64-55.16C1141.62,129.91,1119.82,109.2,1082.55,109.2Z"/><path class="cls-1" d="M208.48,73.59H105.06v174H208.48l50.23-87Zm23,67.87-24.45-14.11V99.12Zm5.12,19.13-29.57,17.07V143.52Zm-43.57-73v31.68L138.18,87.59Zm-74,5.12,74,42.72v50.31l-74,42.72Zm74,109.2v31.68H138.18Zm14,20.14V193.83l24.45-14.12Z"/></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="185px" height="127px" viewBox="0 0 185 127" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
<title>Group 4</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-85.000000, -519.000000)">
<g id="Group-4" transform="translate(89.000000, 519.000000)">
<rect id="Rectangle" fill="#812CE5" x="2" y="0" width="175" height="127" rx="9"></rect>
<circle id="Oval" stroke="#FFFFFF" stroke-width="5" fill="#812CE5" cx="148" cy="31" r="14"></circle>
<path d="M0,86 L45,31" id="Line-4" stroke="#FFFFFF" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M70,93 L45,31" id="Line-4" stroke="#FFFFFF" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M70,93 L96,67" id="Line-4" stroke="#FFFFFF" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M128.467742,94 L96.5322581,67" id="Line-4" stroke="#FFFFFF" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M128.5,94 L177,75" id="Line-4" stroke="#FFFFFF" stroke-width="8" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

20
website/tutorials.json Normal file
View File

@ -0,0 +1,20 @@
{
"3D operators": [
{
"id": "deform_source_mesh_to_target_mesh",
"title": "Fit Mesh"
},{
"id": "bundle_adjustment",
"title": "Bundle Adjustment"
}
],
"Rendering": [
{
"id": "render_textured_meshes",
"title": "Render Textured Meshes"
}, {
"id": "camera_position_optimization_with_differentiable_rendering",
"title": "Camera Position Optimization"
}
]
}