Skip to content

Commit

Permalink
Merge pull request #70 from jonathanhogg/enh_model_hash_ids
Browse files Browse the repository at this point in the history
Identify 3D models using an integer ID instead of a name (+ other fixes, performance improvements and testing)
  • Loading branch information
jonathanhogg authored Jan 2, 2025
2 parents 3b11d80 + 6541036 commit 7b8045e
Show file tree
Hide file tree
Showing 10 changed files with 513 additions and 252 deletions.
6 changes: 5 additions & 1 deletion examples/sdf.fl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@

-- This is the same as the internal SDF function for !cone, but slower
func cone(p)
max(hypot(p[..2])+p[2], abs(p[2]))-0.5

!window size=1080
!record filename=(OUTPUT if frame == run_time * fps - 1)
!canvas3d samples=4
Expand All @@ -13,7 +17,7 @@
!cone
for i in ..2
!transform rotate_x=0.25+i/2 translate=0;0;0.7 scale=0.3;0.3;0.6
!cone
!sdf function=cone
!trim normal=0;1;0 origin=0;0.25;0 smooth=0.1
!difference chamfer=0.05
!intersect fillet=0.1
Expand Down
18 changes: 17 additions & 1 deletion src/flitter/language/vm.pxd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from cpython cimport PyObject

from libc.stdint cimport int64_t
from libc.stdint cimport int64_t, uint64_t

from ..model cimport Vector, Node, Context

Expand Down Expand Up @@ -31,6 +31,22 @@ cdef class VectorStack:
cpdef void poke_at(self, int64_t offset, Vector vector)


cdef class Function:
cdef readonly str __name__
cdef readonly Vector vself
cdef readonly tuple parameters
cdef readonly tuple defaults
cdef readonly Program program
cdef readonly int64_t address
cdef readonly bint record_stats
cdef readonly tuple captures
cdef readonly int64_t call_depth
cdef readonly uint64_t _hash

cdef uint64_t hash(self)
cdef Vector call_one_fast(self, Context context, Vector arg)


cdef enum OpCode:
Add
Append
Expand Down
39 changes: 26 additions & 13 deletions src/flitter/language/vm.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -479,21 +479,19 @@ cdef inline void poke_at(VectorStack stack, int64_t offset, Vector vector):


cdef class Function:
cdef readonly str __name__
cdef readonly Vector vself
cdef readonly tuple parameters
cdef readonly tuple defaults
cdef readonly Program program
cdef readonly int64_t address
cdef readonly bint record_stats
cdef readonly tuple captures
cdef readonly int64_t call_depth
cdef readonly int64_t hash
cdef uint64_t hash(self):
if self._hash == 0:
self._hash = <uint64_t>(id(self.program) ^ self.address ^ hash(self.defaults) ^ hash(self.captures))
return self._hash

def __hash__(self):
if self.hash == 0:
self.hash = id(self.program) ^ self.address ^ hash(self.defaults) ^ hash(self.captures)
return self.hash
return self.hash()

def __repr__(self):
return f'<Function: {self.__name__}>'

def __str__(self):
return self.__name__

def __call__(self, Context context, *args, **kwargs):
if self.call_depth == MAX_CALL_DEPTH:
Expand Down Expand Up @@ -532,6 +530,21 @@ cdef class Function:
assert lnames.top == lnames_top, "Bad function return lnames"
return result

cdef Vector call_one_fast(self, Context context, Vector arg):
cdef int64_t i, k=PyTuple_GET_SIZE(self.captures), m=PyTuple_GET_SIZE(self.parameters)
cdef VectorStack lnames = context.lnames
cdef VectorStack stack = context.stack
for i in range(k):
push(lnames, <Vector>PyTuple_GET_ITEM(self.captures, i))
push(lnames, self.vself)
if m:
push(lnames, arg)
for i in range(1, m):
push(lnames, <Vector>PyTuple_GET_ITEM(self.defaults, i))
self.program._execute(context, self.address, self.record_stats)
drop(lnames, k + 1 + m)
return pop(stack)


cdef class LoopSource:
cdef Vector source
Expand Down
7 changes: 6 additions & 1 deletion src/flitter/model.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ cdef inline uint64_t HASH_UPDATE(uint64_t _hash, uint64_t y) noexcept:


# FNV-1a hash algorithm [https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function#FNV-1a_hash]
cdef inline uint64_t HASH_STRING(str value):
cdef inline uint64_t HASH_STRING(str value) noexcept:
cdef void* data = PyUnicode_DATA(value)
cdef uint64_t i, n=PyUnicode_GET_LENGTH(value), kind=PyUnicode_KIND(value)
cdef Py_UCS4 c
Expand All @@ -32,6 +32,11 @@ cdef inline uint64_t HASH_STRING(str value):
return y


cdef union double_long:
double f
uint64_t l


cdef class Vector:
cdef int64_t length
cdef tuple objects
Expand Down
5 changes: 0 additions & 5 deletions src/flitter/model.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ cdef dict SymbolTable = {}
cdef dict ReverseSymbolTable = {}


cdef union double_long:
double f
uint64_t l


cdef inline int64_t vector_compare(Vector left, Vector right) noexcept:
if left is right:
return 0
Expand Down
3 changes: 2 additions & 1 deletion src/flitter/render/window/canvas3d.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ from ...model cimport Node, Vector, Matrix44, Matrix33, Quaternion, null_, true_
from .models cimport Model, DefaultSegments, DefaultSnapAngle
from .target import RenderTarget, COLOR_FORMATS
from ...plugins import get_plugin
from ...language.vm import Function


logger = name_patch(logger, __name__)
Expand Down Expand Up @@ -493,7 +494,7 @@ cdef Model get_model(Node node, bint top):
minimum = node.get_fvec('minimum', 3, node.get_fvec('min', 3, maximum.neg()))
resolution = node.get_float('resolution', (maximum.maximum() - minimum.minimum()) / 100)
if 'function' in node and (function := node['function']) and function.length == 1 and \
function.objects is not None and callable(f := function.objects[0]):
function.objects is not None and isinstance(f := function.objects[0], Function):
model = Model._sdf(f, None, minimum, maximum, resolution)
else:
model = Model._boolean('union', [get_model(child, False) for child in node._children],
Expand Down
7 changes: 4 additions & 3 deletions src/flitter/render/window/models.pxd
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@

from ...model cimport Node, Vector, Matrix44
from ...language.vm cimport Function

from libc.stdint cimport int64_t
from libc.stdint cimport int64_t, uint64_t


cdef double DefaultSnapAngle
cdef int64_t DefaultSegments


cdef class Model:
cdef readonly str name
cdef readonly uint64_t id
cdef readonly double touch_timestamp
cdef readonly double cache_timestamp
cdef readonly dict cache
Expand Down Expand Up @@ -61,7 +62,7 @@ cdef class Model:
cdef Model _vector(Vector vertices, Vector faces)

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

@staticmethod
cdef Model _mix(list models, Vector weights)
Loading

0 comments on commit 7b8045e

Please sign in to comment.