73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
from typing import TypeAlias
|
|
from random import uniform
|
|
|
|
import torch
|
|
|
|
Point: TypeAlias = torch.FloatTensor
|
|
Vector: TypeAlias = Point
|
|
Color: TypeAlias = torch.FloatTensor
|
|
|
|
|
|
def indexize_tensor(tensor, eps=1e-5):
|
|
"""Take tensor of quads to flat list of points plus index map."""
|
|
tensor_shape = tensor.shape
|
|
tensor = tensor.view(-1, tensor_shape[-1])
|
|
|
|
# Round tensor elements to handle floating point precision errors
|
|
tensor = torch.round(tensor / eps) * eps
|
|
|
|
# Compute unique rows and their indices
|
|
tensor, inverse_indices = tensor.unique(dim=0, return_inverse=True)
|
|
|
|
# Compute index tensor
|
|
index_tensor = inverse_indices.view(tensor_shape[:-1])
|
|
|
|
return tensor, index_tensor
|
|
|
|
|
|
def ferguson_to_bezier(corner_points, tangent_vectors):
|
|
"""Take Ferguson patch to Bezier representation"""
|
|
# Assume corner_points is a list of 4 points [P0, P1, P2, P3] and
|
|
# tangent_vectors is a list of 4 vectors [V0, V1, V2, V3]
|
|
|
|
# Bezier control points
|
|
bezier_points = [None]*12
|
|
|
|
# Use tangent vectors to determine interior points and place them in the order
|
|
for i in range(4):
|
|
bezier_points[3*i] = corner_points[i]
|
|
bezier_points[3*i + 1] = corner_points[i] + tangent_vectors[i]/3
|
|
bezier_points[3*i + 2] = corner_points[i] + 2*tangent_vectors[i]/3
|
|
|
|
return bezier_points
|
|
|
|
|
|
class Mesh:
|
|
def __init__(self, points, tangents, colors):
|
|
self.fpoints, self.ipoints = indexize_tensor(points)
|
|
self.ftangents, self.itangents = indexize_tensor(tangents)
|
|
self.colors = colors
|
|
|
|
@classmethod
|
|
def grid(cls, width, height):
|
|
dx = 1.0 / width
|
|
dy = 1.0 / height
|
|
points = []
|
|
tangents = []
|
|
colors = []
|
|
for i in range(width):
|
|
for j in range(height):
|
|
x1, y1 = i * dx, j * dy
|
|
x2, y2 = (i+1) * dx, (j+1) * dy
|
|
# Clockwise order: bottom left, bottom right, top right, top left
|
|
square = [[x1, y1], [x2, y1], [x2, y2], [x1, y2]]
|
|
points.append(square)
|
|
tangents.append([[0.0, 0.0] for _ in range(4)])
|
|
colors.append([uniform(0, 1) for _ in range(3)] + [1.0])
|
|
|
|
return cls(torch.tensor(points),
|
|
torch.tensor(tangents),
|
|
torch.tensor(colors))
|