<OlivierChafik[m]>
teepee: looking at the manifold codebase, looks like they have GLTF support. I see you've looked into it in the past, wondering if it's still not a good fit https://forum.openscad.org/File-formats-td28947.html (looks like it supports animations, although we'd probably need full frame redefinitions or something)
<OlivierChafik[m]>
(I was wondering if interfacing with manifold - or others, e.g. external plugins - could be done using exchange files, and in what format for efficiency, etc)
ur5us has joined #openscad
<OlivierChafik[m]>
teepee: actually their gtlf import/export support comes from the assimp library: https://github.com/assimp/assimp
<OlivierChafik[m]>
(Which license I can't really tell if it's gpl-compatible, looks bsd-ish)
af has joined #openscad
<peepsalot>
OlivierChafik[m]: i've seen assimp also used by magnum, which is an OpenGL library I was looking into for a while, to help deal with managing shaders etc.
<OlivierChafik[m]>
it looks straightforward enough to hook in and out. Output could either be at geometry level or possibly at top-level union / lazy union style (Retaining colors in outputs)
<OlivierChafik[m]>
I'm taking a stab at streamlining the polyset <-> cgal meshes conversion story. Thinking to add Geometry::toPolySet first
qeed has quit [Quit: qeed]
qeed has joined #openscad
KimK has joined #openscad
ferdna has quit [Quit: Leaving]
LordOfBikes has quit [Ping timeout: 272 seconds]
LordOfBikes has joined #openscad
arebil has joined #openscad
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
ur5us has quit [Ping timeout: 256 seconds]
J223459 has joined #openscad
J2234 has quit [Ping timeout: 256 seconds]
arebil has joined #openscad
TheAssassin has quit [Remote host closed the connection]
TheAssassin has joined #openscad
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
arebil has joined #openscad
arebil has quit [Read error: Connection reset by peer]
arebil has joined #openscad
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
arebil has joined #openscad
aiyion has quit [Remote host closed the connection]
aiyion has joined #openscad
ur5us has joined #openscad
ur5us_ has joined #openscad
ur5us has quit [Read error: Connection reset by peer]
J223459 is now known as J22
<teepee>
I've seen assimp used a lot, my personal experience is not so great though, for some reason I always hit importers that are not really working well :/
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
af has quit [Ping timeout: 260 seconds]
aiyion has quit [Remote host closed the connection]
aiyion has joined #openscad
ur5us_ has quit [Ping timeout: 240 seconds]
af has joined #openscad
lastrodamo has joined #openscad
arebil has quit [Read error: Connection reset by peer]
arebil has joined #openscad
arebil has quit [Read error: Connection reset by peer]
J22 has quit [Quit: Client closed]
J22 has joined #openscad
J22 has quit [Quit: Client closed]
J22 has joined #openscad
af has quit [Ping timeout: 256 seconds]
arebil has joined #openscad
J22 has quit [Ping timeout: 256 seconds]
J22 has joined #openscad
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
arebil has joined #openscad
af has joined #openscad
<OlivierChafik[m]>
teepee: oh, good to know. I was thinking maybe to try and do 1) an assimp --> openscad source generator, e.g. convert a scene to an .scad file with modules that have the same name as in the original scene, transforms etc and 2) a plain import of the geometry (and maybe just 3) a raw export, maybe just skipping the top-level union and transforms + turning colors into materials, maybe using my tree transform code to ensure we have
<OlivierChafik[m]>
more of these bubbling up to the top)
<teepee>
I guess that would be a good start, if it turns out working well, I would not be opposed to adding more import/export stuff
<teepee>
but each extra library is always quite some hassle
<teepee>
looks like something is wrong with the remesh PR, it seems to be reliably stuck at one of the projection test cases
rvt has quit [Ping timeout: 256 seconds]
myosotis has joined #openscad
myosotis has quit [Remote host closed the connection]
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
myosotis has joined #openscad
arebil has joined #openscad
arebil has quit [Client Quit]
rvt has joined #openscad
linext has joined #openscad
<OlivierChafik[m]>
teepee: :'-( I'll try and repro in one of the docker images, doesn't seem to happen locally on my mac (nor in the windows image)
<teepee>
strange, the macos ci builds seems to be also affected
<teepee>
and more annoying build problems, the Snap build crashes in cgal-minkowski with OOM
<teepee>
maybe I should just try switching to clang
J2283 has joined #openscad
arebil has joined #openscad
J22 has quit [Ping timeout: 256 seconds]
arebil has quit [Quit: My keyboard has gone to sleep. ZZZzzz…]
<peepsalot>
OlivierChafik[m], teepee: I'm thinking about the problem of converting between numerous geometry types (as required per geom operation). does this sound crazy?: say we create a single concrete "SCADGeometry" class which encapsulates all other geometry types.
<peepsalot>
For every underlying geom type (Nef/Polyhedron/Surface_mesh/Polyset/etc.) SCADGeometry would hold an optional pointer to a const of that type
<peepsalot>
Any time a conversion to a new type is needed, the result gets cached in the same SCADGeometry object by setting the appropriate pointer.
<peepsalot>
All possible geometry operations would be defined on this top level SCADGeomtry type as member functions. Each operation would have a preferred underlying type, and in that call would be reponsible for retreiving the necessary type (or calling for conversion)
<peepsalot>
This would mean also unifying geometry caching to only need to hold that one type
<peepsalot>
... I'm not sure yet how it would handle various dimensions of geometry, eg if 2D polygon should be mixed alongside 3D types etc.
<peepsalot>
I'm hoping this would help simplify all the scattered utils and conversion functions, and also help ensure that no unnecessary/duplicate conversions are being done
<peepsalot>
OlivierChafik[m]: seems somewhat related to the hybrid polyhedron code you have done, so I'm curious what you think
<peepsalot>
i once tried to unify caching a few years ago, with a bit of a different approach, but got side-tracked and ultimately went nowhere with it
<peepsalot>
also, the class could cache flags for any checks that have been done like closed, manifold, etc.
<OlivierChafik[m]>
peepsalot: I've been toying with similar ideas, but I now think we need both plain old class inheritance + a toPolySet on Geometry + some pluggable engine system too (different geometries may require different orchestration, e.g. when doing parallel unions, or if doing async lazy stuff).
<OlivierChafik[m]>
peepsalot: Accumulating more different types of solids inside the same object seems like redoing virtual inheritance. I does work for the hybrid only because it has to go back and forth between nef and mesh, but even that could be done by the orchestrating CGALHybridCsgEngine instead.
<OlivierChafik[m]>
(adding more types inside just increases the complexity, have to handle all the cases in pretty much every method - really like redoing inheritance haha)
<OlivierChafik[m]>
the toPolySet(triangulate=true) change already simplifies lots of code
<OlivierChafik[m]>
peepsalot: One reason why orchestration should probably be engine-specific is some geometries / engines will support in-place updates while others don't, etc.
<OlivierChafik[m]>
Engines don't have to do all the operations by themselves and can rely on other underlying engines if needed (e.g. use a CGAL engine for the hull operation).
<OlivierChafik[m]>
Each engine's geometry class can support optimized conversions from any other geometry but is required to handle at least PolySet (will convert any geometry->toPolySet() as a fallback case), so engines can coexist at runtime.
<peepsalot>
I'm not sure inplace updates matter when we are caching geometry. nothing pulled from a cache should ever be modified
<OlivierChafik[m]>
Currently we don't cache geometrical results within applyUnion3D and its siblings (e.g. when unioning a hundred different bodies), and we do in place updates.
<OlivierChafik[m]>
we only cache the results of that huge union
<OlivierChafik[m]>
(not the intermediate results)
<peepsalot>
so, right, so apply uniom3D would take in SCADGeometries, and returm SCADGeomwetry, what it holds internally/temporarily is inconsequential
<OlivierChafik[m]>
yeah it's an implementation detail I suppose
<OlivierChafik[m]>
implementation matters when we try and avoid conversions between types in and out of those helpers (or engines if it gets pluggable)
<OlivierChafik[m]>
in the case of Hybrid I still had conversions around minkowski until recently, having a hybrid-specific minkowski code made things 2x faster
<OlivierChafik[m]>
(yet in this case it could probably be generalized to some extent)
<J2283>
OlivierChafik[m] without fast-csg-trust-corefinement it looks ok
<OlivierChafik[m]>
J2283: ah that's half a relief. Did you get any errors in the console? And could you share a minimalized error case?
<J2283>
no not any error
<J2283>
here a case (without library) https://bpa.st/EQSA - seems it has to do with laszy union
<J2283>
hmm well maybe these are two different errors Ü
<J2283>
ok seems the Airfoil thing has to do with "roof" i already have seen roof creates vertex errors on seams which are not giving a error msg but become visible in other programs .. .oO(maybe i shouldn't use too many experimental features at once)
<peepsalot>
OlivierChafik[m]: actually I don't quite understand the reasoning for hybrid geometry. it's holding a single variant, unlike my proposal of pointer for each type. so every conversion creates a new geometry?
<peepsalot>
can't you end up in situations of multiple redundant conversions then?
<peepsalot>
OlivierChafik[m]: what does it mean to have hybrid specific minkowski? doesn't it interally have to convert to Nef or whatever at a certain point?
<OlivierChafik[m]>
I wanted to avoid this with the hybrid, but also kept a way to reinstate the pre-conversion nef in case the corefinement failed on the converted mesh (then it retries on the same nef it already had before)
<OlivierChafik[m]>
in your case if supporting mutable geometry I guess you'd invalidate all the conversions if one is being mutated.
<OlivierChafik[m]>
I can't think of many other cases where having two different representations in parallel would be very useful in practice
<peepsalot>
it would only be mutable in the sense that any additional conversions are stored. there would be no modifying the underlying geometry. geometry operations would return new objects
<OlivierChafik[m]>
peepsalot: yes it does, but it's now using a nef with the same kernel as the hybrid (Epeck), and also it's trying to do less copies of things (Although I still had to copy between Polyhedron_3 and surface_mesh) https://github.com/openscad/openscad/pull/4113/files
<OlivierChafik[m]>
> geometry operations would return new objects
<OlivierChafik[m]>
This could be a bit slower, but I haven't tested it in a while in the fast-csg case.
<OlivierChafik[m]>
right now in a reduction of N unioned body it's a mutable fest, with each pair being unioned inplace. Corefinement needs that as it alters both operands, so you need a copy at some point.
<peepsalot>
i'm talking about operations at the level which correspond to a builtin module. these basically are required to create a new object always because of how we cache
<OlivierChafik[m]>
(operands are corefined in place, then I ask for the output to be the first operand)
<OlivierChafik[m]>
yes at this level copies are needed
<OlivierChafik[m]>
(or rather, the result of the applyOps is locked as a "Const" by the Geometry and cached as is, while when one wants to use it again as a union operadn they'll have to do the copy then)
<OlivierChafik[m]>
peepsalot: have you thought about multithreading? I'm thinking it could partially be handled as an implementation detail of a LazyGeometry (which wraps a future over a geometry) inside some ParallelEngine (wrapping any other thread-safe engine), but I must say I didn't look at alternatives at all (e.g. the multithreaded visitor)
<OlivierChafik[m]>
(in that naive multithreading model that LazyGeometry::toPolySet - or toAnything - would be a blocking call that's hopefully only called at the top level)
<OlivierChafik[m]>
So essentially I'm slightly inclined to rather split the current hybrid into two simple classes (a nef<epeck> and a mesh), and handle their conversions explicitly in the CGALHybridCsgEngine
<OlivierChafik[m]>
peepsalot: another source of inspiration / lead for a new kind of hybrid is ResultObject, which currently remembers whether it's been given a const or non-const object.
<OlivierChafik[m]>
Not sure but maybe it needs to be accepted / returned by the CGAL apply* functions
<OlivierChafik[m]>
(And smartCacheGet(node, preferNef) also gives a hint as to which version of the same object it prefers getting, another hybrid-like situation haha)
<peepsalot>
"smartcache" could be a lot smarter. its very engine specific as is. i'm trying to have a layer that is engine agnostic
<peepsalot>
or maybe better put that the engine differences/conversions would be handled specifically by that class (SCADGeometry or whatever name), so they are at centralized and manage-able
<peepsalot>
*at least
<myosotis>
I definitely don't know this codebase enough to give a valid opinion, but abstraction would only make sense if most engines have the same sort of cachable stuff. If they're drastically different, or some have killer features that are not generally useable, abstraction will make your life more painful, or the feature less useful
<peepsalot>
teepee, InPhase: curious what your thoughts are
<teepee>
oh, lots of discussion :)
<InPhase>
peepsalot: I endorse the principle of what you said, as a unified abstract type would prevent a lot of errors and simplify a lot of logic I think. I have a few concerns about the possibility of high cost conversions ending up being triggered repeatedly without awareness that this is happening though. I wonder what your thoughts are on how to manage that? Like say a routine sequence in a loop grabs a
<InPhase>
particular object geometry over and over again in two different methods requiring a constant converting back and forth of the underlying storage.
<InPhase>
peepsalot: Also, I think that generally there is a merit to separating 2D vs 3D types so that there is no ambiguity about how to implement 2D or 3D operations on things that do not have sensible definitions for this. But that leads me to ask if there are "in between" states that should be planned for, like when you are tesselating a mesh pieces between two layers of an extrusion... how do you store
<InPhase>
this non-manifold piece of a future 3D mesh?
<InPhase>
s/mesh pieces/mesh piece/
<teepee>
yes, we do need 2d in 3d space :)
<teepee>
there's even a PR for that already, which seems to make sense
zauberfisch has quit [Ping timeout: 240 seconds]
<InPhase>
Perhaps my conversion cost concern could be managed adequately by just putting some #ifdef guarded output notification of these conversions. I worry that by going so abstract, it will make the cause of the workload intensity invisible. So the solution might just be a mechanism for shining some sunlight once in a while.
<peeps[win]>
InPhase, the higher level SCADGeometry class would have get[GeometryType] functions for each supported type. inside each getter would 1) check if pointer exists and return or 2) call conversion function to set the pointer.
<InPhase>
Yeah. I was picturing that.
<peeps[win]>
avoiding duplicate conversions is one of the main points of the whole thing
<InPhase>
Well you can only trust the most recently accessed one to be current.
<InPhase>
Unless it was accessed as a const.
<InPhase>
Perhaps there can be a getConst[Type], where get[Type](...) const routes to that, and then read-only ops can be made explicitly efficient, and only modifying ops carry this conversion overhead risk to monitor for.
<InPhase>
Then the class is responsible for cleaning up non-current data at each mutable get.
<InPhase>
This has potential to be a net speed increase.
<peeps[win]>
InPhase, in my vision of it, any given object only stores const pointers to underlying geometries. so they are always current. operations and results require a new object
<InPhase>
Ah.
<InPhase>
Well that simplifies and takes care of that problem.
<InPhase>
Also, this sets us up better for future multithreaded operation, where sharing const's is a huge efficiency boost.
<peeps[win]>
again this is specifically at the level where basically all operations correspond to builtin module instantiations, so every result would be cached which is how its already done
<InPhase>
So then this would not cover the scope of intermediate data either as I mentioned above, but is a simpler end-piece notion.
<InPhase>
This addresses all of my concerns I raised. Seems quite reasonable.
ur5us_ has joined #openscad
<teepee>
yeah, sounds to me as this would fit the current logic quite well, maybe even simplifying the currently confusing caching
<InPhase>
It sounds like this sort of class might have helped fast-csg not eat fabric and lizards. A thing which would have prevented a class of bugs is also a good indicator it makes things better going forward.
<InPhase>
Maybe I missed exactly where that bug hit, but I vaguely remember it being at one of the conversion steps being done manually with a slight error. Centralizing thus sounds helpful.
<teepee>
right, good point, I don't know that part of the code too well, but that was a concern before already, so making it more flexible while plugging those conversion issue holes is probably a good thing
zauberfisch has joined #openscad
GNUmoon has quit [Ping timeout: 240 seconds]
<J2283>
why does the customizer json have these "d": "3.0000000000000001", values?
Joel has quit [Ping timeout: 272 seconds]
Joel has joined #openscad
Joel has quit [Max SendQ exceeded]
Joel has joined #openscad
lastrodamo has quit [Quit: Leaving]
chris22 has joined #openscad
GNUmoon has joined #openscad
myosotis has quit [Quit: myosotis]
<OlivierChafik[m]>
peeps[win]: What would the story by for the intermediate data? If we want to use the same construct down there, in the case of corefinement we'd call getMutableMesh(), then maybe getMutableNef as fallback? (Possibly the first one had to convert from Nef, so having a way to get back to that nef that may have been discarded by a mutable getter would help)
<OlivierChafik[m]>
(or maybe no mutable mode at all at that level and then we still need hybrid-style adhoc management of mutable operands in the intermediate applyOps)
chris22 has quit [Quit: Client closed]
<OlivierChafik[m]>
> where that bug hit, but I vaguely remember it being at one of the conversion steps being done manually [...]
<OlivierChafik[m]>
what's already available without incurring a conversion, etc). Not sure the complexity of dealing with these multiple cases of "do you have this? else can you convert to that" will be different from dynamic_casts of Geometry subclasses and a fallback to Geometry::toPolySet.
<OlivierChafik[m]>
Having a single class may help but if it still contains different possible kinds of geometry, some code will still have preferences towards a certain kind (currently, mostly Nef) and will ask to get that geometry. It's not always possible to create a nef out of resulting geometry, so a fallback to PolySet is also likely needed (and also conceptually it's unclear whether the export or render code wants a Nef for sure, or just wants
<OlivierChafik[m]>
(also unfortunately, the lizard is still on the loose)