Skip to content

Commit 3eb2033

Browse files
committed
Add support for specifying UV coordinates of vector models
1 parent efd3eb4 commit 3eb2033

File tree

4 files changed

+34
-12
lines changed

4 files changed

+34
-12
lines changed

docs/canvas3d.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,10 @@ To create a mesh from scratch use the attributes:
856856
: Optional attribute providing a *3m*-vector of vertex numbers in the range
857857
*[0,n)*, representing the corner vertices of *m* triangular faces.
858858

859+
`uv=` *UV*
860+
: Optional attribute providing a *2n*-vector of *u* and *v* texture-mapping
861+
coordinates for *n* vertices.
862+
859863
If the `faces` attribute is not provided, then a convex hull will be computed
860864
around the given vertices. This provides a quick way of describing simple
861865
geometric forms.
@@ -866,12 +870,12 @@ anti-clockwise direction – as viewed from outside the model – for the surfa
866870
normals to be computed correctly.
867871
:::
868872

869-
Models created from `vertices` and `faces` are cached according to the specific
873+
Models created from `vertices`/`faces`/`uv` are cached according to the specific
870874
values provided. This means that, as long as the attribute values do not change,
871875
the model will be constructed once and reused. However, these models are cached
872876
less aggressively than other models and will be immediately unloaded if not
873877
used. This allows animated surfaces to be created by continuously varying the
874-
`vertices` (and `faces`) attributes without using huge amounts of memory.
878+
attributes without using huge amounts of memory.
875879

876880
### Controlling Model Shading
877881

src/flitter/render/window/canvas3d.pyx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ cdef inline Matrix44 get_model_transform(Node node, Matrix44 transform_matrix):
448448
cdef Model get_model(Node node, bint top):
449449
cdef Node child
450450
cdef Model model = None
451-
cdef Vector origin, normal, function, minimum, maximum, vertices, faces
451+
cdef Vector origin, normal, function, minimum, maximum, vertices, faces, uv
452452
cdef double snap_angle, resolution
453453
cdef str mapping, filename
454454
cdef list models
@@ -464,10 +464,11 @@ cdef Model get_model(Node node, bint top):
464464
filename = node.get_str('filename', None)
465465
vertices = node.get_fvec('vertices', 0, None)
466466
faces = node.get_fvec('faces', 0, None)
467+
uv = node.get_fvec('uv', 0, None)
467468
if filename:
468469
model = Model._external(filename)
469470
elif vertices is not None:
470-
model = Model._vector(vertices, faces)
471+
model = Model._vector(vertices, faces, uv)
471472
if model is not None and node.get_bool('repair', False):
472473
model = model.repair()
473474
elif not top and node.kind is 'transform':

src/flitter/render/window/models.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ cdef class Model:
6666
cdef Model _external(str filename)
6767

6868
@staticmethod
69-
cdef Model _vector(Vector vertices, Vector faces)
69+
cdef Model _vector(Vector vertices, Vector faces, Vector uv)
7070

7171
@staticmethod
7272
cdef Model _sdf(Function function, Model original, Vector minimum, Vector maximum, double resolution)

src/flitter/render/window/models.pyx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,12 @@ cdef class Model:
433433
return ExternalModel._get(str(filename))
434434

435435
@staticmethod
436-
cdef Model _vector(Vector vertices, Vector faces):
437-
return VectorModel._get(vertices, faces)
436+
cdef Model _vector(Vector vertices, Vector faces, Vector uv):
437+
return VectorModel._get(vertices, faces, uv)
438438

439439
@staticmethod
440-
def vector(vertices, faces=None):
441-
return VectorModel._get(Vector._coerce(vertices), Vector._coerce(faces))
440+
def vector(vertices, faces=None, uv=None):
441+
return VectorModel._get(Vector._coerce(vertices), Vector._coerce(faces), Vector._coerce(uv))
442442

443443
@staticmethod
444444
cdef Model _sdf(Function function, Model original, Vector minimum, Vector maximum, double resolution):
@@ -1615,24 +1615,30 @@ cdef class ExternalModel(Model):
16151615
cdef class VectorModel(Model):
16161616
cdef Vector vertices
16171617
cdef Vector faces
1618+
cdef Vector uv
16181619

16191620
@staticmethod
1620-
cdef VectorModel _get(Vector vertices, Vector faces):
1621+
cdef VectorModel _get(Vector vertices, Vector faces, Vector uv):
16211622
if vertices is None or vertices.numbers == NULL:
16221623
return None
16231624
if faces is not None and faces.numbers == NULL:
16241625
faces = None
1626+
if uv is not None and uv.numbers == NULL:
1627+
uv = None
16251628
cdef uint64_t id = VECTOR
16261629
id = HASH_UPDATE(id, vertices.hash(False))
16271630
if faces is not None:
16281631
id = HASH_UPDATE(id, faces.hash(False))
1632+
if uv is not None:
1633+
id = HASH_UPDATE(id, uv.hash(False))
16291634
cdef VectorModel model
16301635
cdef PyObject* objptr = PyDict_GetItem(ModelCache, id)
16311636
if objptr == NULL:
16321637
model = VectorModel.__new__(VectorModel)
16331638
model.id = id
16341639
model.vertices = vertices
16351640
model.faces = faces
1641+
model.uv = uv
16361642
ModelCache[id] = model
16371643
else:
16381644
model = <VectorModel>objptr
@@ -1641,9 +1647,13 @@ cdef class VectorModel(Model):
16411647

16421648
@property
16431649
def name(self):
1650+
cdef str name = f'vector({self.vertices.hash(False):x}'
16441651
if self.faces is not None:
1645-
return f'vector({self.vertices.hash(False):x}, {self.faces.hash(False):x})'
1646-
return f'vector({self.vertices.hash(False):x})'
1652+
name += f', faces={self.faces.hash(False):x}'
1653+
if self.uv is not None:
1654+
name += f', uv={self.uv.hash(False):x}'
1655+
name += ')'
1656+
return name
16471657

16481658
cpdef void check_for_changes(self):
16491659
pass
@@ -1678,6 +1688,13 @@ cdef class VectorModel(Model):
16781688
vertices[i, 0] = <float>self.vertices.numbers[i*3]
16791689
vertices[i, 1] = <float>self.vertices.numbers[i*3+1]
16801690
vertices[i, 2] = <float>self.vertices.numbers[i*3+2]
1691+
if self.uv is not None:
1692+
if self.uv.length != n*2:
1693+
logger.error("Bad uv vector length: {}", self.name)
1694+
return None
1695+
for i in range(n):
1696+
vertices[i, 6] = <float>self.uv.numbers[i*2]
1697+
vertices[i, 7] = <float>self.uv.numbers[i*2+1]
16811698
if self.faces is None:
16821699
points = trimesh.points.PointCloud(vertices=vertices_array[:, :3]).convex_hull
16831700
faces_array = np.array(points.faces, dtype='i4')

0 commit comments

Comments
 (0)