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
13
.gitignore
vendored
@ -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
|
||||
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 272 KiB |
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 314 KiB |
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
13
docs/notes/why_pytorch3d.md
Normal 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.
|
||||
|
@ -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",
|
||||
"\n",
|
||||
"\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",
|
||||
"\n",
|
||||
"\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",
|
||||
|
60
scripts/build_website.sh
Normal 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
@ -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)
|
46
scripts/publish_website.sh
Normal 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
@ -0,0 +1,2 @@
|
||||
*/node_modules
|
||||
*.log
|
13
website/.gitignore
vendored
Normal 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
@ -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
@ -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
@ -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;
|
88
website/core/TutorialSidebar.js
Normal 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
@ -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
@ -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
@ -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
@ -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;
|
49
website/pages/tutorials/index.js
Normal 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
@ -0,0 +1,7 @@
|
||||
{
|
||||
"docs": {
|
||||
"Introduction": ["why_pytorch3d"],
|
||||
"Meshes": ["batching", "meshes_io"],
|
||||
"Differentiable Renderer": ["renderer", "renderer_getting_started"]
|
||||
}
|
||||
}
|
86
website/siteConfig.js
Normal 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;
|
308
website/static/css/custom.css
Normal 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) {
|
||||
}
|
209
website/static/css/pygments.css
Normal 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 */
|
16
website/static/img/batching.svg
Normal 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 |
BIN
website/static/img/favicon.ico
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
website/static/img/ops.png
Normal file
After Width: | Height: | Size: 10 KiB |
23
website/static/img/ops.svg
Normal 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 |
BIN
website/static/img/oss_logo.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
website/static/img/pytorch3dfavicon.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
1
website/static/img/pytorch3dicon.svg
Normal 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 |
BIN
website/static/img/pytorch3dlogo.png
Normal file
After Width: | Height: | Size: 24 KiB |
1
website/static/img/pytorch3dlogo.svg
Normal 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 |
1
website/static/img/pytorch3dlogowhite.svg
Normal 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 |
BIN
website/static/img/rendering.png
Normal file
After Width: | Height: | Size: 12 KiB |
19
website/static/img/rendering.svg
Normal 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
@ -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"
|
||||
}
|
||||
]
|
||||
}
|