Skip to content

Geometry Basics refactor #219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 126 commits into from
Oct 16, 2024
Merged

Geometry Basics refactor #219

merged 126 commits into from
Oct 16, 2024

Conversation

ffreyer
Copy link
Collaborator

@ffreyer ffreyer commented Aug 30, 2024

For a summary of changes in the 0.5 release, see #226 (comment) or the release tag


This is a continuation of #173.

I'm planning to keep the more verbose/drastic changes separate from #173 by doing them here so that we can easily do a full reset if need be. Maybe this also makes it easier to see what actually changed. For changes that essentially just fix #173 I'll try to update that pr.

Plans

(Consider the code here pseudocode)

Mesh type

My current plan for the Mesh type is roughly:

struct Mesh{D, T, Names..., ATs .<: AbstractVector}
    coordinates::AbstractArray{Point{D, T}}
    vertex_attributes::NamedTuple{Names, ATs}
    faces::Vector{FT}
    views::Vector{UnitRange}
end
  • coordinates are always included so that the Mesh has a Dimension and element type
  • vertex_attributes includes all other vertex data, e.g. normals, uvs, colors, etc. The current plan is for them to always be an AbstractVector and maybe AbstractVector{<: Union{T, StaticVector{T}} (I'll figure out the correct syntax for this later)
  • faces (or connectivity) includes a vector of faces
  • views includes UnitRanges that access sections of faces. This is for compatibility with meshes that define different sub meshes with e.g. different materials, i.e. for Add experimental support for materials in wavefront obj files JuliaIO/MeshIO.jl#95. We're also planning/thinking about adding views when merging meshes which would allow you to separate them again.

Mesh wrapper / MetaMesh

As mentioned with views not all the data that you may want to bundle with a mesh is vertex data. You may want materials that apply per view, or maybe some mesh-global data like a name or reference to a file. For this we are thinking about adding a very general, simple wrapper:

struct MetaMesh{D, T, MeshT <: AbstractMesh{D, T}} 
    mesh::MeshT
    meta::Dict{Symbol, Any}
end

GeometryBasics will probably not touch this metadata at all. It's basically just there are storage which you can use for whatever you want. For obj loading in MeshIO this would be used to store materials, texture references, etc so that Makie can extract them and apply them when plotting a mesh.

MultiFace and per-face Attributes per Attribute faces

Wavefront obj files allow for faces to carry different indices for positions, normals and texture coordinates. This is useful to avoid duplication of positions/normal/uvs e.g. for per-face normals. As such we want to allow this in GeometryBasics as well. The (second) idea here is to just allow vertex attributes to carry a face vector in the form of a FaceView:

struct FaceView{T, VT <: AbstractVector, FVT <: AbstractVector{<: AbstractFace}}
    data::VT
    faces::FVT
end

Each vertex attribute in a Mesh can either be a FaceView or an AbstractVector. In the latter case it will use faces(mesh).

MutlIFace Idea

Wavefront obj files allow for faces to carry different indices for coordinates, normals and texture coordinates. We're planning to bring this to GeometryBasics via a MultiFace type:

struct MultiFace{FaceType, Names}
    face::FaceType
    attrib_faces::NamedTuple{Names..., FaceType}
end
  • mirroring Mesh, the face would map to coordinates and always be there
  • attrib_faces would map to the other vertex_attributes in a mesh
  • We are using a NamedTuple here and in Mesh so we can verify that the faces and the vertex attributes match up.

MeshIO already has Code that essentially transforms MultiFace to normal faces (i.e. addressing each vertex attribute with the same index). We are planning to move that here and simplify MeshIO a little by doing so.

Adding MultiFace also means that we can use it for primitives which provides a solution for per-face Attributes while avoiding duplication. For example a Rect3 could define coordinates() ax 8 points, normals() as 6 vecs, and have faces defined as:

MultiFace{QuadFace}((1, 2, 3, 4), (1, 1, 1, 1)),
MultiFace{QuadFace}((1, 2, 5, 6), (2, 2, 2, 2)),
...

MeshIO's remapping code would then take care of the vertex duplication needed for rendering. This would be also be an optional conversion, i.e. a generic mesh(Rect3(...)) would keep the 8 coordinates, 6 normals and 6 MultiFace's.

This may also be helpful for dealing with per-face normal generation and per-face attributes in general. E.g. we could have decompose(FaceNormal(), mesh) and some function that merges per-face attributes with a mesh by generating MultiFace's. (I haven't thought that much about this yet.)

Using FaceViews over MultiFace has a bunch of smaller benefits:

  • it avoids the rather complex MultiFace type
  • it avoid having to differentiate classical faces which refer to vertex attributes by one index from MultiFaces which have many
  • it skips a bunch of "if MultiFace do this, else do that"
  • it removes the need for a NamedTuple for vertex attributes, simplifying the mesh type
  • It is (probably?) simpler to understand
  • it allows for more mutating functions
  • I believe it is simpler to integrate with Meshes.jl

Type Tree

I don't have strong opinions on the type tree and types (beyond Mesh), but some things I'm considering are:

  • restrict AbstractFace to Integer elements
  • change MultiType from structs to alias const MultiType = Vector{Type}
  • make Simplex a GeometryPrimitve like Rect, Sphere, etc. This would safe us reinventing the wheel with them, I think
Current Type Tree

Concrete types are bold,

  • AbstracGeometry{D, T}
    • GeometryPrimitive{D, T}
      • Rect, Sphere, etc
    • Polytope{D, T}
      • AbstractPolygon{D, T}
        • Ngon{D, T, N}
          • Line{D, T, 2}
          • Triangle{D, T, 3}
            • Triangle3d{3, T, 3}
              • GLTriangleElement{3, Float32, 3}
          • Quadrilateral{D, T, 4}
        • Polygon{D, T}
      • AbstractSimplex{D, T}
        • Simplex{D, T, N}
          • NSimplex{N}{D, T}
          • Tetrahedron{3, T, 4}
    • MultiPolygon{D, T}
    • LineString{D, T}
    • MultiLineString{D, T}
    • MultiPoint{D, T}
    • AbstractMesh{D, T}
      • Mesh{D, T, VerticesT, FacesT}
      • MetaMesh{D, T, MeshT, Names, Types}
  • StaticVector{N, T}
    • Point{N, T} @fixed_vector
      • shorthands...
    • Vec{N, T} @fixed_vector
      • shorthands...
    • AbstractFace{N, T}
      • AbstractSimplexFace{N, T}
        • SimplexFace{N, T} @fixed_vector
      • AbstractNgonFace{N, T}
        • NgonFace{N, T} @fixed_vector
          • LineFace{2, T}
          • TriangleFace{3, T}
            • GLTriangleFace{3, GLIndex}
          • QuadFace{4, T}
  • Mat{Row, Col, T, L} <: AbstractMatrix{T}

Other changes

We also plan to:

  • move Ray from Makie
  • move Plane from Makie
  • consistently define coordinates or 2D primitives in counter-clockwise order for Polygon construction (TODO: how should this work with Tesselation?)
  • make sure simplexes and other things for FEM exist and work correctly (probably not adding anything new here though, we can do that later)

(incomplete) TODO

Prototyping;

  • Refactor Mesh type
  • Refactor MetaMesh type
  • Add MultiFace
  • Add vertex index merging from MeshIO
  • update mesh building functions
  • update Rect3 for testing

General:

  • remove add_meta, pop_meta
  • remove old deprecation warning about Tesselation
  • update merge(mesh) to include views
  • replace MultiPoints with Vector{Point} etc
  • update un-tesselated 2D primitives to generate coordinates in counter-clockwise order
  • improve type tree to avoid explicit checks around MultiFace types
  • try simplifying merges(meshes)
  • simplify facetype and add other introspection functions (e.g. hasnormals())
  • update mesh.views when switching to a different (vertex) face type
  • try to allow NormalUVFace{SomeFaceType} instead of NormalUVFace{N, T, SomeFaceType}
  • allow decompose(MultiFace, multi_faces) (incomplete type)
  • add decompose(FT <: AbstractVertexFace, multi_faces) :: Vector{MultiFace{..., FT, ...}}
  • rename "normals" -> "normal" for consistentcy (soft deprecation via constructor/property)
  • replace generators with Arrays
  • drop view output from decompose(facetype, mesh) -> faces, views and add a new function for that (kept version that takes and produces views)
  • add decompose(LineFace, multi_faces)
  • cleanup file structure (add file for face types and core functionality, file for mesh types and core functionality)

@ffreyer ffreyer force-pushed the ff/refactor branch 2 times, most recently from 4199cd5 to af55972 Compare August 31, 2024 21:11
@ffreyer ffreyer marked this pull request as ready for review September 4, 2024 15:00
@ffreyer ffreyer marked this pull request as draft September 4, 2024 15:02
@ffreyer ffreyer merged commit d485293 into sd/simple-mesh Oct 16, 2024
8 checks passed
@ffreyer ffreyer deleted the ff/refactor branch October 16, 2024 15:34
SimonDanisch added a commit that referenced this pull request Oct 17, 2024
* get rid of StaticArrays

* alias must be fully typed

* more fixes

* fix order

* more fixes

* simplify fixed array

* remove meta types

* try to get mesh working

* remove all the things!!

* more tests

* remove 1.3

* drop 1.3

* add imports and get overload

* add getindex for faces for vec too

* fixes

* bring back connect

* add / for e.g. mean(points)

* small improvements

* introduce TriangleMesh

* fix constructor and print Mesh more nicely

* add zero for value

* fix tests

* polys

* fix some compile errors

* fix Simplex <: AbstractSimplex <: Polytope

* fix decompose test

* fix Rect2 Tesselation

* fix ngeom for LineString

* fix compat bounds

* change getindex index to Integer

* remove triangle_mesh Tesselation deprecation warning

* fix Base.intersect extension

* update union docs and comment out broken diff or rects

* add decompose_x methdos with types

* disable diff test

* fix MatN constructors

* fix type ambiguity

* fix vcat of StaticVector, Mat convert

* add mat[VecOrInt, VecOrInt] and Vec(mat)

* match isapprox implementation with docstring

* add isapprox to Mat

* fix indexing instead of implementing isapprox

* rework broadcasting & add more tests

* fix nested broadcast

* fix Mat getindex, Boundschecks and add tests

* fix broadcast size missmatch

* handle map like StaticArrays

* add isapprox and converts from Matrix for Mat3f-like types

* avoid creating Base arrays on copy

* Geometry Basics refactor (#219)

* update MetaMesh

* add MultiFace type

* update Mesh & MultiFace types

* update Mesh & MetaMesh utils

* add MultiFace remapping code

* prototype MultiFace Rect -> Mesh pipeline

* generalize MultiFace getindex to Integer

* remove add_meta, pop_meta

* update merge for MultiFace and views

* add AbstractVertexFace and AbstractMultiFace

* split up  mesh() for better usability

* minor fixes

* add views to Mesh constructors

* add `mesh()` method for converting facetype of mesh

* switch back to "normals"

* fix missing normals rename

* add back point/normal/uv-type kwargs

* consider face views in face decompose

* add mesh(mesh; attribs...) & improve dispatch safety

* fix normals(), cleanup tests

* add mesh constructor tests + fixes

* deprecate normals for normal as vertex attribute name

* make NormalFace and NormalUVFace types again

* cleanup tests & normals vs normal

* let ci run

* remove views aware face decomposition

* fix rect index order

* fix MultiFace remapping with OffsetIntegers

* add moreMultiFace utils

* restore decompose(FaceType, faces, views)

* allow MultiFace -> LineFace conversion

* define Rect3 faces counterclockwise

* add more convenience types

* filter nothing attributes

* drop Base.Pairs for 1.6 compat

* Add depwarn in hasproperty too

* improve MultiFace show

* update Pyramid

* update Cylinder

* add MultiFace decompose

* fix Cylinder tests

* make OffsetInteger printing copyable

* update tests for Rect3 and normal gen

* fix remaining tests

* fix incorrect vertex index counter

* simplify merge of mixed Face types

* test merge(meshes)

* prototype swapping from MultiFace to FaceViews

* treat views in vertex index remapping + some fixes

* fix face type change

* clean up AbstractVertexFace

* extend FaceView interface

* update Cylinder, Pyramids

* declutter NgonFace prints

* update tests

* cleanup some test_broken

* switch to Dict

* fix tests

* remove shorthands

* export vertex_attributes and FaceView

* add center point to Circle to avoid shallow triangles

* make untesselated rect vertices counter-clockwise

* fix tests

* fix Cylinder face windig direction

* add `face_normals()` helepr function

* cleanup face_normals and normals a bit more

* update tests for Cylinder

* rename connectivity -> faces

* update docs (meshes, primitives, decompose, Point, Vec, Mat)

* add/update docstrings

* add quick test for face_normals()

* fix TetrahedronFace conversions

* restore volume functions

* fix tests

* add some Polygon tests

* test Pyramids

* test TetrahedronFace decomposition

* test and improve Mesh validation

* test Mesh inteface functions

* test decompose with views

* test and fix matrix det, inv, transpose, mat*vec

* fix tests

* cleanup normal gen and export face_normals

* add util for splitting meshes by views

* fix missing dot in range .+ idx

* improve performance of merge

* fix tests

* improve GeoInterface conversion performance

* switch back to NamedTuple for performance

* cleanup merge(meshes)

* test clear_faceviews with mesh.views

* fix missing import in docs examples

* add convert for arrays of meshes

* add function for removing duplicate faces

* update normal gen tests + fixes

- fix normal gen for varying face types
- fix normalization of face_normals

* remove time piracy

* bring back shorthand types

* restrict type in meshes to error earlier

* update precompiles

* autoconvert point dim in merge(meshes) instead of restricitng type

* add compat entry

* ignore unused PrecompileTools in 1.6, 1.7

* bring back old precompiles

* add convert target to orthogonal_vector

* revert triangulation changes of Circle

* revert to using StaticArrays

* avoid some invalidations (and fix get)

* fix stale instances due to AbstractVector

Apparently T[] is an AbstractVector here?

* use string interpolation in error to avoid invalidation from string *

* fix test

* export clear_faceviews & update FaceView docstring

* update type docstring

* add notes about views

* update Mesh docs

* add FaceView ref to Mesh docstring

* add brief section about extending decompose

* derive Point eltype when dimension is given

* reuse docstring

* fix docs?

* fix docs??

* add GLMakie to docs

* fix pkg command

* rename clear_faceviews & update

* fix pkg

* fix another clear_faceviews

* fix docs

* use action cache

* fix typo

---------

Co-authored-by: ffreyer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants