1
1

Compare commits

...

858 Commits

Author SHA1 Message Date
c8004ff653 Just what version of C++ does the linux buildbot use, anyway. 2021-09-21 00:44:36 -07:00
fdffbf87ac Fix last commit 2021-09-21 00:13:43 -07:00
bee00909bc forgot a line 2021-09-21 00:04:10 -07:00
562723b080 More linux fixes 2021-09-21 00:03:32 -07:00
2195a5eb2c Try to fix another linux compile error 2021-09-20 23:28:03 -07:00
4307c0eb68 try to fix weird gcc compile error 2021-09-20 22:56:02 -07:00
2d473ff4a8 Sculpt: more brush stuff 2021-09-20 22:52:17 -07:00
2b2b569229 Disable a static assert on gcc. 2021-09-20 20:26:53 -07:00
015dae3dc5 add missing files 2021-09-20 19:42:31 -07:00
3fc687ad75 Sculpt: Finish color support for brush channels
* BRUSH_CHANNEL_VEC3/4 are now implemented
* New flag BRUSH_CHANNEL_COLOR
* Also tried to sculpt's usage of wm.radial_control in keymaps
2021-09-20 19:41:00 -07:00
76beed9068 Sculpt: More brush engine stuff, got automasking to work with it
* Sculpt now has an API to get brush channel settings.
  If a sculpt cache exists it will use the channels there
  (ss->cache->channels_final), otherwise it pulls them
  from a brush and Sculpt toolsettings. Exampes:

  float f = SCULPT_get_float(ss, "setting", sd, brush);
  itn i = SCULPT_get_int(ss, "setting", sd, brush);

* Improved the UI a bit
2021-09-20 14:10:35 -07:00
645aee0835 Fix small crash in last commit and a few typos 2021-09-20 03:34:13 -07:00
83bfa950b1 Sculpt: add missing files 2021-09-20 03:14:39 -07:00
898625547f Fix problem in last commit 2021-09-20 03:14:14 -07:00
73150981c8 Sculpt: More brush channel stuff
* The input device curves for brush channels
  now use a copy on write mechanism.
  + It's based on a global cache of curves.
    The alternative is to reference count
    BrushChannels, which I also implemented
    then abandoned.
  + Profiling showed that copying CurveMapping
    instances was actually a problem.

* Lots of small fixes to the old<-> new brush setting
  conversion code;

* Brush commands can now, sortof, have individual
  spacing.  The default brush spacing still acts
  as a minimum though.

* Added a BLI_ghash_lookup_p_ex method that
  returns the key ptr inside the ghash (it
  returns the actual key, not a pointer to
  Entry.key).
* Added a general 1d CurveMapping preset operator
  that uses an RNA path to get the curve.
2021-09-20 03:01:30 -07:00
c9f1e104da Sculpt: Brush channels names are now lower-case instead
of upper case.
2021-09-19 16:17:01 -07:00
336b263b56 Sculpt: brush engine stuff
BrushChannels are now stored in linked lists
instead of simple arrays.  This helps to
avoid memory corruption.

I had originally wanted to be able to pass
BrushChannels by value, but that doesn't really
work since they heap allocd data (the input
mapping curves).
2021-09-19 15:35:10 -07:00
b3ed969b86 commit prior to small refactor 2021-09-19 13:30:43 -07:00
87feba04dd Sculpt: more brush engine stuff; do not test.
Pushing this commit early due to computer
weirdness
2021-09-19 01:11:35 -07:00
1ca57bc5f4 Sculpt: flushed out brush channel RNA and made basic UI 2021-09-18 12:10:14 -07:00
7749b89d74 Sculpt: Added some icons and commit icon_geom.blend into the branch
Help with icons would be appreciated.  The
scene project icon kind of came out looking
like a band-aid.
2021-09-18 02:43:03 -07:00
bae92a0ce5 Disable threading for sculpt project brush 2021-09-18 01:39:40 -07:00
5223f73a1d Fix compile error 2021-09-18 01:26:12 -07:00
fe47584316 Sculpt: Flesh out RNA wrapping of BrushChannels 2021-09-18 00:35:56 -07:00
2d3d6eb7b2 Merge remote-tracking branch 'origin/temp_bmesh_multires' into sculpt-dev 2021-09-17 23:32:08 -07:00
f0c35d16f3 Merge branch 'master' into temp_bmesh_multires 2021-09-17 20:13:39 -07:00
85d274a60c Merge branch 'master' into sculpt-dev 2021-09-17 16:22:10 -07:00
d3bba94bf2 Commit current working copy; having
weird file system issues
2021-09-17 14:43:00 -07:00
04c3690299 Sculpt dyntopo: Roughed out skeleton of new brush engine API
Command Lists

* The new system will be based on command lists
  generated by (eventually) a node editor.
* For now, the lists will be hardcoded.
* Idea is to make a minimal viable
  brush engine that won't cause file breakage
  when the upgrade to node-based brushes happen.

Brush Channels

* Wrote new structures and API to wrange
  brush parameters: BrushChannel.
* Supports, floats, ints, enums, bitmasks,
  with plans for vec3 and vec4.
* This will replace UnifiedPaintStruct,
  most of the members of Brush and the
  DynTopoSettings struct.
* Brush channels can
  be mapped to various input device
  channels (e.g. pen pressure); each
  mapping has its own associated curve
  (CurveMapping instance) and bounds.

Brush channel inheritence chaining

* Brush channels can form inheritence chains
* Channel sets are stored in three places:
  in the scene toolsettings, in Brush, and in
  individual brush commands.
* Node groups will also have a channel set.
* Channels in each set can be flagged to
  inherit from the parent set.
* Inheritence happens in seperate merged
  channel sets at runtime.  The final
  Brush channels live in Brush->channels_final,
  while the final command channels live in
  BrushCommand->params_final.
2021-09-16 20:29:33 -07:00
627edd1efa Merge branch 'master' into temp_bmesh_multires 2021-09-16 13:44:21 -07:00
445889676b commit prior to merge 2021-09-16 10:42:30 -07:00
350e783668 Add skeletal beginnings of C++ sculpt refactor
design study (note that it's #ifdef'd out).

Basic idea is to put all the sculpt brush code
in a single large template.  This template
takes a PBVH adaptor class (of which there
would be three, one per PBVH_XXX type)
as a template argument.

Basically we're using the compiler to generate
three complete copies of every brush implementation.
C++20 concepts are used to validate the pbvh classes.

An example brush implementation:

    pbvh->forVertsInRange(
        {
          .brush = ss->cache->brush,
          .radius = radius,
          .use_threads = true,
          .use_original = false
        },

        [&offset](auto viter, int node_i, void *userdata) {
          //add offset to vertex coordinates

          madd_v3_v3fl(viter.co, offset, viter.fade);
        },

        [](PBVHNode *node, int node_i, void *userdata) {
          BKE_pbvh_node_mark_update(node);
        });
2021-09-15 14:56:19 -07:00
0b2aee5841 Sculpt dyntopo: Fix a few issues from last commit
* Fixed crashing on entering sculpt mode
* Fixed transitioning between sculpt and
  another undo system type sometimes
  corrupting stack.
2021-09-15 02:50:32 -07:00
ecdd6a302e Sculpt dyntopo: fix missing bit from last commit
* BM_mesh_bm_to_me now saves id layers by default.
2021-09-15 02:16:03 -07:00
173f5f94ff Sculpt dyntopo:
Seperate enabling PBVH_BMESH from enabling DynTopo:

* Created a new option to globally disabled
  DynTopo.
* The DynTopo panel header now reads "Dynamic Mode",
  to hopefully signal that turning on PBVH_BMESH is
  a seperate step from enabling or disabling DynTopo
  itself.
* The first checkbox in the panel is "DynTopo" so it
  should be clear enough (it's on by default, with multiple
  layers of file versioning checks).

PBVH_BMesh's undo system:

* CD_MESH_ID layers are now permanently saved once
  they are created (by default they are not).  This
  fixed a *lot* of bugs:

  Before this the undo system had to save maps between
  mesh indices and mesh IDs on transitioning
  between sculpt and global undo steps.  This was
  extremely error prone, and it simply wasn't possible
  to cover all of the corner cases

* Note that there is still an odd bug where the first
  global undo push after a sculpt step gets ignored,
  I dunno what's up with this.

* Dyntopo undo should be nearly (hopefully completely)
  bug-free after this commit.

C++20

* Made a few small changes to get blender to compile
  with c++20.  std::result_of was removed, had to
  replace a couple of usages of it with std::invoke_result.

* I'm planning to do some design studies on rewriting
  sculpt into C++.

* I strongly suspect we are going to need C++20'a new
  concepts feature if we move sculpt into C++.
  I'm planning to do some design studies on how
  that might work.
2021-09-15 01:41:03 -07:00
0eeaeb3fc2 Sculpt dyntopo: fix nasty node splitting bug 2021-09-13 20:14:46 -07:00
3df335d330 Sculpt dyntopo:
* Fixed noise on using autosmooth with tools that use original
  coorinates.  While this was most prominent with DynTopo,
  it did happen with other tools.
* The solution is to smooth the original coordinates as well
  as the explicit coordinates if the active tool requires
  original data.

* I decided to replace the original coordinates system for
  PBVH_FACES and PBVH_GRIDS with the same MDynTopoVert structure
  DynTopo uses.  The alternative would have been extremely messy
  code.

* Todo: Rename MDynTopoVert to. . .SculptInfoVert?
* Todo: Cache boundary flag and corner info in MDynTopoVert->flag
        for PBVH_FACES/GRIDS similar to PBVH_BMESH.
2021-09-13 19:24:21 -07:00
0676928408 Sculpt dyntopo: more collapse fixes
The edge cases just never end.
2021-09-13 02:31:33 -07:00
e68667a835 Sculpt dyntopo:
* A few more collapse fixes
* Fixed boudary handling in surface_smooth_v_safe
2021-09-12 23:39:49 -07:00
86972d294f Dyntopo sculpt: fix bug with boundary flags 2021-09-11 13:38:42 -07:00
f52a03dd71 Sculpt dyntopo: Added a 'hard edge mode' option
to forcibly set autosmooth_fset_slide to zero
(i.e. treat face set boundaries as hard edges
and not project them on the surface).
2021-09-09 10:06:24 -08:00
a52f89a446 Add more int casts for linux 2021-09-08 23:21:57 -08:00
9f3bafc4ab Sculpt dyntopo
* Non-manifold "fins" are now detected and automatically
  deleted.
* Fixed compile error on linux.
2021-09-08 23:18:07 -08:00
bb1096f475 Sculpt dyntopo:
* Collapse now uses code from decimate to detect
  degenerate cases.
* Remaining, unknown (and rare) degenerate cases
  are now detected (via presence of duplicate verts
  in faces) and fixed.
* DynTopo fills in undo size properly now,
  so undo memory limiting works.
2021-09-08 15:51:56 -08:00
3e6edf5278 Sculpt dyntopo:
* BLI_table_gset now internally uses a SmallHash instead of
  a GHash.  Profiling revealed this to be quite a bit
  faster.
* This is something of a stopgap until C++-afication of
  pbvh, when we'll have our pick of a bunch of
  really nice C++ hashmap libs.
* pbvh_collapse_edge bites the dust; dyntopo now uses
  BM_collapse_edge.  Of the three topology operations
  (subdivide edge, collapse edge, dissolve 3/4 valence
  vertex) only dissolve still has a dyntopo-specific
  implementation.
* Fixed a bunch of annoying memory corruption bugs.
* Non-manifold triangles are now detected in more
  places.

SmallHash changes:

* Enabled removal
* Fixed infinite loop bug caused by
  improperly counting free*d* cells
  versus free cells.
* Added a BLI_smallhash_ensure_p method
  that works just like the GHash version.

Sculpt replay system

* Roughed out a simple system to record and
  play back sculpt strokes using a simple
  text format.
* This is exclusively for
  performance profiling and unit tests.
* For each brush stroke the system saves a copy
  of the active StrokeCache and PaintStroke
  and parts of Sculpt.

This should make profiling DRAM thrashing a lot
easier.
2021-09-07 23:49:54 -08:00
37bce7b701 commit working code 2021-09-02 23:19:11 -07:00
6febbd7a55 Linux's gcc's flags are evil 2021-09-02 11:42:06 -07:00
416c7a32d8 Fix warnings 2021-09-02 11:32:46 -07:00
d4badd4b22 Fix compile error 2021-09-02 11:26:28 -07:00
4e43e09cca Sculpt dyntopo: increment subversion. 2021-09-02 11:08:28 -07:00
21b6d78cd2 Sculpt dyntopo: change brush defaults and fix bug
* Changed brush defaults a bit.  New defaults
  are for organic modeling.
* autosmooth_fset_slide now defaults to 1, so
  face set boundaries are smoothed but stick to mesh
  surface (if 0 they would function as hard edges).
* Weight by area smooth mode is on by default for all
  brushes.
* Cleaned up versioning code and made it
  kick in at 3.00:21, with some simple checks to
  try and detect existing data from beta testers.

* Also fixed a small crash bug.
2021-09-02 11:02:44 -07:00
2b20931707 Merge branch 'master' into temp_bmesh_multires 2021-09-02 00:02:20 -07:00
416686707f commit before merge 2021-09-01 21:32:43 -07:00
8bfbbc467a Sculpt dyntopo
* Wrote a simple fix for drawing face sets
  in inverse (ctrl) mode with face set automasking
  on.

* Various fixes related to hard edges and smoothing.

* Started writing some code to defragment bmesh mempools.
  Need to figure out how to avoid triggering excessive
  PBVH node rebuilds.
2021-09-01 11:47:03 -07:00
baa24243a5 Sculpt dyntopo: Dynamic field-propegated topology rake
I might write a paper on this.  Topology rake now locally
updates a vector field, which it uses to smooth the input
and constrain to mesh (including face set) boundaries.
This can make an enormous difference for things like
smoothing.

Note that this is different from the existing 'curvature rake'
mode, which also builds a field and which is fed into the input
of this new one.

The only oddity is that the field is stored in a CD_PROP_COLOR
since we don't have a CD_PROP_FLOAT4, and this shows up in the UI
(not sure if I'm messing up the CD_TEMPORARY flags or if the UI
doesn't check for them).
2021-08-30 15:04:43 -07:00
73529fb1bb Sculpy dyntopo: fixed various topology bugs
* Fixed crash in dyntopo collapse.  The
  loops around vertex iterator dyntopo uses
  doesn't actually work on non-manifold meshes,
  or meshes with invalid normals, this was not
  being checked in pbvh_bmesh_collapse_edge.
* Rotate tool now works with dyntopo.
2021-08-29 16:05:26 -07:00
381ef09073 Sculpt dyntopo: another bugfix from today's earlier commits 2021-08-28 15:33:41 -07:00
56ba339cd8 Fix a few bugs in lat commit 2021-08-28 14:59:54 -07:00
055fa3fa5e fix missing curly braces 2021-08-28 13:59:00 -07:00
7d5c3beb06 Sculpt dyntopo: Fix bug with edge collapse 2021-08-28 13:30:46 -07:00
39b0e9df81 Sculpt dyntopo: Add edge API
* Added a minimal edge API to query edge
  boundary states.
* This is necassary because the previous approximation,
  testing if two adjacent verts are boundaries, breaks
  for triangles.
2021-08-28 12:14:59 -07:00
6648f82ef7 Merge branch 'master' into sculpt-dev 2021-08-28 19:58:13 +02:00
320ff87948 Sculpt: Quantize mask filter 2021-08-28 19:57:32 +02:00
b21595cdf9 Tweak last commit to not affect base face set. 2021-08-27 21:54:15 -07:00
e4b36fb6bc Sculpt dyntopo: split face set boundaries on mirror boundary
Added an option to split face set boundaries on mirror
boundaries; currently only DynTopo supports this.

Very useful for making hard edges along mirror lines.
2021-08-27 20:02:20 -07:00
966e4ba9ae Sculpt dyntopo: improved boundary smoothing
It's kind of hackish mathematically.
2021-08-27 18:13:18 -07:00
268682527f Sculpt dyntopo: added a smoothing factor for sharp boundaries
Works by projecting non-boundary verts onto boundary vert
normals and weighting by boundary_smooth_Factor.
2021-08-27 14:18:50 -07:00
cdb52aee9f Missed an ATTR_NONNULL fix 2021-08-27 01:59:34 -07:00
8b02ab86f1 change 'error' to 'warning' in a printf 2021-08-27 01:57:13 -07:00
019700583b Sculpt dyntopo: undo bugfixes
* Fixed nasty undo bug related
  to now rewinding BMLogEntry subchains properly.
* Fixed bug in dyntopo collapse
2021-08-27 01:51:56 -07:00
31d2b04411 Sculpt dyntopo: Who knew gcc's nonnull attribute is 1-based 2021-08-26 20:23:17 -07:00
3508c699fb Sculpt dyntopo: Cleanup past few commits
* Removed some ATTR_NO_OPTs
* Made pbvh_split_edges disallowed
  4-valence splits if cleanup topology
  mode is on
2021-08-26 20:10:54 -07:00
8ea7c93a37 Sculpt dyntopo: support sharp edge flags
* Sharp edge flags are now supported and are
  treated much the same as face set boundaries:
 + Dyntopo preserves them
 + Interior smoothing treats them as boundaries
 + Corners are detected and pinned in smoothing
 + TODO: add a brush flag to ignore sharp boundaries
   for smoothing.
* Seams are also preserved, but don't affect smoothing.
* BMLog now saves edges.
* The new edge split function is enabled.
* Dyntopo now pushes new combined BMLog entries in
  its top-level function, to avoid scary id reuse
  edge cases.
* SCULPT_vertex_is_boundary/corner now take a bitmask
  of which types of boundaries you wish to query instead
  of check_face_sets.
2021-08-26 18:00:29 -07:00
8b8733e76c Sculpt Vertex Colors: New sample color operator 2021-08-27 01:07:07 +02:00
4dda04eaa9 Merge branch 'master' into sculpt-dev 2021-08-26 23:19:21 +02:00
30691560fa Fix C++20 designated initializer build issue. 2021-08-26 20:56:13 +05:30
12f87d02c6 commit prior to small cleanup 2021-08-25 03:01:56 -07:00
9680edf77c * Implemented bounday/face set corner handling.
* New function SCULPT_vertex_is_corner, similar to
  SCULPT_vertex_is_boundary it takes argument to
  check face sets.  PBVH_FACES/GRIDS version is
  incomplete.  It returns a bitmask of whether
  the vert is a boundary corner and/or a face
  set one.
* PBVH_BMESH uses a somewhat more expensive
  calculation to detect corners of face set islands by
  edge angle. This is currently not done for boundary
  corners.

Corner pinning now happens in:

* The internal smoother dyntopo uses for stability reasons.
* SCULPT_vertex_neighbor_average_interior.
* Topology rake.
* Dyntopo collapse.

Note that DynTopo always pins face set corners
but everything else only does so if preserve face
sets is on.
2021-08-24 13:18:36 -07:00
a00bfa8976 Sculpt dyntopo: more smooth stuff
* All of the smooth brushes now use the SculptCustomLayer
  system for temporary data, so all work with dyntopo now.
* You can now use a flat array in SculptCustomLayer with
  PBVH_BMESH (though you have to build the structure manually).
  The mesh filter code uses this.
* Smooth (and autosmooth) now have an option to preserve face
  set boundaries.  Corners are currently not handled.
* Simplify brush has preserve face set boundaries autosmooth
  flag set by default.
* SCULPT_vertex_is_boundary now takes an addition argument
  for whether to check for face set boundaries.
2021-08-23 22:55:17 -07:00
bde54e127e Sculpt dyntopo: Smooth improvements and bug fixes
* Added an option to weight smooth by face areas
* Dyntopo now caches face areas in a CD_PROP_FLOAT layer
* Dyntopo also caches number of edges around verts inside of
  MDynTopoVert.  To avoid increasing the struct size flag was
  made a short.
* Cleanup mode (dissolves 3/4-valence verts) now piggybacks on
  subdivide code to build list of verts; this is much faster.
2021-08-23 21:06:10 -07:00
9b8c82e2ed Sculpt dyntopo: fix mem cache test function, how did this
ever work
2021-08-23 02:28:19 -07:00
5866a4680d Dyntopo Sculpt: Wrote new edge split code, currently disabled 2021-08-23 01:19:55 -07:00
d795144f54 I hate default int 2021-08-22 13:31:05 -07:00
de6258c618 Silly me, don't use alloca in this situation 2021-08-22 13:16:10 -07:00
d912ceeb40 Fix compile error on linux 2021-08-22 13:15:08 -07:00
9a197a1185 Sculpt dyntopo: Temp fix for nasty GCC compiler bug on linux.
I'll file a bug report with GCC tomorrow.
2021-08-22 12:51:53 -07:00
36785c83f0 Sculpt dyntopo: Fix a dumb mistake I made in space_toolsystem_toolbar.py 2021-08-22 10:29:36 -07:00
8eb7a04150 fix signed/unsigned warning 2021-08-21 20:46:08 -07:00
97c3e5944c Sculpt dyntopo: Finished bmesh cache coherency tester
To run, in the python console enter:

bpy.msgbus.pbvh_bmesh_do_cache_test()

The output will be in the regular console.  The test
build a half-million vert cube and smooths it. It runs
several passes (all of which perform the same smoothing
operation):

1; Randomized order pass
2. Ordered pass (by vertex clustering)
3. Same as 2 but with a purely data-oriented version
   of the bmesh structs.
4. Same as 2, but using a version of the bmesh structs
   with all pointers replaced by integer indices.

At least on my laptop #3 and #2 are about a third faster
then #1, and #2 tends to be around 15%.
2021-08-21 20:40:22 -07:00
6f523ffacb Sculpt dyntopo: Don't allow dyntopo when multires modfier exists
Note that thoeretically we could support multires in dyntopo,
but numerical instability would probably make the grid data
explode.
2021-08-21 15:19:15 -07:00
04562794df Sculpt dyntopo: disable mem cache test executable
from compiling altogether
2021-08-20 20:52:22 -07:00
93004c7b19 Dyntopo: Disable mem cache test executable for now as it
doens't link on mac
2021-08-20 20:49:29 -07:00
0d542db1e1 Sculpt dyntopo:
* Fixed multires apply base feeding bad original coordinates to
  deform modifiers.
* Roughed out some code for cache performance testing.
* Wrote skeleton code for a PBVH texel API; hasn't been tested
  yet and may be removed.
2021-08-20 20:36:04 -07:00
de1f2c41fa * BM_mesh_remap can now reorder loops
* Wrote yet another BKE_pbvh_reorder_bmesh function
2021-08-18 21:43:59 -07:00
106f542ac4 Sculpt dyntopo: yet another undo bug
BKE_pbvh_bmesh_add_face had a branch where it ignored
the log_face argument, leading to corruption in
BMLog.
2021-08-17 14:58:37 -07:00
83f94ebb6f Sculpt dyntopo: remove debug ATTR_NO_OPT's 2021-08-17 00:31:04 -07:00
954aa88ba4 Sculpt dyntopo: more undo fixes
Yay for massively overdetermined bugs.
2021-08-17 00:09:43 -07:00
9503751c83 Sculpt dyntopo
* Added a limited "fast draw" mode to pbvh drawing
  that tries to limit data sent to the GPU.
 - Facesets and mask data are disabled.
 - Indexed mode is forced.
 - Does not work (at all) for multires.

* Finally fixed some outstanding bmesh sculpt undo bugs:
 - Forgot to mark pbvh nodes to update their bounds, which
   produced a bug I had thought was caused by something else.
 - Hopefully fixed a long-standing occasional memory corruption
   bug.
2021-08-16 20:50:02 -07:00
dcaba4c5e3 Sculpt dyntopo: fix various faceset init operator bugs
that crept in.
2021-08-16 16:34:35 -07:00
fb463a13cd Sculpt dyntopo: Fix memory corruption caused by improperly disabled
code.
2021-08-16 02:12:30 -07:00
b5100e73c8 Sculpt dyntopo: Fix boundary brush for multires
This commit fixes boundary brush for multires which
broke two commits ago.

This required implementing the geodesic api for PBVH_GRIDS,
which I did by building topology maps in a rather. . .
haphazard fashion.

Basically I built a vert->edge map and then used it to
derive a pseudo edge to quads mapping (it maps edges
to all the verts in the two surrounding quads except
the edge's own verts).

Just for fun I enabled geodesic mode in mask expand;
it seems to work.
2021-08-16 01:44:31 -07:00
ab632243e6 Merge branch 'master' into temp_bmesh_multires 2021-08-15 18:14:41 -07:00
8510c77b9c Sculpt dyntopo: improve boundary brush for irregular topology
(still a wip)

The boundary brush now builds a geodesic distance
  field (from the boundary) from which it derives a tangent
  field:

* These now define the rotation plane for bend mode.
* Rotation origins snap to these planes.

There is also typedef'd code for visualization tangents
in a temporary object (note the sculpt object), to enable
define VISBM in sculpt_boundary.c.  This will be removed
lated.

Additional changes:

* Added a function to get the number of edges around verts,
  SCULPT_vertex_valence_get.
* Added an API to calculate cotangent weights for vert fans,
  SCULPT_cotangents_begin (call in main thread first) and
  SCULPT_get_cotangents.
* Sculpt neighbors for PBVH_FACES now uses ss->vemap if it exists.
* The Mesh topology mapping code now takes extra parameters for
  sorting vert/edge cycles geometrically.
* Similarly, there is now a function to sort BMesh edge cycles,
  BM_sort_disk_cycle.
* MDynTopoVert->flag now has a bitflag for when the disk cycle
  sorting needs to be redone, DYNVERT_NEED_DISK_SORT.
* The sculpt geodesic code now supports passing in custom vertex
  coordinates.
* The geodesic API can also build an optional map of which vertex
  in the initial vertex list is closest to any other vertex.
2021-08-15 18:02:16 -07:00
40aa321dc7 Sculpt dyntopo: fix bug with dyntopo geometry undo push 2021-08-11 22:51:09 -07:00
a80c381ec5 Sculpt Dyntopo: PBVH draw fixes
* The PBVH draw subsystem is now told whether any viewports
  have drawtype >= OB_MATERIAL before anything in any windows
  are drawn.  There are no alternatives given the design
  constraints of sculpting, where simply uploading data to the GPU
  quickly becomes a bottleneck.

* Fixed flat vcol shading mode.
2021-08-07 22:28:00 -07:00
1e9a7383ef * Don't rely on BMLog's stored normals, instead flag pbvh nodes to
update normals on undo/redo.
2021-08-07 19:25:36 -07:00
dc738de90c Sculpt dyntopo: Fix bug in cleanup_valence_3_4 2021-08-06 18:39:54 -07:00
8ed4c5fc61 Merge branch 'master' into temp_bmesh_multires
Also fixed a pbvh corruption bug
2021-08-06 12:51:18 -07:00
76bd253be7 Dyntopo sculpt: add dev operator to debug memory cache coherency 2021-08-06 09:58:46 -07:00
c78b0874ad Asset Browser: Support dropping materials into Face Sets 2021-08-06 17:33:18 +02:00
b991a92aab Merge branch 'master' into sculpt-dev 2021-08-05 20:10:57 +02:00
01965a275c Cursor: Change face set color and wireframe preview 2021-08-04 22:17:48 +02:00
b2dc8bd92e Merge branch 'master' into sculpt-dev 2021-08-02 21:35:31 +02:00
d3faf09082 Merge branch 'master' into sculpt-dev 2021-07-31 17:16:02 +02:00
b243eb2646 Merge branch 'master' into temp_bmesh_multires
Also:

* added BMLog function to save mesh IDs.
  - Used by SCULPT_UNDO_DYNTOPO_BEGIN/END instead of
    saving the whole mesh, which was the previous behavior.
* SCULPT_UNDO_DYNTOPO_BEGIN no longer pushes a non-dyntopo
  geomtry undo node, as this is no longer necassary.

This greatly speeds up going into/out of sculpt mode
with dyntopo enabled, as before it was copying
the mesh twice.
2021-07-29 16:08:14 -07:00
fcfb47b983 Merge branch 'master' into sculpt-dev 2021-07-27 22:00:24 +02:00
c1f5ac7cfe Array Brush: Support array editing with the voxel remesher 2021-07-25 20:36:56 +02:00
89897140cf Merge branch 'master' into sculpt-dev 2021-07-25 18:20:27 +02:00
af71984942 sculpt dyntopo: fix memory corruption and associated memory leak 2021-07-25 05:28:54 -07:00
ec4b9dff19 Add 'projection' option for volume-preserving smoothing to
smooth corrective modifier
2021-07-23 15:46:01 -07:00
d71b6d37fe Array Brush: Initial radial and linear array editing 2021-07-23 21:29:07 +02:00
2689124320 Array Brush: Path edit mode working 2021-07-21 23:27:46 +02:00
70a4956020 Sculpt dyntopo: Removed triangle limit for PBVH_BMESH
* PBVH_BMESH now supports faces other then triangles;

* Dyntopo triangulates faces as it finds them.
  - I looked into methods of preserving quads and failed to
    find anything that worked well in practice; it actually
    worked better to use topology rake to align triangles
    into quads and then mark diagonal edges for later dissolving
    then to try to preserve quads explicitly (I've not
    implementated that here, that was research code).
  - To avoid excessive cache-destroying loops over vertex-faces,
    DynTopo flags which verts have non-triangle faces.

* PBVHTriBuf now builds edge buffers so we can avoid drawing
  tesselation phantom edges.

* BMLog also now supports arbitrary faces.  It still does not
  support edges though.

TODO:

* Fix vcol cell shading mode
* Make sure indexed drawing works
2021-07-20 19:46:00 -07:00
93305b97df Merge branch 'master' into sculpt-dev 2021-07-20 18:28:53 +02:00
7cd74015f8 Sculpt dyntopo: Another fix for faceset boundary handling
* Turned out pbvh->cd_faceset_offset wasn't being updated
  correctly.
2021-07-20 05:47:08 -07:00
7bd521a5c4 Sculpt dyntopo: Another small fix 2021-07-20 04:56:29 -07:00
7dda5ac5ba A few small fixes for last commit 2021-07-20 04:29:23 -07:00
1694e2aca4 Sculpt dyntopo: Face set boundaries are now presered with dyntopo
* Face set boundaries are now preserved on dyntopo remeshing.
* MDynTopoVert->flag now has a DYNVERT_FSET_BOUNDARY flag
  in addition to DYNVERT_BOUNDARY.
* Instrumented uiBut with ASAN poison regions to hopefully
  find the super evil memory corruption bug that's been driving
  me insane.  It's frustratingly intermittent.  There are five
  poison regions.
2021-07-20 04:14:59 -07:00
2fddbebf93 Sculpt dyntopo: Dyntopo now handles mesh boundaries in a more
intelligent way.
2021-07-19 15:32:41 -07:00
4247a56cde Add back hackish fix for clang bug. I should probably
file a bug report with the clang people.
2021-07-18 13:15:43 -07:00
e3b58b6451 Sculpt dyntopo: Split off dyntopo stuff from pbvh_bmesh.c into a new file, dyntopo.c. 2021-07-18 13:12:08 -07:00
5b10d08db3 Sculpt dyntopo:
* Prototyped a threaded bmesh->Mesh converter function.  It's about
  20-30% faster.  Currently disabled.
* Tried to fix more of the bugs when stepping between sculpt and
  other undo step types in the global undo stack.
2021-07-17 04:10:28 -07:00
7c4eb4f8db Merge branch 'master' into temp_bmesh_multires 2021-07-17 00:44:01 -07:00
792292e3de Sculpt dyntopo: BLI_mempool now adds redzones when compiled with ASAN 2021-07-16 23:29:28 -07:00
95a969e7d5 Array Brush: Disable debug drawing 2021-07-15 21:20:48 +02:00
f9c0c9e70c Merge branch 'master' into sculpt-dev 2021-07-15 21:16:12 +02:00
aousdfh
3600e9057b Array Brush: expose fill holes and orientation lock 2021-07-15 21:00:14 +02:00
aousdfh
a78ecfe0f3 Array Brush: Fix crash 2021-07-14 02:57:07 +02:00
aousdfh
65127f9875 Array Brush: Refactor array indices access 2021-07-14 02:02:26 +02:00
aousdfh
37c2bbe5ea Array Brush: Fix EEVEE and modifier evaluation 2021-07-13 19:22:00 +02:00
aousdfh
ceac1d91e2 Array Brush: Fix scale, symmetry and rotation jittering 2021-07-13 02:16:05 +02:00
aousdfh
dfab5a0c4a Array Brush: Array rotation orientations working 2021-07-13 00:37:10 +02:00
aousdfh
85379482d5 Array Brush: Orientation detection working 2021-07-12 23:49:22 +02:00
4ca249018d More msvc errors 2021-07-12 16:03:22 -04:00
d529e13d65 Sculpt dyntopo: fix msvc compiler error 2021-07-12 16:01:17 -04:00
4e797dbc69 Definitely going to modify BLI_strict_types.h 2021-07-12 12:30:23 -04:00
aousdfh
41a8e94d4d Array Brush: First attempt to copy orientation (disabled) 2021-07-12 17:48:42 +02:00
1b9a835893 Make gcc happy 2021-07-11 23:57:14 -04:00
320a1b6f35 Fix bug in previous commit; customdata_bmesh_set_default now ignores
CD_MESH_ID layers
2021-07-11 23:28:19 -04:00
f07f56aa37 BM_mesh_create will now add mesh_id customdata layers when asked,
instead of leaving that to the client.

Also semi-fixed uninitialized memory bug in bmesh unit test (dunno
how best to memset a C struct in C++ won't won't run afoul of some
random compiler somewhere).
2021-07-11 22:02:52 -04:00
4e91e72d53 Let's try that again 2021-07-11 21:21:10 -04:00
58b4688c34 Weird linux compile error 2021-07-11 21:20:37 -04:00
2f862bc7b9 Fix more dyntopo sculpt undo memory corruption 2021-07-11 21:14:49 -04:00
4674795591 Sculpt dyntopo: another attempt to fix undo memory corruption bug 2021-07-11 13:14:24 -04:00
be9017c349 Fix implicit int error 2021-07-11 06:01:39 -04:00
4c2f5b80b7 Remove extraneous code 2021-07-11 05:25:41 -04:00
0502b0103f Merge branch 'master' into temp_bmesh_multires 2021-07-11 05:23:24 -04:00
e8b717ee42 Sculpt dyntopo: Exposed UV smooth bruth in experimental features prefs.
* Also got undo working for it
2021-07-11 04:12:20 -04:00
4b4ac93acd Sculpt dyntopo: Wrote a little UV smoother sculpt brush.
It uses a simple LSCM-like solver; hold ctrl to do simple
laplacian relaxation.

There are some interesting artistic possibilities to using
DynTopo with UV maps, the point of this tool is to help
explore them.

Note that I'm not planning to merge this into master with
the rest of this branch.  When the time comes I plan to
move it into a new branch for sculpt research stuff.
2021-07-11 03:43:47 -04:00
aousdfh
f283c527d2 Array Brush: Scale and stroke strength working 2021-07-09 00:01:56 +02:00
aousdfh
820d086719 Array Brush: Count and deform mode brush properties 2021-07-07 03:26:52 +02:00
aousdfh
69668d62ba Array Brush: Working code for path and radial arrays 2021-07-07 02:20:14 +02:00
aousdfh
351744f2b0 Sculpt Array: Debug path drawing 2021-07-06 01:21:14 +02:00
aousdfh
5ac471a021 Sculpt Array: Initial code for path and path points 2021-07-06 01:06:15 +02:00
aousdfh
db932ccde6 Array Brush: Implement symmetry datalayers 2021-07-06 00:44:49 +02:00
57286eed8d Sculpt dyntopo: Add support for multiple materials to dyntopo
pbvh drawing.

* Dyntopo now stores a list of PBVHTriBufs in leaf nodes, one per material
  used by the node.
* Actual drawing buffers live in a new mat_draw_buffers PBVHNode member.
2021-07-02 13:14:00 -07:00
9dbf3b9fab Array Brush: Implement array instances datalayer 2021-07-02 22:10:21 +02:00
4f8c63e77b Array Brush: BMesh duplication working 2021-07-02 19:52:58 +02:00
47c226cbe3 Array Brush: Add template code and support geometry modifications 2021-07-02 16:38:37 +02:00
d0759840a0 Merge branch 'master' into temp_bmesh_multires 2021-06-30 21:38:18 -07:00
5b19b2cb56 remove debug printf 2021-06-30 21:25:46 -07:00
dcb00bf529 * Enable mask/fset extract for dyntopo]
* Fix nasty memory corruption bug
2021-06-30 21:13:24 -07:00
e8e062f866 Merge branch 'master' into sculpt-dev 2021-06-30 18:12:50 +02:00
9838e9e485 Merge branch 'master' into sculpt-dev 2021-06-30 01:31:21 +02:00
d66d5b431e Clean up a few warnings 2021-06-29 05:50:40 -07:00
43a0fe378f Merge branch 'master' into temp_bmesh_multires 2021-06-29 04:35:53 -07:00
199f846072 Merge branch 'master' into sculpt-dev 2021-06-28 19:44:07 +02:00
fb6636c812 Sculpt dyntopo: fix bug with automasking being needlessly initialized 2021-06-26 23:46:47 -07:00
adc8980dec Sculpt dyntopo: fix symmetrix undo bug from last commit 2021-06-26 22:52:35 -07:00
48c41b189a fix type of code line being after the parenthesis
instead of before
2021-06-26 21:40:07 -07:00
7562ad5777 Sculpt dyntopo: BMLog now uses the new bmesh unique id system
A few notes:

* MESH_ID layers are not saved on conversion to Mesh unless
  you ask for it in BM_mesh_bm_to_me's params.
* Still need to test the box/lasso trim tools.
* Need to find some way to test loop/edge ids, which aren't
  used by dyntopo.
2021-06-26 21:26:33 -07:00
27986e9b56 Sculpt dyntopo: Added a function to add multiple customdata
layers to a bmesh at once.  Helpful since bmesh customdata
layers are allocated in single blocks, thus adding
layers individually can lead to lots of memory
copying.
2021-06-26 19:12:07 -07:00
dba4f30328 Sculpt dyntopo: Added (optional) support for unique mesh id tracking in
bmesh

* System is per element type.  So you can have unique ids for verts and
  faces, but not edges and loops.
* Supports an optional id to element lookup table.
* Uses single id space for all elements
* Added a new CD_FLAG_ELEM_NOCOPY flag to tell
  customdata_bmesh_copy_data to ignore that layer.
* IDs are stored as a temporary customdata layer with
  CD_FLAG_ELEM_NOCOPY set.
2021-06-26 18:24:00 -07:00
83c491f044 Merge branch 'master' into temp_bmesh_multires 2021-06-26 13:00:26 -07:00
7ef7843ada Sculpt Dyntopo: Fix memory corruption in dyntopo undo
ss->active_XXX_index wasn't being handled properly.
2021-06-25 17:10:12 -07:00
5a7b9adef1 Dyntopo sculpt: add support for asan to mempool 2021-06-25 15:04:09 -07:00
d293de425f Sculpt Dyntopo: fix bug in dyntopo brush spacing. 2021-06-25 11:49:28 -07:00
17d4c7abb1 Sculpt dyntopo:
* Got automasking to work with dyntopo properly.
  - AutomaskingCache->factor
    has been replaced with the new temp layer API (which works for all
    PBVH modes).
  - AutomaskingCache->factor is, however, only initialized for
    topology and face set boundary modes (if DynTopo is enabled)
    since it's probably better to calculate the rest dynamically
    in that case.
* Fixed stats bug
2021-06-24 23:50:49 -07:00
2f81449a70 Twist brush: use relax instead of smooth 2021-06-22 01:20:36 +02:00
ca4ac36c59 Merge branch 'master' into temp_bmesh_multires 2021-06-20 15:58:24 -07:00
5c328ab8b0 Twist Brush: Add separate smooth step 2021-06-20 18:32:19 +02:00
7a67cb2aeb Twist Brush: Fix bug in rotation 2021-06-20 17:53:35 +02:00
178c3a4064 Twist Brush: Scale brush tip space per vertex 2021-06-20 17:34:20 +02:00
15884510e8 Twist Brush: Deform rotation space 2021-06-20 17:21:53 +02:00
22e2e4f062 Twist Brush: Rotate in brush tip space 2021-06-20 17:12:05 +02:00
3ccc160682 Merge branch 'master' into sculpt-dev 2021-06-20 16:46:21 +02:00
00fd823bcd Sculpt dyntopo: Don't calculate curvature info in topology rake if curvature
mode is not enabled.
2021-06-19 23:54:51 -07:00
d9badbf25c Merge branch 'master' into sculpt-dev 2021-06-19 22:12:13 +02:00
f16e35ce0a Twist Brush: Initial working version 2021-06-18 22:01:26 +02:00
425e5c8d76 Twitst Brush: initial commit 2021-06-18 21:44:29 +02:00
1ab412f13d Merge branch 'master' into sculpt-dev 2021-06-18 21:24:36 +02:00
ee1c0c682b Fix build in edit mode mesh fairing 2021-06-16 21:06:27 +02:00
59f0811ac9 Merge branch 'master' into sculpt-dev 2021-06-16 21:01:43 +02:00
45f522888b Merge branch 'master' into sculpt-dev 2021-06-14 22:53:41 +02:00
d15262ded1 Merge branch 'master' into sculpt-dev 2021-06-11 21:58:12 +02:00
ab5b138805 Merge branch 'master' into sculpt-dev 2021-06-08 22:56:21 +02:00
8ca52a7757 Merge branch 'master' into temp_bmesh_multires 2021-06-07 16:57:33 -07:00
d4af8a8d26 Sculpt: Make subdivision surface modifier use the On Cage option 2021-06-04 16:20:38 +02:00
b1e59f1a20 Merge branch 'master' into sculpt-dev 2021-06-03 22:46:38 +02:00
bd34d77a90 Merge branch 'master' into sculpt-dev 2021-06-03 20:24:11 +02:00
3ac83dcc73 Merge branch 'master' into sculpt-dev 2021-06-01 14:26:49 +02:00
900178d438 Fix build after merge 2021-06-01 14:22:49 +02:00
414b8b7628 Merge branch 'master' into sculpt-dev 2021-06-01 12:52:07 +02:00
4adc0a7798 Dyntopo: do a little bit of code cleanup 2021-05-31 10:53:22 -07:00
88620e8cd9 Merge branch 'master' into sculpt-dev 2021-05-31 11:14:07 +02:00
552e44bd25 Fix implicit int error 2021-05-27 14:30:45 -07:00
1f19a86150 DynTopo:
* Fixed failed patch reversion from a while ago
* Also tweaked a few comments.
2021-05-27 12:15:49 -07:00
702376e935 Merge branch 'master' into sculpt-dev 2021-05-27 11:24:32 +02:00
3ca3098ed7 DynTopo: Enable BLI_linklist_stack type checking for clang-cl
and fix a few errors.
2021-05-24 11:40:05 -07:00
995702da48 Let's try that again. 2021-05-23 21:39:37 -07:00
33066542ca MIssed a flag in bli_strict_types.h 2021-05-23 21:34:20 -07:00
5a26ea0961 DynTopo: Attempt to fix compiling on macos 2021-05-23 21:02:29 -07:00
1e3e79fe7b Fix one more strict flags violation 2021-05-23 20:52:25 -07:00
d4292bbd28 * Added clang-cl support to BLI_strict_flags.h 2021-05-23 20:39:52 -07:00
a97c5d7daa DynTopo: started refactoring pbvh drawing to handle customdata layers in
a more generic (and maintainable) way.
2021-05-23 16:11:16 -07:00
6b009b8890 Merge branch 'master' into temp_bmesh_multires 2021-05-23 14:30:32 -07:00
3d16099a77 Dyntopo:
Fix multires not setting pbvh->depth_limit
2021-05-20 17:59:09 -07:00
4352980b0f Dyntopo
* Got threaded mesh->bmesh conversion working (it's disabled
  pending further testing however).

Note that SCULPT_dynamic_topology_enable_ex calls BKE_scene_graph_update_tagged,
which in tests was adding ~1 second to conversion time for larger
meshes.  Do we need this call?
2021-05-19 14:36:00 -07:00
3d6ac0bd7b Dyntopo: code cleanup 2021-05-19 12:21:46 -07:00
71959181ad * Fix bug with symmetrize creating non-manifold geometry.
* Fix bug in pbvh face create
2021-05-18 22:26:49 -07:00
daa4a33383 Merge branch 'master' into temp_bmesh_multires 2021-05-17 19:48:16 -07:00
d3695eb12c * Fix corner case in last commit 2021-05-17 14:23:02 -07:00
c1f236dcd4 BMLogFace now stores the face normal. 2021-05-17 14:02:31 -07:00
3276c3b4a1 Merge branch 'master' into sculpt-dev 2021-05-17 22:08:28 +02:00
a90533e9b8 Cleanup failed patch reversion 2021-05-17 00:45:07 -07:00
9bea7259e1 Merge branch 'master' into temp_bmesh_multires 2021-05-16 23:32:35 -07:00
7fca310f25 Dyntopo now updates the existing pbvh on undo instead of building
a new one from scratch, an operation that can be slow despite being
  threaded.

PBVH building is a memory bound operation (not just on the CPU side
either, remember the draw buffers have to be fully regenerated too).
Incrementally updating it this way is enormously faster (about as fast
as non-dyntopo undo).

The downside is we don't have the convienience of users regularly
building the pbvh from scratch anymore.  Dyntopo does try to
join empty PBVH nodes (which happens after every stroke), but
that's not a complete substitute for a decent tree balancer.
That's on the todo list.
2021-05-15 21:19:20 -07:00
27f4f761e7 Tried to make pbvh bmesh normals calc a bit more efficient. 2021-05-15 11:51:14 -07:00
17fafe2f63 fix memory leak 2021-05-14 21:21:01 -07:00
89d56ea225 fix missing null pointer check. 2021-05-14 21:12:23 -07:00
cfd6d48aab * Prototyped a faster smooth algo, currently disabled.
* Wrote a new API for wrangling temporary customdata layers across pbvh types:
  - SCULPT_temp_customlayer_ensure: makes sure a (named) customdata
    layer exists.  Works for multires; since these are temporary
    layers we can safely allocate them in a temporary CustomData
    structure (in ss->temp_vdata).
  - SCULPT_temp_customlayer_get: initializes a special structure,
    SculptCustomLayer, that is used to get per elem customdata.
  - SCULPT_temp_cdata_get: Uses a SculptCustomLayer ref along with
    a SculptVertexRef to look up the data.
2021-05-14 18:26:41 -07:00
6be2c079c1 Did some profiling with VTune.
* Sculpt code seems to be memory bandwidth bound.
  * Some key topology loops will have to be written manually
    instead of using BM_ITER.

I wrote a function to re-allocate a bmesh with elements ordered by
PBVH leaf nodes, SCULPT_reorder_bmesh.  It's currently disabled.

This is going to take more profiling, but my original proxy refactor
idea might be worth revisiting.  Might be more cache efficient.

The good news is that the worst case is the smooth code, which I can speed
up significantly by keeping a bit of state around.
2021-05-14 15:56:04 -07:00
ae5d971e8f Merge branch 'master' into sculpt-dev 2021-05-14 19:09:06 +02:00
13bdc4a7e6 Merge branch 'master' into sculpt-dev 2021-05-14 19:08:19 +02:00
72aad83780 Merge branch 'master' into sculpt-dev 2021-05-13 17:43:21 +02:00
32ceaa7919 Update ATTR_NO_OPT macro 2021-05-12 22:27:35 -07:00
ec4786d00b Dyntopo branch
* Sculpt expand now works with dyntopo in more cases
* Fixed various dyntopo face set bugs

Stuff from several commits ago:

* There is now an API to get face sets using SculptFaceRef's.
  + SCULPT_face_set_get
  + SCULPT_face_set_set

* Prototyped a faster geodesic propagation function, but it currently
  doesn't work.

* Dyntopo triangulation now preserves face flags (took some work as BM_triangulate_face explicitly prevents selection flags from being preserved).
* Also face smooth flags are no longer being overriden.
* Most of the faceset create operators work (I'm not sure I've tested
  all of them though).
* SCULPT_face_set.c now has helper functions that checks if a pbvh
  is *not* PBVH_BMESH, in which case it builds a temporary bmesh,
  otherwise ss->bm is used (sculpt_faceset_bm_begin and sculpt_faceset_bm_end).
  + Note that some functions were able to use SCULPT_face_set_XXX
    instead and avoid bmesh entirely.
2021-05-12 16:22:39 -07:00
582c30d32f Fix nasty edge case for BMLog. 2021-05-11 22:57:06 -07:00
b047b333b0 Remove yet more debugging crap . . . 2021-05-11 21:48:14 -07:00
f2c9706781 Get rid of various ATTR_NO_OPT debug attributes left from two
commits ago.
2021-05-11 21:46:44 -07:00
fa06238aa7 Fix bug in last commit. 2021-05-11 21:45:43 -07:00
b8a8e4f9b1 Today I ran outside screaming and an hour later came back in and made BMLog
reference counted.  This fixes various undo bugs caused by dyntopo
needing to execute an undo push but not being able too (e.g. during
file load, and I think it also happens sometimes with global undo).

A much better way of fixing this would be to add unique IDs to mesh
verts and faces, perhaps as a customdata layer.

The root problem is that BMLog assigns unique IDs to mesh elements,
which it does via a series of GHash's.  I imagine this is a fairly
serious violation of the undo system's design rules, since it means
BMLogs are tied to specific instances of the bmesh in SculptSession->bm.

There were some hacks to try and get around this, but they were buggy
and needed to push the unstack stack to work, which wasn't possible in
all cases (e.g. if G_MAIN->wm.first->undo_stack is NULL, as it is during
file loading and apparently global undo).

Anyway, long story short each chain of SculptUndoNodes needs some way
to reconstruct their ID GHash's when exiting/entering the chain. The
only way I could think to do this was to make BMLog reference counted,
with BMLogEntry the users.

Like I said, having a proper system to assign unique IDs to mesh
elements would be *much* better.
2021-05-11 21:14:45 -07:00
dbe767f5d9 Merge branch 'master' into temp_bmesh_multires 2021-05-11 14:18:48 -07:00
fad42fc6c7 Merge branch 'master' into sculpt-dev 2021-05-10 19:01:57 +02:00
7cf3b1f472 Get face set create operator working for dyntopo 2021-05-07 07:04:19 -07:00
6c3b29a14c Merge branch 'master' into temp_bmesh_multires 2021-05-05 08:52:14 -07:00
febfaecd97 * Added new paint API method paint_stroke_apply_subspacing, for various
things that need custom spacing (that is coaser than the brush radius),
  and refactored the existing dyntopo spacing code to use it.

* Added option to topology rake to ignore brush falloff settings
  (it forcibly uses Smooth falloff).

* Smooth and topology rake support custom spacing now.
  + This is especially important for the clay brush, which works
    better at smaller spacings and with a bit of autosmoothing.
    Now you can tell it to override the smooth spacing to be coarser,
    leading to much better performance.

* Topology rake now has a projection setting similar to autosmooth
  which defaults to 1.0 (to preserve current behavior).

The main motivation for this commit was to make topology rake work
better for normal brushes.  This is now possible, however it tends to
make the brush slower and also the settings are a bit fiddly.
We might want to make dedicated brush presets for this.

Btw, the UI for brush settings are becoming a real mess. Help!
2021-05-02 14:29:30 -07:00
2d98802905 * Added a "projection" option to smooth/autosmooth. It works by
projection neighboring vertices onto the current smooth vert's normal
  plane, multiplied by a "projection" factor.  This is extremely similar
  to what the surface laplacian produces, but is much simpler, uses
  no temporary state and thus can be used in more places.
2021-05-02 10:54:12 -07:00
f70a8c1581 Merge branch 'master' into temp_bmesh_multires
Also fixed a pose brush bug that may or may not have been
the result of the merge nixing code, need to check master.
2021-04-29 10:17:22 -07:00
8eeacca9cb Fix a few cast warnings 2021-04-29 08:01:32 -07:00
82847af9f9 Fix invalid parameter type in bmlog. 2021-04-29 06:28:37 -07:00
ee19a80041 * Eeek, left in an ATTR_NO_OPT attribute 2021-04-28 19:31:43 -07:00
013eee7ec6 * The dyntopo remesher is now a bit smarter about avoiding
certain degenerate cases that produce lots of bad geometry (and
  also bad PBVHs that slows down the whole mesh).
 + A very small amount of surface smoothing is now applied by dyntopo.
 + The recursive functions that expand the region considered by dyntopo
   now ignore "front face only" for depths less then 5.
 + The number of edges dyntopo can split or collapse in one run has been cut in
   half to 4k.
   - This limit is also now dynamically adjusted by a measure
     of how skinny the edges are.
2021-04-28 19:11:23 -07:00
ce0b4e6681 Merge branch 'master' into sculpt-dev 2021-04-28 21:55:09 +02:00
d1cf59e547 Sculpt: Add operator to store a limit surface manually 2021-04-27 23:54:04 +02:00
d0407b0ed5 Merge branch 'master' into sculpt-dev 2021-04-27 22:42:21 +02:00
83a855a8a1 fix compile error 2021-04-27 13:38:14 -07:00
9e46eebcf1 Fix last commit flipping the order of booleans. 2021-04-27 13:20:36 -07:00
786781304c * Got box trim tool working for dyntopo
- This required implementing SCULPT_UNDO_GEOMETRY for dyntopo.
    That turned out to be more work then I expected.  Basically
    it writes an entire Mesh to BMLogEntry, which can be swapped
    with current bmesh.  Tricky part was patching bm log ids.
2021-04-27 13:04:36 -07:00
2e888bfe6c Fix possible crash with dyntopo and clay strips normal filter 2021-04-27 21:31:25 +02:00
901d6e68d7 Merge branch 'master' into sculpt-dev 2021-04-27 21:31:00 +02:00
3028d53865 Edit face set brush now works for pbvh bmesh 2021-04-27 09:51:49 -07:00
fb5f6e762e Merge branch 'master' into sculpt-dev 2021-04-27 18:31:19 +02:00
02b4df9827 Enable color filter brush for pbvh bmesh 2021-04-27 09:12:35 -07:00
815d77192f One more null ptr check 2021-04-27 09:07:00 -07:00
9fab16f0f3 * Fix null ptr bug in automasking code 2021-04-27 09:01:32 -07:00
82f5e0200c * Fix bug in last commit where boundary flags weren't properly
updated after symmetrize.
2021-04-26 17:44:38 -07:00
032a35fb50 Fix memory corruption in sculpt neighbors code 2021-04-25 15:12:11 -07:00
8a700673db * Boundary info is no longer initialized with
SCULPT_boundary_info_ensure, instead PBVH_BMESH keeps
  track of boundary vert flags internally.  This prevents
  nasty first-click lag on the smooth brush as well as anything
  with autosmooth.
2021-04-25 14:51:31 -07:00
0386350de6 * Fixed SCULPT_dynamic_topology_sync_layers to properly sync
active/render/clone/mask layers indices.
* Fixed sculpt color bugs in pbvh drawing for bmesh.
2021-04-25 14:02:39 -07:00
d912d4735a Merge branch 'master' into sculpt-dev 2021-04-22 21:23:44 +02:00
97fc606c65 Fix nasty crash in dyntopo with non-manifold geometry. 2021-04-21 10:00:02 -07:00
14be52f0fc * Fixed vcol drawing in indexed smooth shading mode 2021-04-20 15:40:03 -07:00
739bb8f1d2 Merge branch 'master' into sculpt-dev 2021-04-20 22:43:50 +02:00
7107753f73 Merge branch 'master' into sculpt-dev 2021-04-20 17:56:22 +02:00
73c590e1eb Added detail_size to local dyntopo brush settings 2021-04-20 06:34:35 -07:00
44fd07c1c8 Merge branch 'master' into sculpt-dev 2021-04-19 23:24:55 +02:00
931a8da26c Merge branch 'master' into sculpt-dev 2021-04-19 20:14:24 +02:00
895fef5ccb Sculpt: Add area normal test to clay strips for better front faces detection 2021-04-18 20:10:12 +02:00
b82a2fd9ab Fix wrong visibility flush with Face Sets 2021-04-18 19:36:44 +02:00
18a86af416 Fix neighbor connectivy with hidden edges 2021-04-18 19:00:02 +02:00
a0b5fd9cb6 Fix Scene project brush after merge 2021-04-18 18:14:45 +02:00
553e8ffd1a Merge branch 'master' into sculpt-dev 2021-04-18 18:04:00 +02:00
fdc6fb2c53 SCULPT_calc_principle_curvatures now has option to use
slower but more accurate BLI_eigen_solve_selfadjoint_m3 solver.
2021-04-17 20:25:51 -07:00
8bc9286c4c Merge branch 'master' into sculpt-dev 2021-04-16 19:52:23 +02:00
4f8693652b Sculpt Symmetrize: Fix missing updates with modifiers 2021-04-16 01:47:27 +02:00
d29378c2f2 Sculpt Symmetrize: Free the symmetrize map on changes 2021-04-16 01:31:44 +02:00
0e6c07c063 Sculpt Symmetrize: Prevent crash with dyntopo and multires 2021-04-16 01:30:02 +02:00
cb3e0ff344 Sculpt Symmetrize: Add brush falloff 2021-04-16 01:29:12 +02:00
11d1fdeb34 Sculpt Symmetrize: Fix bug in main brush loop 2021-04-16 01:25:22 +02:00
430641d481 Sculpt Symmetrize: Initial working version 2021-04-16 01:24:49 +02:00
4745f29971 Sculpt Symmetrize: Add base symmetrize map code 2021-04-16 00:56:39 +02:00
8512b1b5dd Sculpt Symmetrize: sculpt_symmetrize file and main loop 2021-04-16 00:47:08 +02:00
674bc2e4b4 Sculpt Symmetrize: Initial commit 2021-04-16 00:38:47 +02:00
b240973412 Object: Make flash animation slower 2021-04-15 20:28:04 +02:00
39994c3208 Object: Use theme select color for animation 2021-04-15 20:26:45 +02:00
8189f2c806 Merge branch 'master' into sculpt-dev 2021-04-15 20:14:30 +02:00
237ac342c9 Merge branch 'master' into temp_bmesh_multires 2021-04-14 22:07:27 -07:00
465e804193 commit prior to merge 2021-04-14 22:04:36 -07:00
4ab8614cd1 Last attempt at fixing boundary brush for now. Unassigned boundary
verts now get bend data from their neighbors.  Still isn't quite
satisfactory but better then before.
2021-04-14 22:02:32 -07:00
dabff9af7d * Fix crash in boundary sculpt tool
* For some reason boundary tool sometimes fails to match verts to
  boundary verts.  It now simply freezes them in place if that happens
2021-04-14 18:41:23 -07:00
384a0930d1 Commit current code state 2021-04-14 15:55:09 -07:00
a5fa9ec310 Fix another crash 2021-04-13 01:44:29 -07:00
ed15d0c1b9 Fix infinite loop bug 2021-04-13 01:08:05 -07:00
e07a95b86d Fix extremely nastly memory corruption bug in pbvh 2021-04-12 04:19:49 -07:00
b52e04f794 * Fix bug in last commit, broke draw brush 2021-04-11 23:39:25 -07:00
e74c298cf9 Fix dyntopo undo bug 2021-04-11 22:03:16 -07:00
cd485a7c6f fix last commit 2021-04-11 21:44:00 -07:00
06341c19c4 Fix crash 2021-04-11 21:42:47 -07:00
a527bd5f48 Get rid of various __attribute__((optnone)) I had scattered throughout
the code
2021-04-11 19:29:06 -07:00
7f14d519c0 * Dyntopo cleanup mode is now on by default.
* Fixed undo bug
2021-04-11 18:19:13 -07:00
64337d087d * Merge branch 'master' into temp_bmesh_multires
* Implemented DynTopo option to dissolve 3 and 4-valence
  vertices.
* Fixed bug in dyntopo collapse customdata snapping.
2021-04-11 17:59:16 -07:00
e1fae3cbee Fix do_versions check 2021-04-11 12:34:15 -07:00
7dbb4c9b2d Fix issues with last commit. Also, simplify brush now
uses dyntopo local overrides to always enable collapse instead
of being hardcoded.
2021-04-11 12:27:02 -07:00
fe67ca56d6 * Fixed wireframe drawing in vcol cell drawing mode
* Added UI for editing local brush dyntopo settings.
2021-04-11 11:38:27 -07:00
68e4e1bb41 Merge branch 'master' into sculpt-dev 2021-04-11 17:43:40 +02:00
881df30a46 Cavity masking now has a checkbox in the UI, instead of simply turning
itself on if the concave mask factor is > 0.
2021-04-07 22:49:39 -07:00
6f91eaad39 * Fixed an annoying number of undo bugs
* Original data for bmesh pbvh is no longer handled by the undo code.
  This should eliminate a whole class of subtle and hard to track down
  bugs.
2021-04-07 20:39:16 -07:00
55045ed85a SCULPT_dyntopo_ensure_templayer no longer returns a customdata offset.
Making multiply layers sequentially can lead to corrupted offsets.
Instead, ensure all layers exist with SCULPT_dyntopo_ensure_templayer
first,

then get all the offsets at once.
2021-04-07 02:03:32 -07:00
2582090824 Fix bug in previous commit, code was being subject to inside
brush test that should not ahve been.
2021-04-07 01:46:10 -07:00
55415cd62a * Layer brush now supports dyntopo.
- To do this I made a little API to make scratch
    customdata layers: SCULPT_dyntopo_[ensure/get]_templayer.
    Takes a customdata type and a layer name (e.g.
    '__dyntopo_bleh") and returns a customdata offset.
  - Note that I also did this for the persistent base code.

* Added a macro to check if a tool supports splitting the PBVH
  during a stroke, DYNTOPO_HAS_DYNAMIC_SPLIT.  It is in sculpt_intern.h
  (for now) to avoid the enormous amount of recompiling that is
  triggered if DNA_brush_enum.h is modified.

* TODO: Right now the undo code resets original vertex coordinates for
  bmesh PBVH.  This means tools that rely on original data (sharp and
  layer) can't split the pbvh during the stroke, since that will
  allocate new undo nodes and reset original coords.

  The solution is to move the original data API entirely out of the undo
  code.
2021-04-07 01:20:21 -07:00
d29bdda34c Fix build error with include 2021-04-06 19:56:17 +02:00
e3ee04dec5 Object: Flash objects on mode transfer 2021-04-06 19:49:18 +02:00
347c8255ed Merge branch 'master' into sculpt-dev 2021-04-06 17:49:13 +02:00
8aac19cab5 Merge branch 'master' into temp_bmesh_multires 2021-04-05 21:26:04 -07:00
b4536d274c Forgot to increase array size for data transfer modifier struct. 2021-04-05 21:24:38 -07:00
d3ffaa8e52 Merge branch 'master' into sculpt-dev 2021-04-05 18:22:38 +02:00
f5588dfb70 Merge branch 'master' into temp_bmesh_multires 2021-04-03 19:29:12 -07:00
4b308888d8 Add support for sculpt colors to the data transfer modifier 2021-04-03 19:23:15 -07:00
fdfa2045ec Add a paranoia check 2021-04-02 13:55:48 -07:00
33af94dc46 Fixed an out of bounds read error. 2021-04-02 13:42:29 -07:00
8ea624aeaf fix gcc build errors 2021-04-01 15:58:56 -07:00
e29cd298fe Fix last commit to handle symmetrical brushing properly 2021-04-01 15:09:50 -07:00
7bba304c57 * Dyntopo now has its own brush spacing. This is a huge performance
boost for brushes with fine spacing, e.g. the clay brush.
2021-04-01 14:51:10 -07:00
0dc09668ce Finished curvature rake. 2021-04-01 13:07:10 -07:00
cfa6753518 wrote a fast and inaccurate distance to triangle function
for DynTopo.  Profiling consistently showed it to be a bottleneck.
I've now written scalar versions of this function four times.

For now I'm committing this inaccuration version.  I'm also committing
code for a vectorized version I found in a paper.  Still need to rejigger
the dyntopo code to use it though.
2021-03-30 19:00:08 -07:00
2cf8c35578 Merge branch 'master' into temp_bmesh_multires 2021-03-30 00:57:43 -07:00
aa116ba5ba Added per-brush DynTopo settings which are stored in a new DynTopoSettings struct.
This system is designed to inherit settings from scene dyntopo defaults
in a highly flexible way; settings can be individually overridden via the
.inherit bitmask.

At stroke time the scene settings and brush->dyntopo are merged
and stored in brush->cached_dyntopo.

Note that brush->flag has a bit flag, DYNTOPO_DISABLED, with a few
subtlies.  It does not switch the PBVH back to PBVH_FACES mode, it
simply disbles dyntopo topology update.  It also doesn't inherit from
any default settings.  And it's the only setting
that's currently exposed in the UI.
2021-03-30 00:08:09 -07:00
d2c1357fc5 Sculpt: Initial implementation of uniform smoothing 2021-03-27 21:52:24 +01:00
0bf2a1f8fe Merge branch 'master' into sculpt-dev 2021-03-27 21:27:41 +01:00
7be027075f Add this file 2021-03-26 14:23:31 -07:00
215c346017 Only send all vcol layers to gpu (for pbvh drawing) in a material
draw mode.
2021-03-25 17:38:27 -07:00
7c9235d0e0 * Sculpt color layers are now properly handle by pbvh bmesh draw code.
Before only the active layer was uploaded to the GPU, now all of them
  (except the autogenerated original color layer) are.
2021-03-25 17:17:42 -07:00
e254cc23b2 Code cleanup 2021-03-25 11:32:20 -07:00
f5a122309d Sculpt Poly Loop: Fix symmetry 2021-03-25 02:46:00 +01:00
dee286fc7e clean up code a bit 2021-03-24 17:01:53 -07:00
ab9b89ac5d Fixed two remaining performance bugs with dyntopo:
* Normals are now updated in threads.
* The sculpt neighbor code was using the slower BM_LOOPS_OF_VERT
  instead of BM_EDGES_OF_VERT, fixed.
2021-03-24 14:09:02 -07:00
ce9e0b53b1 Sculpt Expand: Default Face Set boundary modes to topology 2021-03-24 21:20:09 +01:00
ce6d9112aa Sculpt Poly Loop: Symmetry support 2021-03-24 20:55:31 +01:00
20f4fe138e Merge branch 'master' into sculpt-dev 2021-03-24 20:55:05 +01:00
ecbf642ddd Cleanup: Clang format 2021-03-24 18:48:39 +01:00
caf5f5767f Cloth Filter: Add pinch origin modes 2021-03-24 18:47:01 +01:00
e0cc387124 Cloth Filter: Add symmetry support to pinch deformation mode 2021-03-24 18:12:55 +01:00
ebeb144701 Merge branch 'master' into sculpt-dev 2021-03-23 17:54:08 +01:00
924b13b03a * Added a new CustomData type for dyntopo vertex data: MDynTopoVert.
It stores:
   - Original coordiates, colors and mask (which were previously four
     seperate layers).
   - A bitmask with (currently) one bitflag, whether or not a vertex is
     on a boundary.

I needed to cache calculating vertex boundary state (which involves
iterating over the edges surrounding a vertex) and got fed up with
having so many CD layers for dyntopo.  This struct consolidates them
and saves having yet another layer just to store a flag.
2021-03-21 16:26:38 -07:00
75a1116b51 Merge from master 2021-03-19 18:01:12 -07:00
73a4b885ec Merge branch 'master' into sculpt-dev 2021-03-19 20:08:30 +01:00
f6cda6bf88 Merge branch 'master' into temp_bmesh_multires 2021-03-19 10:57:32 -07:00
9ce0a2815d Merge branch 'master' into sculpt-dev 2021-03-19 18:44:23 +01:00
7d7dcce859 Merge branch 'master' into sculpt-dev 2021-03-18 16:42:53 +01:00
f429a7dc13 Sculpt Expand: Split snap event into two separate events 2021-03-17 16:58:56 +01:00
257562ad6d Sculpt Expand: Add Poly Loop Falloff mode 2021-03-17 16:49:08 +01:00
8883c76b9a Merge branch 'master' into sculpt-dev 2021-03-17 16:20:44 +01:00
dd77b22626 Face Sets Topology: Improve keymap and creation delay 2021-03-17 03:03:02 +01:00
3d70805a68 Sculpt Poly Loop: Improve loop direction detection 2021-03-17 01:39:08 +01:00
b6f0176c10 Face Sets Topology: Add repeat last and default keymap 2021-03-17 01:20:50 +01:00
6835ea72f2 Sculpt Poly Loop: Move poly loop code to its own file 2021-03-17 00:07:41 +01:00
6408c4ebf6 Sculpt Poly Loop: refactor poly loop code for reusability 2021-03-16 23:46:46 +01:00
e557e4d03c Face Sets Topology: Initial working version 2021-03-16 23:17:08 +01:00
02d482e8f2 Face Sets Topology: Initial loop iteration implementation (one side only) 2021-03-16 22:48:31 +01:00
525badbd7d Face Sets Topology: Initial edge loop detection 2021-03-16 22:28:39 +01:00
49fa3dd5ff Face Sets Topology: Initial commit 2021-03-16 22:03:22 +01:00
8b0bc7e3e8 Cleanup: Clang format 2021-03-16 21:25:56 +01:00
ef4abf1212 Sculpt IPMask: Working exec callback for scripts 2021-03-16 21:24:08 +01:00
6ce37c59ec Sculpt IPMask: Refactor filter initialization 2021-03-16 21:05:10 +01:00
6824d73b75 Sculpt IPMask: Add direction property to the filter 2021-03-16 20:45:58 +01:00
06762eefcf Sculpt IPMask: Start implementing exec callback 2021-03-16 20:42:12 +01:00
f791fc031e Sculpt IPMask: Fix memory leak in step compute 2021-03-16 20:26:55 +01:00
57b7eba4b6 Merge branch 'master' into sculpt-dev 2021-03-16 20:00:37 +01:00
abda36c076 Sculpt: Apply latest clang-format changes to the branch 2021-03-14 21:15:47 +01:00
476b333a3e Merge branch 'master' into sculpt-dev 2021-03-14 21:14:58 +01:00
4ad1a7ab31 Cleanup: Clang format 2021-03-14 21:14:39 +01:00
5f5aa43ab1 Sculpt: Fair all by tangency mode for face set edit 2021-03-14 21:14:19 +01:00
4293db60b3 Merge branch 'master' into sculpt-dev 2021-03-12 21:57:37 +01:00
647c065b9c Merge branch 'master' into sculpt-dev 2021-03-12 16:51:18 +01:00
497e532e23 Merge branch 'master' into sculpt-dev 2021-03-12 01:46:40 +01:00
e1f338b9f4 Merge branch 'master' into sculpt-dev 2021-03-11 17:53:47 +01:00
15ef2d42f3 Merge branch 'master' into sculpt-dev 2021-03-10 18:55:12 +01:00
a9083cc0ee Sculpt: Move Mask Init to its own file 2021-03-09 22:11:23 +01:00
c8a03bc716 Sculpt IPMask: Increase sensitivity of contrast mask filter 2021-03-09 21:53:19 +01:00
3efb094fd3 Merge branch 'master' into sculpt-dev 2021-03-09 21:50:31 +01:00
251440f538 Merge branch 'master' into sculpt-dev 2021-03-09 18:44:15 +01:00
cb0f159155 Merge branch 'master' into temp_bmesh_multires
Merge not finished, but need to commit to move to different computer;
laptop being sent in for repairs
2021-03-08 13:57:21 -08:00
409a525fa9 Merge branch 'master' into sculpt-dev 2021-03-08 21:18:53 +01:00
966af5a075 Cleanup: Clang format 2021-03-08 17:37:57 +01:00
5234e23c2c Voxel Remesher: Option to preserver material slots 2021-03-08 17:37:47 +01:00
11613f8c7a Merge branch 'master' into sculpt-dev 2021-03-07 18:06:27 +01:00
8a98189bfb commit before merge 2021-03-07 04:00:14 -08:00
3678b87272 Merge branch 'master' into sculpt-dev 2021-03-06 18:51:48 +01:00
1f2b48eb45 Add a little todo list 2021-03-05 16:54:19 -08:00
dd1c4c84c9 Merge branch 'master' into sculpt-dev 2021-03-04 20:06:27 +01:00
de2625518b Merge branch 'master' into sculpt-dev 2021-03-04 17:32:05 +01:00
75709e4d57 Fix crash in Boundary brush expand mode after refactor 2021-03-03 22:13:19 +01:00
6a74211f99 Merge branch 'master' into sculpt-dev 2021-03-03 20:25:18 +01:00
d3742022c2 Sculpt: Make global smooth factor control the strengh directly 2021-03-03 18:52:16 +01:00
75794afdcd Cleaup: Clang format 2021-03-03 18:51:35 +01:00
b1b49f6130 Sculpt IPMask: Tweak default filter sensitivity 2021-03-03 17:29:46 +01:00
ca60d520d9 Sculp IPMask: Property to enable/disable step interpolation 2021-03-03 17:29:24 +01:00
2fd22fd663 Cleanup: Clang format 2021-03-03 17:12:38 +01:00
04c85de559 Sculpt IPMask: Implement restoring and cancelling the filter 2021-03-03 17:10:09 +01:00
407dd37573 Merge branch 'master' into sculpt-dev 2021-03-03 17:08:59 +01:00
0acaa40c08 Fix after merge 2021-03-03 16:43:41 +01:00
f2024f7d99 Merge branch 'master' into sculpt-dev 2021-03-02 17:05:00 +01:00
a7b5bbf13f Merge branch 'master' into sculpt-dev 2021-03-01 22:28:41 +01:00
e696280b88 Sculpt IPMask: Fix crash in original data updates 2021-03-01 22:14:22 +01:00
5e9eb1930f Sculpt IPMask: Implement filters that use original data 2021-03-01 22:03:22 +01:00
9a7cbff535 Sculpt IPMask: Some experiments for a better sharpen filter 2021-03-01 20:21:23 +01:00
8dec2ca7ba Sculpt IPMask: Tweak default sensitivity of each step 2021-03-01 19:24:58 +01:00
098d0d782a Sculp IPMask: First working version of substep interpolation 2021-03-01 19:19:41 +01:00
779a268c6e Sculpt IPMask: Initial refactor to support step interpolation 2021-03-01 18:52:27 +01:00
13b7b69e7f Merge branch 'master' into sculpt-dev 2021-03-01 18:01:17 +01:00
148b39caec Added some code to calculate principle curvature direction for
uniform triangle tesselations (dyntopo).  This will be used for
a version of topological rake that aligns edge flows to lines of curvature
automatically.
2021-03-01 01:09:27 -08:00
e9f9217f75 Merge from master 2021-02-28 17:05:35 -08:00
dd45a4bc6e Merge branch 'master' into temp_bmesh_multires 2021-02-28 04:59:03 -08:00
1ccd92d0bb commit prior to merge 2021-02-28 04:23:45 -08:00
9f78a24eca Merge branch 'master' into sculpt-dev 2021-02-27 18:32:35 +01:00
930a9edc1e Sculpt IPMask: First version of contrast filter 2021-02-26 22:03:48 +01:00
5cfe7bf72c Merge branch 'master' into sculpt-dev 2021-02-26 20:34:38 +01:00
422b1c64cd Merge branch 'master' into sculpt-dev 2021-02-26 19:05:58 +01:00
1edad56ffc Sculpt IPMask: update pie menu 2021-02-26 17:17:00 +01:00
ef3d68f17b Sculpt IPMask: Use the new mask filter in the pie menu 2021-02-26 14:46:02 +01:00
094ffcf669 Sculpt IPMask: Implement some other filterts (hard/soft) 2021-02-26 02:47:49 +01:00
56d33186a4 Sculpt IPMask: Move main data update to its own function 2021-02-26 01:41:23 +01:00
d570feeffc Cleanup: Clang format 2021-02-26 01:36:13 +01:00
158397a007 Sculpt IPMask: Ignore inbetween mouse events 2021-02-26 01:35:30 +01:00
4e8c430c6e Sculpt IPMask: Free ghash when finishing 2021-02-26 01:31:49 +01:00
d8a4ebb068 Sculpt IPMask: Multithreaded and fast mesh updates 2021-02-26 01:23:45 +01:00
6d46a3ca4e Sculpt IPMask: Enable iteration count 2021-02-26 01:12:14 +01:00
1751b3c7c1 Sculpt IPMask: Refactor, prepare for iteration counts 2021-02-26 01:08:21 +01:00
8ae0573c0f Sculpt IPMask: Unify function to apply delta steps 2021-02-26 00:50:25 +01:00
be0194ef3e Sculpt IPMask: Remove debug prints 2021-02-26 00:47:45 +01:00
0a2ca5860f Sculpt IPMask: Implement automasking for the filter 2021-02-26 00:46:52 +01:00
151cf0b9d9 Sculpt IPMask: Implement filter selection 2021-02-26 00:43:46 +01:00
12cb22d5f6 Sculpt IPMask: Multithreaded compute step 2021-02-26 00:25:06 +01:00
5c2bb6f93a Sculpt IPMask: Implement undo 2021-02-26 00:14:11 +01:00
2e99348da7 Sculpt IPMask: Generalize compute function 2021-02-26 00:08:25 +01:00
817ccc3a99 Sculpt IPMask: Implement smooth and sharpen callbacks 2021-02-26 00:03:44 +01:00
a429f73d2b Sculpt IPMask: Fix bugs in stack index, start refactor 2021-02-25 23:52:41 +01:00
5898cc25c9 Sculpt IPMask: First working version 2021-02-25 23:09:56 +01:00
c05c2c3fb7 Merge branch 'master' into sculpt-dev 2021-02-25 22:24:03 +01:00
f55c39a974 Sculpt IPMask: Functions to step back/forward in the stack 2021-02-25 18:24:09 +01:00
ebf94179b5 Sculpt IPMask: Dummy function to compute a step 2021-02-24 20:48:12 +01:00
9e5a219f3f Sculpt IPMask: delta steps struct and packing 2021-02-24 20:10:34 +01:00
76de0eeb95 Sculpt: Add mask filter tool and target step count 2021-02-24 20:00:02 +01:00
773c5c7464 Sculpt: Initial commit for Mask Filter tool with interactive preview
Hopefully this will become a mask filter that can grow/shrink and smooth/
sharpen any mask shape interactively by dragging the pen, like the rest
of the filters.
2021-02-24 16:50:24 +01:00
7abdfb5c2a Merge branch 'master' into sculpt-dev 2021-02-24 16:23:38 +01:00
ad743c056f Fix crash in versioning code 2021-02-23 23:27:51 +01:00
05bb102a30 Sculpt: Add global smooth strength factor for alt-smooth 2021-02-23 22:52:40 +01:00
b37fd7a14b Sculpt: Add extra options to Face Set pie menu 2021-02-23 22:36:43 +01:00
4154943eef Merge branch 'master' into sculpt-dev 2021-02-23 18:58:53 +01:00
5d7f7b7065 Sculpt: Initial support for bend deformations in Pose 2021-02-23 17:33:21 +01:00
09e394583e Sculpt Expand: Silence warning 2021-02-21 19:33:53 +01:00
7baa3c7df3 Sculpt Expand: Fix artifacts in sculpt geodesic distances 2021-02-21 19:33:32 +01:00
06a8b84792 Merge branch 'master' into sculpt-dev 2021-02-21 17:57:56 +01:00
343950f0c0 Merge branch 'master' into sculpt-dev 2021-02-21 17:28:13 +01:00
da0ef1daac Merge branch 'master' into sculpt-dev 2021-02-19 22:24:49 +01:00
2eb35c7cc0 Merge branch 'master' into sculpt-dev 2021-02-17 19:21:38 +01:00
13952ecec1 Merge branch 'master' into sculpt-dev 2021-02-17 18:02:01 +01:00
214e802f5f Sculpt Expand: More comment on ExpandCache 2021-02-17 17:50:18 +01:00
697e6e53b8 Sculpt Expand: Improve and fix Face Set snapping whit Face Sets 2021-02-17 17:44:00 +01:00
64c0f1fc3f Sculpt Expand: ExpandCache comments 2021-02-17 17:40:14 +01:00
ca5ccb52e5 Sculpt Expand: Expose normals expand in the keymap 2021-02-17 17:39:50 +01:00
51e90a0ada Sculpt Expand: Fix normals falloff 2021-02-17 16:50:41 +01:00
822bbb19f1 Merge branch 'master' into sculpt-dev 2021-02-17 16:35:48 +01:00
a35da15228 Merge branch 'master' into sculpt-dev 2021-02-17 16:35:31 +01:00
53874b413e Sculpt Expand: More comments 2021-02-17 00:17:49 +01:00
1b029b790b Sculpt Expand: Refactor, more comments 2021-02-16 21:03:34 +01:00
acd99f12e7 Sculpt Expand: Cleanup, comments 2021-02-16 20:38:06 +01:00
1a11ac5e34 Sculpt Expand: rename texture options to distortion 2021-02-15 19:41:23 +01:00
416afcb1c3 Sculpt: Move geodesic distances code to its own file 2021-02-15 19:11:49 +01:00
3539cbc497 Sculpt Expand: Fix face set snapping with Multires 2021-02-15 19:07:59 +01:00
4288b2a1d1 Sculpt Expand: Fix crash when editing an existing face set with Multires 2021-02-15 18:56:58 +01:00
d4548fe55b install_deps: Bump OpenEXR to 2.5.5 version. 2021-02-15 18:29:47 +01:00
7b360abb18 Cleanup: Remove code duplication (merge error) 2021-02-15 18:29:47 +01:00
b30294ba41 Cleanup: clang tidy 2021-02-15 18:29:47 +01:00
50f1bd6f09 Cleanup: Spelling in function name 2021-02-15 18:29:47 +01:00
Peter Fog
83d530688b FFmpeg: Improve multi-threading settings for VSE proxies
Following code from D8627 this patch corrects multi threaded processing
of proxies, where a 60 sec proxy generation drops to 35 sec.

Differential Revision: https://developer.blender.org/D8659
2021-02-15 18:29:47 +01:00
b790b57fe1 FFmpeg: Improve multi-threading settings
Allow use all system threads for frame encoding/decoding. This is very
straightforward: the value of zero basically disables threading.

Change threading policy to slice when decoding frames. The reason for
this is because decoding happens frame-by-frame, so inter-frame threading
policy will not bring any speedup.

The change for threading policy to slice is less obvious and is based on
benchmark of the demo files from T78986. This gives best performance so
far.

Rendering the following file went down from 190sec down to 160sec.

  https://storage.googleapis.com/institute-storage/vse_simplified_example.zip

This change makes both reading and writing faster. The animation render
is just easiest to get actual time metrics.

Differential Revision: https://developer.blender.org/D8627
2021-02-15 18:29:47 +01:00
14fe422b48 CMake/Deps: upgrade USD 20.05 → 21.02
USD version 21.02 includes two of the changes Blender used to patch in,
which have now been removed from `usd.diff`. Unfortunately 21.02
introduces another issue where LZ4 symbols are accidentally exported,
causing linker errors. Fortunately these symbols are only used for
resting, so I added a patch hunk that simply removes their `extern "C"`
declaration.

The LZ4 linker issue has been reported upstream at
https://github.com/PixarAnimationStudios/USD/issues/1447.

Reviewed By: sebbas, mont29

Differential Revision: https://developer.blender.org/D10367
2021-02-15 18:29:47 +01:00
0af8ddab2d CMake/Deps: OpenImageDenoise 1.2.3 → 1.3.0 2021-02-15 18:29:47 +01:00
Ray molenkamp
79ecc59f0b CMake/Deps: XR_OpenXR v1.0.14
Straight up version bump

Things of note:

They started using API calls only available in windows 8, however given
the Python 3.9 update will forcibly bump us to 8.1+ anyhow this is not
an issue.

Will require some minor tweaks to platform_win32.cmake after adding the
libs to svn which are not included in this diff so this diff can land
without having to have the libs in place yet.

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10349
2021-02-15 18:29:47 +01:00
Ray molenkamp
0ac4824d07 CMake/Deps: OpenVDB 8.0.1
Straight forward version bump, some of the variables to detect a static
OpenEXR changed and the folder structure seemingly changed a little
requiring updates to the diff

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10340
2021-02-15 18:29:47 +01:00
5f8d444a76 CMake/Deps: Alembic 1.7.16
Version bump + no longer using Boost.

Building Alembic with Boost gave compiler errors, and having one less
inter-dependency is good as well.

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10329
2021-02-15 18:29:47 +01:00
Ray molenkamp
42c5fdeff4 CMake/Deps: TBB 2020U2
Straight forward version bump.

2020U2 is significantly louder in the deprecated header usage warning
department, we should probably see if we need to act on this: P1949

Differential Revision: https://developer.blender.org/D10359
2021-02-15 18:29:47 +01:00
Ray molenkamp
54801f695c CMake/Deps: Boost 1.73
Just a simple version bump.

Maniphest Tasks: T85365

Differential Revision: https://developer.blender.org/D10314
2021-02-15 18:29:47 +01:00
39ac38c25f Attributes: return refined Attribute from attributes.new method
Previously `mesh.attributes.new(...)` would return a generic attribute that
one could not do much with. Now it returns refined attributes like `FloatAttribute`.
2021-02-15 18:29:47 +01:00
834d3e15ce Fix T71960: Malformed .bmp files lead to crash
Add a boundary check, avoiding access past actual data.

Ideally would need to report error to the user somehow,
but it doesn't seem to be easy to do.

This is a minimal safe patch. The proper complete fix is
being worked on by Jesse.

Differential Revision: https://developer.blender.org/D10357
2021-02-15 18:29:47 +01:00
b3c00f97be Cleanup: Use enum class for CryptomatteLayerState. 2021-02-15 18:29:47 +01:00
6324e9bae8 Cleanup: Grammar in comments 2021-02-15 18:29:47 +01:00
bbdfd0cabe Fix: incorrect versioning for Attribute Randomize node 2021-02-15 18:29:47 +01:00
6ef557fdf1 Cleanup: unused variable 2021-02-15 18:29:47 +01:00
30897a56e7 Fix T85633: Misspelling of "neighborhood" in description 2021-02-15 18:29:47 +01:00
eb18eb709d Merge branch 'master' into sculpt-dev 2021-02-14 21:20:30 +01:00
fc7c57f4a1 Sculpt Expand: Improve support for Multires and dyntopo 2021-02-14 20:02:24 +01:00
e3fdfcc981 Sculpt Expand: Fix propagation from grids to faces in Multires 2021-02-14 19:53:30 +01:00
e9b6848fe7 Sculpt Expand: Limited support for Multires 2021-02-14 19:50:59 +01:00
38e61c04ea Sculpt Expand: Fix texture strength when switching falloffs 2021-02-14 19:12:48 +01:00
5e56eb8ca2 Sculpt Expand: Make texture strength consistent across falloff modes 2021-02-14 19:09:07 +01:00
ccfc8aacf8 Sculpt: Add option to show the sculpt pivot as part of the cursor 2021-02-14 18:17:29 +01:00
edece9e741 Sculpt Expand: Update Keymap descriptions 2021-02-14 18:07:27 +01:00
6ee1db0d67 Sculpt Expand: Fix wrong expandcache ref when finishing expand 2021-02-14 18:06:43 +01:00
30434e3904 Sculpt Expand: Render the origin of expand as part of the cursor 2021-02-14 17:45:30 +01:00
e45986291d Merge branch 'master' into sculpt-dev 2021-02-14 17:42:08 +01:00
eb6e96006e Cleanup: clang format 2021-02-12 18:47:23 +01:00
9047bf89fa Sculpt Expand: Fix max falloff with texture distorsion 2021-02-12 18:42:14 +01:00
63ef98d056 Sculpt Expand: Support for texture distorsion for mask and colors 2021-02-12 18:34:18 +01:00
bf53622eef Merge branch 'master' into sculpt-dev 2021-02-12 17:57:50 +01:00
f419d4625a Sculpt Expand: Fix and improve behaviour of pivot reposition 2021-02-11 20:32:25 +01:00
ae19d5303a Sculpt Expand: Fix Face Set ID constantly updated when moving 2021-02-11 20:05:29 +01:00
35f883b886 Cleanup: clang format 2021-02-11 20:02:15 +01:00
7d52658d84 Sculpt Expand: Use symmetry and component filtering for pivot reposition 2021-02-11 20:01:58 +01:00
974b50d16b Scupt Expand: Remove unused Face Sets update code 2021-02-11 18:55:49 +01:00
55382bcdd9 Merge branch 'master' into sculpt-dev 2021-02-11 18:55:15 +01:00
51c931ebb5 Fix depth PBVH raycast with grids 2021-02-11 18:48:14 +01:00
0b9aaaf97f Sculpt Expand: Force all enabled when cursor not over the mesh 2021-02-11 18:47:48 +01:00
faccaee6c3 Fix cloth filter not working after merge 2021-02-11 17:54:54 +01:00
a56fb568ed Cleanup: Clang format 2021-02-10 21:09:41 +01:00
c365e0c6b6 Merge branch 'master' into sculpt-dev 2021-02-10 21:08:52 +01:00
0d6deb7e65 Merge branch 'master' into sculpt-dev 2021-02-10 18:04:45 +01:00
50eed6e54f Merge branch 'master' into sculpt-dev 2021-02-10 01:45:53 +01:00
147cddb398 Merge branch 'master' into sculpt-dev 2021-02-10 00:35:07 +01:00
88c4684466 Sculpt expand: Fix crash when missing connected components 2021-02-09 20:18:02 +01:00
77a30a2886 Sculpt: fix pose brush flood fill with symmetry 2021-02-09 00:30:14 +01:00
370e2b5d82 Sculpt Expand: Force expand to work only on active connected components 2021-02-08 20:27:09 +01:00
44dc741e89 Fix crash in versioning code 2021-02-08 19:02:23 +01:00
7a8cf94170 Sculpt Expand: Fix keymap entry for snapping 2021-02-08 19:01:55 +01:00
fd28c19d09 Scupt: Fix failed scene projection with ortographic views 2021-02-08 18:59:26 +01:00
2f5eabf859 Sculpt: Fix wrong vertex normals in Scene Project 2021-02-08 18:42:43 +01:00
1a17c578a8 Merge branch 'master' into temp_bmesh_multires 2021-02-07 23:17:09 -08:00
56e1ae1afa * Yet another attempt at writing a faster distance to tri function.
I think I will end up writing a less accurate version and be done
  with it.  This is a consistent hotspot in profiling.
* Fixed a few more undo bugs
2021-02-07 23:01:09 -08:00
eea78bd112 PBVH depth: Improve detection with normal orientation in trim 2021-02-07 19:33:35 +01:00
d927f54da6 Merge branch 'arcpatch-D9622' into sculpt-dev 2021-02-07 19:18:46 +01:00
Pablo Dobarro
ec8d1b4eae Sculpt: Location option for lasso trim and depth info
This adds a location option to the trim lasso tool to position the shape
in the middle of the volume of the object instead of in the surface
under the cursor.

{F9349724}

In order to make this work, the SCULPT_cursor_geometry_info_update can
now also get the depth of the geometry from the raycast. The depth is
calculated as the second further intersecting triangle in the raycast
over the entire mesh. This information will also be used to improve and
create new tools.

Differential Revision: https://developer.blender.org/D9622
2021-02-07 19:12:37 +01:00
4e4c1f40e0 Sculpt Expand: Use visibility state for enabled values 2021-02-07 18:54:13 +01:00
35ac8cf4dc Sculpt Expand: Fix gradient when using invert 2021-02-07 17:59:15 +01:00
2f2f14ffed Sculpt Expand: Enable gradient when enabling brush gradient 2021-02-07 17:53:38 +01:00
03778b787e Merge branch 'master' into sculpt-dev 2021-02-07 17:49:48 +01:00
f7e062ef3e Sculpt: fix pose and expand floodfill initial vertex 2021-02-07 17:45:28 +01:00
23cf808585 Sculpt: Boundary circle deformation mode 2021-02-07 17:42:51 +01:00
8e8845786f Cleanup: clang format 2021-02-05 21:59:21 +01:00
3ed1a99dd2 Fix elastic deform surface falloff crashing or breaking geometry 2021-02-05 20:44:45 +01:00
0a9bc6944c Rename random per component to random per loose part 2021-02-05 20:33:38 +01:00
ec4e2f32c8 Fix const warning 2021-02-05 20:31:56 +01:00
2ea03ff860 Remove unused variable 2021-02-05 20:31:18 +01:00
9a3f32f80f Fix crash in versioning code 2021-02-05 20:30:54 +01:00
bcf2f30878 Merge branch 'master' into sculpt-dev 2021-02-05 20:23:18 +01:00
23312a6994 Merge branch 'master' into sculpt-dev 2021-02-04 19:06:15 +01:00
cf5a96aa8d Merge branch 'master' into sculpt-dev 2021-02-04 16:46:45 +01:00
7ed64d9430 Merge branch 'master' into sculpt-dev 2021-02-03 21:08:28 +01:00
1cc0f8cf75 Sculpt Expand: Enable repeat events for loop count increase/decrease 2021-02-03 19:26:18 +01:00
b4e90b6e61 Sculpt Expand: fix topology recursion and flood fill 2021-02-03 18:49:03 +01:00
112c67f688 Merge branch 'master' into sculpt-dev 2021-02-03 17:03:50 +01:00
19fa6fd9f4 Cleanup: Clang format 2021-02-03 01:26:24 +01:00
88921150ff Sculpt: Init Face Sets by Face Sets boundary 2021-02-03 01:25:47 +01:00
e973c94036 Sculpt Expand: Add Expand to the keymap by default 2021-02-03 01:12:11 +01:00
b40f1f4c79 Sculpt Expand: Fix multiple crashes when using modifiers 2021-02-03 00:36:54 +01:00
c191344efb Sculpt Expand: Fix modal keymap descriptions 2021-02-03 00:10:28 +01:00
debf4fc7c9 Sculpt Expand: Refactor and pivot reposition 2021-02-02 23:48:06 +01:00
a60aca00bb Sculpt Expand: Implement topology diagonals falloff 2021-02-02 23:06:18 +01:00
763f96526e Sculpt Expand: implement restore, undo and cancel 2021-02-02 22:44:44 +01:00
abfd14817f Merge branch 'master' into sculpt-dev 2021-02-02 22:05:49 +01:00
529cffd804 Merge branch 'master' into sculpt-dev 2021-02-02 16:08:54 +01:00
09bb5e3aa0 Merge branch 'master' into sculpt-dev 2021-02-01 19:34:38 +01:00
5fb15545c1 Merge branch 'master' into sculpt-dev 2021-01-30 18:15:24 +01:00
a2df63e996 Merge branch 'master' into sculpt-dev 2021-01-29 22:44:44 +01:00
ccaba71fdf Merge branch 'master' into sculpt-dev 2021-01-28 01:16:42 +01:00
710c72807f Merge branch 'master' into sculpt-dev 2021-01-27 20:58:23 +01:00
e779eab729 Sculpt: Implement elastic surface falloff 2021-01-26 20:51:53 +01:00
a72cf784a7 Merge branch 'master' into sculpt-dev 2021-01-26 20:30:39 +01:00
78dffe2f16 Fix Face Set init not showing in the menus 2021-01-25 21:06:36 +01:00
9d31943d88 Merge branch 'master' into sculpt-dev 2021-01-25 20:05:56 +01:00
0a2b19e96d Merge branch 'master' into sculpt-dev 2021-01-24 20:23:54 +01:00
46582b3743 Merge branch 'master' into sculpt-dev 2021-01-24 03:04:27 +01:00
c10b19e453 Merge branch 'master' into sculpt-dev 2021-01-20 18:56:37 +01:00
5631bd4f94 Cleanup: Clang format 2021-01-20 18:51:49 +01:00
30b6d7826d Sculpt: Reset all brushes operator 2021-01-20 18:48:34 +01:00
d1b2c55322 Sculpt Expand: Brush Gradients 2021-01-20 18:17:19 +01:00
87ae49c78e Sculpt Expand: Expose geodesic and topology recursions 2021-01-19 00:14:10 +01:00
2765fb6c76 Sculpt Expand: Loops and recursion types 2021-01-18 23:28:49 +01:00
65cea9523e Merge branch 'master' into sculpt-dev 2021-01-18 22:26:46 +01:00
3d311fdaf1 Sculpt Expand: Expand from active 2021-01-16 21:21:16 +01:00
7a0d5e0c9e Sculpt Expand: Expand from face set boundary 2021-01-16 21:05:16 +01:00
e2fb2315fd Cleanup: Clang Format 2021-01-16 20:41:33 +01:00
fc1fc95b79 Sculpt Expand: Modify Active Face Set 2021-01-16 20:41:10 +01:00
05703d630e Sculpt Expand: face set selection snapping 2021-01-16 20:11:37 +01:00
65c358851d Sculpt Expand: Recursivity, move and falloff switching 2021-01-16 18:38:05 +01:00
b997fc5ea1 Sculpt Expand: Initial implementation of face falloff factors 2021-01-16 01:54:36 +01:00
869747e527 Sculpt Expand: Initial face sets expand target 2021-01-16 01:19:56 +01:00
df7857a364 Sculpt Expand: vertex colors target 2021-01-16 00:42:26 +01:00
cd0cf0a5b7 Expand: Support for invert, preserve and mask gradients 2021-01-15 23:37:42 +01:00
abf7518cbf Sculpt expand modal keymap 2021-01-15 22:24:12 +01:00
58406eddb5 Merge branch 'master' into sculpt-dev 2021-01-15 19:47:28 +01:00
97ab225428 Merge branch 'master' into sculpt-dev 2021-01-14 17:56:31 +01:00
24bbe05913 Add automatic falloff type switching to expand 2021-01-14 02:03:49 +01:00
81ac9f61b6 Implement boundary expand 2021-01-14 01:40:32 +01:00
a9f6ab7357 Basic mask expand operation working 2021-01-14 01:05:11 +01:00
df9a5825e1 Initial commit for new generic sculpt expand operator 2021-01-13 22:59:59 +01:00
0c8b9cd7d1 Cleanup: Clang format 2021-01-13 20:28:09 +01:00
142aba9485 Sculpt: Grab brush surface falloff 2021-01-13 20:27:51 +01:00
bf632990e0 Merge branch 'master' into sculpt-dev 2021-01-13 18:53:20 +01:00
3b4a9b2319 Merge branch 'master' into sculpt-dev 2021-01-12 19:43:30 +01:00
38dce1d29d Merge branch 'master' into sculpt-dev 2021-01-09 17:56:44 +01:00
deeb0b3aac Add experimental ripple effects option to the cloth solver 2021-01-06 20:26:38 +01:00
237b1f9d75 Merge branch 'master' into sculpt-dev 2021-01-06 17:34:16 +01:00
11cd86a8d2 Fix crash in fairing and memory optimization 2021-01-06 17:34:01 +01:00
27713d65d1 Merge branch 'master' into sculpt-dev 2021-01-05 23:49:10 +01:00
d37d96437e Fix crash with scene project and dyntopo 2021-01-05 23:32:29 +01:00
940fb3c044 Sculpt Scene Project: Add option to use vertex normals and brush normal 2021-01-05 22:47:22 +01:00
f91a2a0831 Sculpt: add option for use the center of mass to the sphere mesh filter 2021-01-05 21:59:15 +01:00
6d6ab057e4 Add missing random mask init menu 2021-01-05 21:27:59 +01:00
ea12ba5441 Merge branch 'master' into sculpt-dev 2021-01-05 21:03:21 +01:00
601d896fc6 Fix crash with custom input curves versioning 2021-01-05 18:12:32 +01:00
c237a48104 Fix warnings and windows build 2021-01-05 17:53:50 +01:00
29078186f8 Merge branch 'master' into sculpt-dev 2021-01-05 17:52:46 +01:00
7754c4f10f Fix windows build 2021-01-04 21:22:45 +01:00
90931d6de9 Sculpt: Update clay strips presets with custom input curves 2021-01-01 21:47:18 +01:00
4785f80d51 Fix multiple crashes with custom input curves 2021-01-01 20:12:46 +01:00
5136cc701f Merge branch 'master' into sculpt-dev 2021-01-01 17:18:40 +01:00
ef9eb626a8 Sculpt: Initial support for custom pressure input curves 2020-12-31 19:48:25 +01:00
0663576d19 Tweak draw sharp preset to include size-pressure 2020-12-31 18:36:39 +01:00
e1b8577e41 Merge branch 'master' into sculpt-dev 2020-12-31 18:30:27 +01:00
e09d9c86b6 Merge branch 'master' into sculpt-dev 2020-12-30 18:17:24 +01:00
52e99c5639 Merge branch 'master' into sculpt-dev 2020-12-29 16:13:12 +01:00
193806f590 Merge branch 'master' into sculpt-dev 2020-12-28 22:41:46 +01:00
a3e4f9d9a6 Merge branch 'master' into sculpt-dev 2020-12-28 14:21:15 +01:00
482f46a35a Change default cloth grab deform constraints strength 2020-12-27 00:41:45 +01:00
975a17c816 Sculpt: Auto detect the sphere radius in the sphere mesh filter 2020-12-27 00:14:57 +01:00
985c6464e2 Sculpt: Edit face set extrude operation 2020-12-26 20:11:19 +01:00
bca07d9039 Merge branch 'master' into sculpt-dev 2020-12-26 17:52:31 +01:00
35092510ba Merge branch 'master' into temp_bmesh_multires 2020-12-26 04:24:54 -08:00
85842851d5 Fix build 2020-12-25 21:54:14 +01:00
61ec4159c8 Implement radial gradient 2020-12-25 21:51:21 +01:00
c4ebefc1c8 Cleanup: Clang format 2020-12-25 21:36:58 +01:00
eb4f2f1548 Sculpt: Base code for gradient tools 2020-12-25 21:36:31 +01:00
47b4b45011 Optimize fairing weights calculation 2020-12-25 17:25:00 +01:00
7547e28ba4 Merge branch 'master' into sculpt-dev 2020-12-25 17:09:01 +01:00
0b2e4fa52e Cleanup: Clang format 2020-12-24 19:58:09 +01:00
f4900b3d02 Sculpt: Smooth Directional deform mode 2020-12-24 19:57:58 +01:00
1d53fbfd06 Merge branch 'master' into sculpt-dev 2020-12-24 19:30:30 +01:00
c203de25db Merge branch 'master' into sculpt-dev 2020-12-24 16:30:33 +01:00
ac8c589b7c Preparte curvature fairing and Fairing edit mode operator 2020-12-24 16:30:12 +01:00
f32d3f7b06 Merge branch 'master' into sculpt-dev 2020-12-23 19:23:03 +01:00
5385455e6a Fixed undo bugs caused by SculptVertRef refactor. I need to figure out
the right way to make assigning a pointer to a SculptVertRef to an int*
spit out a compiler error.
2020-12-22 22:47:50 -08:00
1bf726f1ad Merge branch 'master' into sculpt-dev 2020-12-22 23:59:48 +01:00
f031000b28 Sculpt: Mask Init operator and random init modes 2020-12-22 23:59:25 +01:00
2c54c641a3 Added a new cavity automasking mode for sculpt colors painting.
In theory it should also work with other sculpt tools (the
automasking code is fairly general) though it doesn't seem
to do much.
2020-12-22 14:11:11 -08:00
554be8d96c Merge branch 'master' into sculpt-dev 2020-12-22 16:30:14 +01:00
f969b3d440 Merge branch 'master' into sculpt-dev 2020-12-21 23:44:17 +01:00
6034a5bd5b Merge branch 'master' into sculpt-dev 2020-12-21 21:17:51 +01:00
eea756e513 Sculpt: Scene Project Brush 2020-12-21 21:16:16 +01:00
ecbf3e2d0f Sculpt: Face Set Edit fill component mode 2020-12-21 20:00:56 +01:00
6fa6a8851f Merge branch 'master' into sculpt-dev 2020-12-21 16:19:03 +01:00
b3fff9b07a Merge remote-tracking branch 'origin/master' into temp_bmesh_multires
Also redid vcol boundary tool icon, and made a little icon for sculpt
color paint.
2020-12-21 01:08:24 -08:00
671ef8f0e9 Merge branch 'master' into sculpt-dev 2020-12-20 16:10:56 +01:00
373b9b4481 Merge branch 'master' into sculpt-dev 2020-12-19 21:00:53 +01:00
0ada9c1638 Sculpt: Improve boundary artifacts in fairing mask with line gestures 2020-12-19 17:46:23 +01:00
31158ef0c9 Merge branch 'master' into sculpt-dev 2020-12-19 17:00:44 +01:00
5fbd436bb1 Merge branch 'master' into sculpt-dev 2020-12-18 20:10:58 +01:00
c0cb475689 Merge branch 'master' into sculpt-dev 2020-12-17 22:28:12 +01:00
b8a0455983 Fix crash in combine proxies 2020-12-17 19:24:45 +01:00
6145a6bc6c Merge branch 'master' into sculpt-dev 2020-12-17 17:48:12 +01:00
5c03d0c30c Fix plane falloff with elastic cloth 2020-12-16 21:09:45 +01:00
6b42781319 Merge branch 'master' into sculpt-dev 2020-12-16 21:02:04 +01:00
6c4a9b83ff Fix elastic drag cloth brush deformation 2020-12-16 20:59:20 +01:00
9453b45e20 Sculpt: Change default damping for cloth deform target 2020-12-16 20:52:52 +01:00
c0f19d6082 Sculpt: Cloth Brush elastic drag deform type 2020-12-16 20:49:02 +01:00
06078a6f92 Merge branch 'master' into sculpt-dev 2020-12-16 20:27:13 +01:00
1199b9e678 Merge branch 'master' into sculpt-dev 2020-12-16 19:10:48 +01:00
92bc9477d1 Merge branch 'master' into sculpt-dev 2020-12-16 16:43:09 +01:00
7bc1657d05 Fix cloth sim artifacts on planes 2020-12-15 22:13:11 +01:00
e582a4dc77 Fix debug build 2020-12-15 22:07:47 +01:00
243e329ec3 Sculpt: Cloth Deform target for transform 2020-12-15 22:07:08 +01:00
5775efba2f Sculpt: Elastic Transform 2020-12-15 21:38:07 +01:00
cab8626cf2 Sculpt: lasso and box project gestures 2020-12-15 21:33:49 +01:00
19cb01aa21 Cleanup: Clang format 2020-12-15 21:15:05 +01:00
6e6828e09d Sculpt: Project gesture fairing deformation mode 2020-12-15 21:14:26 +01:00
72ff64590d Sculpt: Fairing Brush 2020-12-15 20:39:53 +01:00
553724529e Change PBVH leaf limit size 2020-12-15 20:35:29 +01:00
681e2b6134 Fixes from merge 2020-12-08 13:37:00 -08:00
49bd2228cb Merge branch 'master' into temp_bmesh_multires 2020-12-07 13:04:19 -08:00
0a140ec66e Commit before merge 2020-12-07 11:48:32 -08:00
f30225725d Some multires stuff 2020-11-18 18:34:08 -08:00
a1ac104f02 add NULL pointer check 2020-11-11 05:19:35 -08:00
d823f6e2cf Added an "Exponent" slider to Color Boundary brush. 2020-11-09 22:25:03 -08:00
3042f6e608 Tweaked value for smoothing in vcol boundary tool (a slight amount of
smoothing is applied to prevent normal discontiuties from perfectly
colinear triangles).

Also reverted some CLANG compiling stuff.
2020-11-09 18:30:24 -08:00
6115091103 View3D: take clipping into account for Frame All
Clamp the min/max used for Frame All/Selected
by the clipping region if it's set.

Resolve T81050
2020-11-07 02:54:23 -08:00
78ef2d0d84 Cleanup: move plane array intersection into a function
Also add check to ensure a point isn't occluded by it's own plane,
which could happen if a small epsilon values are passed in.
2020-11-07 02:54:23 -08:00
9d92a97562 Cleanup: Rename render texture files to texture_* 2020-11-07 02:54:23 -08:00
192670e8ce Cleanup: Remove unused variable 2020-11-07 02:54:23 -08:00
7ae1cc23fc Cleanup: remove unused includes in readfile.c and writefile.c 2020-11-07 02:54:23 -08:00
ebb6648bda Fix missing include warning
Caused by rB580ff2cb937daf43699908afe1190baea8d117aa
2020-11-07 02:54:23 -08:00
384f2956e5 Cleanup: fix naming and remove unnecessary code 2020-11-07 02:54:23 -08:00
2ba90cf717 Refactor: move Screen .blend data read to blenkernel
Ref T76372.
2020-11-07 02:54:23 -08:00
e5af8597e5 Refactor: move Ipo .blend I/O to IDTypeInfo callbacks 2020-11-07 02:54:23 -08:00
1f6a7785f6 Refactor: move Object .blend I/O to IDTypeInfo callbacks 2020-11-07 02:54:23 -08:00
0ee053fb12 Cleanup: Clang-Tidy modernize-use-nullptr
Replace `NULL` with `nullptr` in C++ code.

No functional changes.
2020-11-07 02:54:20 -08:00
8cd4776764 Clang-Tidy: error out when executable not found
Stop with an error when the Clang-Tidy executable cannot be found.

Without this check, CMake will happily report "Found Clang-Tidy" but with
the fallback version (0, 0, 0), when `CLANG_TIDY_EXECUTABLE` points to a
non-existing executable.
2020-11-07 02:53:25 -08:00
f32bde6bd9 Refactor: move Pose .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:25 -08:00
Yevgeny Makarov
8b808cefae UI: Improved macOS Application Icon Progress Bar
Nicer appearance for the progress bar that is drawn over the application icon during long processes on macOS.

Differential Revision: https://developer.blender.org/D9398

Reviewed by Brecht Van Lommel
2020-11-07 02:53:24 -08:00
f8466b6284 Refactor: move Constraint .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
4a2d7a2f89 Refactor: move MotionPath .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
67defe866b Fix T81997: Subsurf Optimal Display sticks after object conversion
When using Optimal Display, some edges are not flagged `ME_EDGEDRAW` |
`ME_EDGERENDER`.
When the modifier is applied through the UI in the modifier stack this is
not an issue because the `modifyMesh` callback is run with
`MOD_APPLY_TO_BASE_MESH` (this will effectively turn of Optimal
Display).
When converting to mesh though, this will just get an evaluated mesh
(where the edge flags are still the same as with the subdivision
modifier).
Now ensure every edge is flagged to draw after conversion.

Maniphest Tasks: T81997

Differential Revision: https://developer.blender.org/D9331
2020-11-07 02:53:24 -08:00
b6575fed92 Refactor: move gpencil modifier .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
d6735bfae0 Refactor: move modifier .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
e4c45d0c5e Fix T82251: Outliner Material Drag&Drop missing tree update
Caused by rBb077de086e14.

Not entirely sure why this was rebuilding the tree prior to above
commit, but sending an ND_OB_SHADING notifier is appropriate (and also
what the Outliners listener listens to).

Maniphest Tasks: T82251

Differential Revision: https://developer.blender.org/D9396
2020-11-07 02:53:24 -08:00
c4668b750c Fix T82220 Missing viewport update after manual "HDRI Preview Size" input
This is caused by the TAA being reset after the init phase, leading to
1 sample being kept as valid when it is clearly not.

To fix this, we run the lookdev validation before TAA init.

Reviewed By: Jeroen Bakker

Differential Revision: https://developer.blender.org/D9452
2020-11-07 02:53:24 -08:00
81a85233a7 Cleanup: Clang-Tidy, modernize-make-unique 2020-11-07 02:53:24 -08:00
89f62e5dc3 Cleanup: Sort includes after recent render module cleanup 2020-11-07 02:53:23 -08:00
408e13783d Cleanup: remove unused functions 2020-11-07 02:53:23 -08:00
3900734063 Refactor: move ShaderFx .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:23 -08:00
fa688ac593 Cleanup: Render Module: combine intern/ source & include 2020-11-07 02:53:23 -08:00
787f952ef4 Cleanup: whitespace 2020-11-07 02:53:23 -08:00
63241d25b9 Cleanup: Render Module: move header files to main directory
Move headers files from `render/extern/` to `render/`

Part of T73586
2020-11-07 02:53:23 -08:00
Paul Melis
98166b5c98 Add background rectangle option to video sequencer Text strip
This adds a Box option to the Text strip's style properties, plus related Box Margin value:

{F9208309}

When enabled the text is placed on top of a solid-filled rectangle of a chosen color, as shown below:

{F9208324}

When the box option is disabled the text strip works the same as it does now. When the box option is enabled the meaning of the Shadow option changes to provide a drop-shadow on the rectangle (and not on the text itself). The latter made more sense to me.

The box margin is specified as a fraction of the image width. The offset of the drop-down box shadow is fixed to a specific fraction of the image width as well.

I tested this feature on a movie of a couple of minutes containing dozens of text strips (all with box background), edge cases like multi-line strings and text overlapping the image edges.

Reviewed By: ISS

Differential Revision: https://developer.blender.org/D9468
2020-11-07 02:53:23 -08:00
229849af0f Refactor: move ParticleSystem .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:23 -08:00
0a1fc855bc Sequencer: Make naming consistent in header and implementation files 2020-11-07 02:53:23 -08:00
46ccaff9a3 VSE: Don't store proxy images in cache
Proxies are expected to be fast to read. Storing them in cache has
little to no effect on performance.

This change also allows to omit invalidation of cache when user switch
between proxies and original media.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9473
2020-11-07 02:53:23 -08:00
9c8b0a20c1 Refactor: move Scene .blend expand to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
a42cf75ecb Refactor: move Scene .blend lib reading to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
d77e884bd7 Cleanup: rename time related variables
Variables renaned:
 - cfra -> timeline_frame
 - nr -> frame index
 - cfra_over -> overlap_frame

Function seq_give_stripelem_index was renamed to seq_give_frame_index.
2020-11-07 02:53:22 -08:00
e2111233f0 Blenloader: access report list via api 2020-11-07 02:53:22 -08:00
e4efd04063 Blenloader: expose BLO_reportf_wrap in api
This function is used by a couple of functions that are moved out of blenloader.
2020-11-07 02:53:22 -08:00
8edd20274e Refactor: move Scene .blend data reading to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
9be60839cd Refactor: move Scene .blend writing to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
af934d751d CMake: Fix wrong library used for dependency
Was causing compilation failure on fresh builds.
2020-11-07 02:53:22 -08:00
5ac07c31f0 Refactor: move PointCache .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:22 -08:00
f3a7d9375d Cleanup: Fluid engine API return types
Use bool return type where possible instead of int (the return values from fluid object are already boolean instead of int).

Also removed several if guards in API functions. If one of the arguments is in fact invalid / nullptr (should not happen though), it better to catch them directly where they failed and not silently escape them.
2020-11-07 02:53:22 -08:00
a033a0eaaf Cleanup: Clang-Tidy, modernize-use-bool-literals 2020-11-07 02:53:22 -08:00
c137b53569 Refactor: move sequencer modifier .blend I/O to sequencer module
Ref T76372.
2020-11-07 02:53:21 -08:00
f0a9986ccf Cleanup: Alembic, simplify expression
Change `1 + current_mat++` to `++current_mat`.

No functional changes.
2020-11-07 02:53:21 -08:00
f639ffe795 Cleanup: Alembic, simplify material assignment code
Refactor material assignment code such that:
- `build_mat_map()` just returns the built map (instead of relying on
  modifying a map passed as parameter),
- `LISTBASE_FOREACH` is used to loop over a `ListBase` (instead of a
  hand-crafted for-loop),
- just `return` when not enough material slots can be created (instead
  of setting a boolean to false, then doing some useless work, then
  checking the boolean),
- reorder some code for clarity, and
- rename `mat_map` to `matname_to_material` so that the semantics are
  clearer.

No functional changes.
2020-11-07 02:53:21 -08:00
326381bfe1 Refactor: move Paint lib linking to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
174e3c6b65 Refactor: move color settings .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
5c899dcc92 Cleanup: Clang-Tidy, modernize-use-emplace 2020-11-07 02:53:21 -08:00
24ee80f077 Fix compilation error of bf_draw
Similar to previous commit, missing build dependency.
2020-11-07 02:53:21 -08:00
22b69af796 Fix compilation error when building from scratch
Make sure the DNA offset files is ready at a time bf_windowmanager
need it.
2020-11-07 02:53:21 -08:00
0758c006ec Cleanup: Clang-Tidy, modernize-redundant-void-arg 2020-11-07 02:53:21 -08:00
c2a329ec07 Refactor: move LightCache .blend I/O to eevee_lightcache.c
Ref T76372.
2020-11-07 02:53:21 -08:00
bdaee543f3 Refactor: move remaining ViewLayer .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
44d358c384 Cleanup: remove unnecessary function 2020-11-07 02:53:21 -08:00
f87123a6eb Refactor: move Paint .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
f2fc2cd521 Refactor: move wmWindowManager .blend I/O to IDTypeInfo callbacks 2020-11-07 02:53:20 -08:00
af92a39e37 Fix T82364: Widget anim state not updated when deleting channel in Graph Editor
So a keyframed e.g. location slider would stay yellow/green even if its
corresponding channel was removed.

Needs a appropriate notifier so the listeners (e.g.
buttons_area_listener, view3d_buttons_region_listener) would cause a
redraw.

Maniphest Tasks: T82364

Differential Revision: https://developer.blender.org/D9438
2020-11-07 02:53:20 -08:00
49cbb23855 Fix T82457: Python error when clicking on a tool in the viewport
Ths variable was initialized for false, while it was expected to be
true.
2020-11-07 02:53:20 -08:00
9cb84de509 Clang Tidy: Expand modernize category
Gives an idea of which warnings are affecting Blender code base.
2020-11-07 02:53:20 -08:00
53f6991de8 Cleanup: Use nullptr everywhere in fluid code
Switched from NULL to nullptr.
2020-11-07 02:53:20 -08:00
5b696c2bd8 Fix T82407: Negative number input gives syntax error for velocities and
accelerations

Caused by rB45dbc38a8b15.

Above commit would place parentheses surrounding a block until the next
operator was found.
For velocities and accelerations though, the '/' in 'm/s' or 'ft/s'
should not be considered an operator.

Maniphest Tasks: T82407

Differential Revision: https://developer.blender.org/D9467
2020-11-07 02:53:20 -08:00
b95a5c2e68 Fix T82387: Crash loading file saved with recent master in old versions
This fix makes sure new files save `wmWindow.global_areas` under a different
name, so old Blender versions don't recognize and 0-initialize it.

Since enabling global area writing (ef4aa42ea4), loading a file in old
Blender versions would cause `wmWindow.global_areas` to be read, because there
was already reading code for it and `ScrAreaMap` was in SDNA.
However the `ScrArea.global` of the global areas would be NULL, because it was
*not* in SDNA (`ScrGlobalAreaData` was excluded).
Now, issue is that the code assumes that areas in the global area-map have a
valid ScrArea.global pointer.

Think this was a mistake in rB5f6c45498c92. We should have cleared all this data
on reading, until the global area writing was enabled.

Differential Revision: https://developer.blender.org/D9442

Reviewed by: Brecht Van Lommel
2020-11-07 02:53:20 -08:00
080e78d205 Cleanup: Clang-Tidy, readability-redundant-member-init 2020-11-07 02:53:20 -08:00
a55a69f81a Fix Outliner editbone selection with 'Sync Selection'
When editbones were selected from the Outliner (and they were connected
to a parent) with the 'Sync Selection' option turned ON, they could not
get duplicated.

For duplication to work, the (connected) parent bone's tip also has to
be selected [which was not the case when selection is done from the
Outliner under above circumstances]. The reason being that
armature_duplicate_selected_exec ->
ED_armature_edit_sync_selection clears the BONE_ROOTSEL flag if the
parent bone's BONE_TIPSEL is not set.

Caused by rB71eb65328078 btw.

The correct "parent-tip-selection" would actually happen in activation
- `tree_element_active_ebone`
-- `tree_element_active_ebone__sel`
but for 'Sync Selection' this happens [also] in
- `outliner_sync_selection_from_outliner`
-- `outliner_select_sync_to_edit_bone`
which did not do the "flushing" to the parent bone's tip

Now use existing dedicated function for this.

ref. T82347

Reviewers: Zachman

Differential Revision: https://developer.blender.org/D9470
2020-11-07 02:53:20 -08:00
596fea8afd Cleanup: Clang-Tidy warnings 2020-11-07 02:53:19 -08:00
47e4adde5a Fix compilation error in GHOST
ELEM macro isn't available in GHOST library.
2020-11-07 02:53:19 -08:00
a349943cd7 Cleanup: Fix the order of info_cfg_option. 2020-11-07 02:53:19 -08:00
360faf5c3c Cleanup: add missing doxygen group 2020-11-07 02:53:19 -08:00
9cf97857d1 Cleanup: Fix wrong doxygen groups
Was missed in rB9b6088cb9da4df1a893361997fc1a22986bf6f2e
2020-11-07 02:53:19 -08:00
44bdf515ba CMake: configue_file() to pass strings for build-info
Using configue_file(..) would have avoided the breakage from
1daa3c3f0a, caused by buildinfo not properly escaping quotes.

Rely on CMake to escaping strings instead using configure_file().
2020-11-07 02:53:19 -08:00
45ccdebad3 Fix uninitialized value
Own mistake in rB74188e65028d268af887ab2140e4253087410c1e
2020-11-07 02:53:19 -08:00
d242d33571 Cleanup: use 'BKE_' prefix for initialization functions 2020-11-07 02:53:19 -08:00
731eaa68d3 Cleanup: use doxy sections for node_group.c 2020-11-07 02:53:19 -08:00
344963bf23 Cleanup: use if/else check for property poll 2020-11-07 02:53:19 -08:00
aaca5731fb Cleanup: replace STREQLEN with STRPREFIX for constant strings 2020-11-07 02:53:19 -08:00
aa7147f665 Cleanup: use STR_ELEM macro 2020-11-07 02:53:19 -08:00
0fb50afdc5 Cleanup: Use LISTBASE_FOREACH macro 2020-11-07 02:53:18 -08:00
f3cc74d216 Cleanup: Use descriptive variable names 2020-11-07 02:53:18 -08:00
0946a8da3b Cleanup: de-duplicate code for instancing objects when linking
Ref D8843
2020-11-07 02:53:18 -08:00
a8e5e63f45 Cleanup: doxygen comments 2020-11-07 02:53:18 -08:00
e52f8ac7ce Cleanup: doxygen comments in ghost
Use colon after parameters, use hash to reference symbols.
2020-11-07 02:53:18 -08:00
71a088582a Cleanup: use ELEM macro (>2 args) 2020-11-07 02:53:18 -08:00
3aab8dd731 Cleanup: clang-format
Missed this last commit.
2020-11-07 02:53:18 -08:00
56d57b2e9d Cleanup: use ELEM macro 2020-11-07 02:53:18 -08:00
b16eb9d7ad Cleanup: follow our code style for float literals 2020-11-07 02:53:17 -08:00
3fcd3d41c4 Cleanup: use bool argument in BLI_noise 2020-11-07 02:53:17 -08:00
0b0bfa0628 Cleanup: BLI_noise
Use common prefix as this collided with existing API's (eg BLI_voronoi).

Also expand some non-obvious abbreviations:

- 'g'  -> 'generic'
- 'vl' -> 'variable_lacunarity'
- 'V'  -> 'v3'
2020-11-07 02:53:17 -08:00
ff9ce5fd98 Cleanup: remove unused BLI_turbulence1
A slightly modified version of BLI_turbulence1, unused for years.
2020-11-07 02:53:17 -08:00
2d99e118b4 Cleanup: use snake case for BLI_args API 2020-11-07 02:53:17 -08:00
a93add61b0 Cleanup: remove unused BLI_argsArgv 2020-11-07 02:53:17 -08:00
7f28a99dd5 Cleanup: use string APPEND/PREPEND
Replace 'set' with 'string(APPEND/PREPEND ...)'.
This avoids duplicating the variable name.
2020-11-07 02:53:10 -08:00
9aaf9857a0 Cleanup: transform.h comments, use doxy sections 2020-11-07 02:52:23 -08:00
e2595de761 Cleanup: sort structs, files 2020-11-07 02:52:23 -08:00
40c4942901 Cleanup: clang-format 2020-11-07 02:52:23 -08:00
2e188dc504 Cleanup: unused variable 2020-11-07 02:52:23 -08:00
Yevgeny Makarov
dfce29b809 UI: Tweaks to the Warning Icon
Warning Sign Alert Icon given a more rounded border.

Differential Revision: https://developer.blender.org/D9443

Reviewed by Pablo Vazquez
2020-11-07 02:52:23 -08:00
decf7adcf6 Fix T81915: Draw Face Sets not working with deformed sculpt mesh
The draw face sets brush uses the poly center when used in meshes to increase
its precision when working in low poly geometry. For this to work with deformed
meshes, the deformed coordinates from the PBVH should be used instead.

Reviewed By: sergey

Maniphest Tasks: T81915

Differential Revision: https://developer.blender.org/D9424
2020-11-07 02:52:23 -08:00
81531d5e76 Fix memory leaks in sculpt mode trimming tools
BKE_mesh_free() seems to not free the meshes correctly, so using BKE_id_free() instead.
The looptri array was also not freed.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9426
2020-11-07 02:52:23 -08:00
15bc0b7d5d Fix T82400: Dyntopo detail size edit operator visual glitch
Just a missing immUnbindProgram

Reviewed By: sergey

Maniphest Tasks: T82400

Differential Revision: https://developer.blender.org/D9459
2020-11-07 02:52:23 -08:00
17dec471c5 Fix Dyntopo detail size preview orientation not matching the cursor
Used the sampled cursor normal when available instead of the raycast face normal.
This makes the preview match the previous orientation of the cursor.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9460
2020-11-07 02:52:23 -08:00
81f05aca29 Move "Camera Parent Lock" from preferences to Object Relations
"Camera Parent Lock" can be useful when rigging cameras, but it is not
intuitive, and has also generated a lot of confusion (bug reports).
This is because it breaks the fundamental parent <-> child relationship
conventions in Blender, and there is no indication that it's intended
without diving into the preferences.

This commit moves the setting to the object level, and exposes it in
the relations panel in the property editor. It is exposed for every
object type because any object type can be "View Locked" in the 3D view.
The property description is also updated to reflect this change and be
more specific without getting too long.

In the future this could become a more general feature of the transform
system, but for now it is limited to "Lock Camera to View".

Differential Revision: https://developer.blender.org/D9239
2020-11-07 02:52:22 -08:00
d1270925a5 Fix T82423: Add modifier key back into keymap
Commit rBf5080c82dd915db6c7b9dd68a52aaaccf2600137
accidentally remove the Shift modifier key from
the `AUTOCONSTRAINPLANE` shortcut.

Differential Revision: https://developer.blender.org/D9480
2020-11-07 02:52:22 -08:00
9e09ae7aff Fix T82164: Knife tool draws huge vertices after using bgl.glPointSize
Since it is possible to have multiple draw callbacks, (some of which
use bgl and others gpu), check and force the reset of the drawing status
at the end of each callback.

Differential Revision: https://developer.blender.org/D9476
2020-11-07 02:52:22 -08:00
Robert Guetzkow
c51a5e1066 Fix T82423: Replace duplicate name in keymap
The two entries `TFM_MODAL_AUTOCONSTRAINT` and
`TFM_MODAL_AUTOCONSTRAINTPLANE` had the same name
displayed in the UI. The latter is now includes
"plane" in it's name.

Reviewed By: mano-wii

Differential Revision: https://developer.blender.org/D9474
2020-11-07 02:52:22 -08:00
758452ffba Fix T80043: missing Cycles displacement update when relinking output sockets 2020-11-07 02:52:22 -08:00
c7cd82c356 Cleanup: Reduce variable scope
Differential Revision: https://developer.blender.org/D9475
2020-11-07 02:52:22 -08:00
cc554eea75 Fix T82428: Cycles crashes when building volume meshes
The Volume Node did not have all of the sockets from its Mesh base class
which are now required due to the recent socket API change.
2020-11-07 02:52:21 -08:00
0d770432d6 pre-merge commit 2020-11-07 02:48:34 -08:00
b2cb9d4b1b Fixed handling of edge seam flags in dyntopo, for some reason did the
code was not brought over from trimesh branch.
2020-11-06 16:23:12 -08:00
08e19c6bc0 Added debug option in dyntopo to draw sculpt colors as solid cells
instead of interpolating (it's next to "draw smooth" in the dyntopo
settings panel).
2020-11-06 03:17:45 -08:00
b928f58849 Made vcol boundary tool avoid perfectly degenerate triangles. 2020-11-06 01:35:52 -08:00
228c1e5345 Replace call to BMLog with origco CD layer.
Also fixed SCULPT_HIDE_FACE_SETS.  It was 1<<16, which overlaps
SCULPT_DYNTOPO_DETAIL_MANUAL.  Changed it to 1<<17.  Someone should do
this in master too.
2020-11-05 16:35:42 -08:00
488af21ae0 Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-05 09:05:02 -08:00
b54d7bfad8 Fix redraw error for dyntopo smooth brush 2020-11-05 09:03:56 -08:00
2babf80ae6 Fixed sculpt colors undo for mesh pbvh. 2020-11-04 21:27:21 -08:00
022dcb8e6c Added autosmooth-like option to run vcol boundary tool in paint tool 2020-11-04 20:36:43 -08:00
6d66e81667 Fixed color boundary tool for faces pbvh 2020-11-04 03:05:38 -08:00
91a5e1aef8 Added an icon for new sculpt colors boundary smooth tool 2020-11-04 02:34:18 -08:00
6d704d57ad Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-03 22:41:57 -08:00
a1b1c840a0 Adjust weighting for color boundary tool 2020-11-03 19:41:18 -08:00
901654dcbf * Added a "color boundary" tool that tries to smooth out vcol boundaries 2020-11-03 19:08:37 -08:00
37a657a45f Added face set support to dyntopo. Still need to finish "edit face
sets" tool and do more testing.
2020-11-03 16:05:38 -08:00
e07bb3955e Enabled dyntopo for sharp brush. Also fixed paint brush strength being
too strong with dyntopo enabled.
2020-11-03 00:47:19 -08:00
7834b59598 Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-02 14:33:52 -08:00
0c8d40d2de Fixed bug with multires editmode code messing up loop indices for draw
code.

Also fixed a bug in dyntopo ray tracing, where r_active_vertex_index
wasn't always being set.
2020-11-02 14:29:45 -08:00
1014b6f455 More fixes for sculpt vertex color undo. Moved one of the undo pushes
outside a thread, since dyntopo undo is not thread safe.
2020-10-31 11:06:15 -07:00
093e29f3c2 Tried to fix sculpt vcol paint undo. It's better, but I still need to
go through and thorougly analyze just what the undo stack is doing.
2020-10-30 20:06:05 -07:00
0f0d1f8e2a Paint brush no long SCULPT_undo_push_node per dab (except for first
stroke) for dyntopo.  Instead it updates the original vertex color
customdata layer.

Calling into the undo system destroys threading with dyntopo, as its
undo code is single-threaded.
2020-10-30 19:37:22 -07:00
43ccbe353f Try to make SCULPT_orig_vert_data_init avoid allocating undo nodes,
which calls into BMLog which, while now threadsafe (ish?) causes
threads to get bogged down in lock contention.
2020-10-30 19:17:03 -07:00
2d861122e1 Remove debugging clang keyword. It's not #ifdef'd code, but still. 2020-10-29 22:39:06 -07:00
66f8852e30 * Edge queue creation for dyntopo edge split/collapse is now
multithreaded.
* Worked on ProxyVert system, but it still needs more work.  Issue is keeping
  topological layers (reasonably) up to date without it being slow.
* Fixed memory leak in bmlog.
2020-10-29 22:33:57 -07:00
54ddb01299 Fixed a variety of memory corruption bugs 2020-10-29 04:28:03 -07:00
3d47323162 Fixed bug with original coordinates/normals not being set when
dyntopo pbvh is first built
2020-10-27 01:38:59 -07:00
5c77439264 * Fix bug in BKE_pbvh_node_color_buffer_get. 2020-10-27 00:20:07 -07:00
e2c92c1341 More fixes for dyntopo undo and vertices (face data still isn't
implemented).
2020-10-26 18:46:12 -07:00
faf8402c19 Added initial support for customdata to dyntopo undo (BMLog).
TODO:
 - Handle face (loop) data
 - Figure out what to do about edge data (warn user? actually handle
   it?)
 - Handle sculpt color undo push nodes properly (shouldn't be hard).
2020-10-26 02:45:56 -07:00
4c0bcc3d13 PBVH drawing now properly names attributes.
NOTE: I've added a new function, DRW_make_cdlayer_attr_aliases, for
this.  It's patterned after extract_uvs.  The appropriate devs from the
draw engine team should take a look.
2020-10-26 00:19:14 -07:00
4fc4a7e1f4 Fixed SCULPT_dynamic_topology_sync_layers from last commit. 2020-10-25 22:55:46 -07:00
f9859a3b2a Got sculpt colors to work, needs more testing 2020-10-25 22:35:02 -07:00
6da9fa1bf2 pre-valgrind commit 2020-10-25 20:00:42 -07:00
5c6407c268 Fixed broken customdata interpolation in dyntopo collapse.
Also added support for uvs to dyntopo gpu buffer building code.
2020-10-25 04:31:06 -07:00
3214b1114f Added support for customdata interpolation to dyntopo.
It seems fast enough for simple cases, I make no promises that it
will be fast in crazy cases lots if there's lots of vgroup layers.

Note I still need to interface properly with the sculpt colors code.
2020-10-25 01:37:52 -07:00
bfbe9a0d55 Fix bugs in last commit. 2020-10-25 01:07:05 -07:00
f482afadab Refactored sculpt code to use a new type, SculptVertRef, that replaces
much of the usage of integer indices.  Meshes and grids simply store the
index here, but bmesh stores a pointer to a BMVert.  This greatly speeds
up DynTopo by reducing the need to maintain flat pointer arrays in bmesh.

To prevent the accidental casting of ScuptVertexRef to indices and vice
versa SculptVertRef is defined as a struct:

typedef struct {intptr_t i} SculptVertRef;

There are also two functions to convert flat index indices to
SculptVertRefs and back:

ScultpVertRef BKE_pbvh_table_index_to_vertex(PBVH *pbvh, int index);
int BKE_pbvh_vertex_index_to_table(PBVH *pbvh, SculptVertRef *ref);

Note that these functions require the aforementioned maintanance of
flat pointer arrays in bmesh, so make sure to call
SCULPT_ensure_vertex_random_access().
2020-10-25 00:32:59 -07:00
661dcd813c Merge performance improvements from trimesh branch into this one. 2020-10-24 19:41:54 -07:00
5541de9a3a Submodule update 2020-10-24 16:03:05 -07:00
3791afa29c Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-10-24 16:01:45 -07:00
3ae8229843 commit before merge 2020-10-24 16:01:08 -07:00
f61d4b2e3a * Improved multires projection some more in bmesh_interp.c 2020-10-18 18:10:16 -07:00
49f57d8de8 COde cleanup 2020-10-18 16:12:02 -07:00
64c7bad391 New branch to fix multires topology editing. WIP
Changes:
* Brought back bmesh_mdisps_space_set, written from scratch using
  subdiv api, not ccg.
* Wrote a function to smooth multigres grids from within bmesh.  I might
  not need it; unless anyone thinks of a use for it I'll go ahead and
  delete it.

Todo:
* Purge code of all usages of CCG for multires.

This commit:
* Wrote a utility function to dump multires displacements into a (new)
  scene object.
* Consequently, I now know that the CCG_based multires code is not
  compatible with the OpenSubdiv based code.  The former produces gaps
  between grids when converting displacements to object space.
2020-10-17 15:11:02 -07:00
4659855b0f commit multires patch 2020-10-17 01:24:34 -07:00
285 changed files with 50898 additions and 5094 deletions

View File

@@ -263,6 +263,7 @@ ForEachMacros:
- SET_SLOT_PROBING_BEGIN
- MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN
- TGSET_ITER
StatementMacros:
- PyObject_HEAD

View File

@@ -578,6 +578,12 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
find_library(
COMPILER_ASAN_LIBRARY_THUNK NAMES clang_rt.asan_dll_thunk-x86_64
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
elseif(APPLE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER}
-print-file-name=lib
@@ -598,6 +604,7 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
)
endif()
mark_as_advanced(COMPILER_ASAN_LIBRARY_THUNK)
mark_as_advanced(COMPILER_ASAN_LIBRARY)
endif()
endif()
@@ -918,9 +925,9 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
unset(_list_COMPILER_ASAN_CFLAGS)
unset(_is_CONFIG_DEBUG)
elseif(COMPILER_ASAN_LIBRARY)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\"")
set(PLATFORM_LINKFLAGS "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
endif()
endif()
endif()

View File

@@ -389,7 +389,7 @@
// Does the compiler support result_of?
#ifndef EIGEN_HAS_STD_RESULT_OF
#if EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L)))
#if __cplusplus < 201703L && EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L && __cplusplus)))
#define EIGEN_HAS_STD_RESULT_OF 1
#else
#define EIGEN_HAS_STD_RESULT_OF 0

View File

@@ -221,7 +221,7 @@ AUD_API void AUD_Device_setListenerVelocity(AUD_Device* device, const float valu
AUD_API double AUD_Device_getRate(AUD_Device* device)
{
auto dev = device ? *device : DeviceManager::getDevice();
return dev->getSpecs().rate;
return dev ? dev->getSpecs().rate : 0.0;
}
AUD_API float AUD_Device_getSpeedOfSound(AUD_Device* device)

View File

@@ -87,11 +87,17 @@ public:
* \param args The arguments of the task.
* \return A future of the same type as the return type of the task.
*/
#if __cplusplus > 201703L
template<class T, class... Args>
std::future<typename std::invoke_result<T, Args...>::type> enqueue(T&& t, Args&&... args)
{
using pkgdTask = std::packaged_task<typename std::invoke_result<T, Args...>::type()>;
#else
template<class T, class... Args>
std::future<typename std::result_of<T(Args...)>::type> enqueue(T&& t, Args&&... args)
{
using pkgdTask = std::packaged_task<typename std::result_of<T(Args...)>::type()>;
#endif
std::shared_ptr<pkgdTask> task = std::make_shared<pkgdTask>(std::bind(std::forward<T>(t), std::forward<Args>(args)...));
auto result = task->get_future();

View File

@@ -67,7 +67,7 @@ SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
IF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_GLPK)
FIND_PACKAGE(GLPK 4.33)
ENDIF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_ILOG)

View File

@@ -4,7 +4,7 @@ FIND_PATH(ILOG_ROOT_DIR
PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
"CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
NO_DEFAULT_PATH

View File

@@ -16,3 +16,4 @@ LINK_DIRECTORIES(
# ADD_EXECUTABLE(myprog myprog-main.cc)
# TARGET_LINK_LIBRARIES(myprog lemon)

View File

@@ -88,3 +88,4 @@ INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
DESTINATION lib/pkgconfig
)

View File

@@ -10,6 +10,7 @@
#include <fstream>
#include <unordered_map>
#include <functional>
namespace qflow {
@@ -69,7 +70,7 @@ void load(const char* filename, MatrixXd& V, MatrixXi& F)
};
/// Hash function for obj_vertex
struct obj_vertexHash {
struct obj_vertexHash : std::function<size_t(obj_vertex)> {
std::size_t operator()(const obj_vertex &v) const {
size_t hash = std::hash<uint32_t>()(v.p);
hash = hash * 37 + std::hash<uint32_t>()(v.uv);

BIN
icon_geom.blend Normal file

Binary file not shown.

View File

@@ -49,27 +49,27 @@
/* Unsigned */
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x;
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_sub_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - x;
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
{
return InterlockedCompareExchange64((int64_t *)v, _new, old);
return (uint64_t)(InterlockedCompareExchange64((int64_t *)v, _new, old));
}
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
}
/* Signed */
@@ -103,32 +103,32 @@ ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, x) + x;
return (uint32_t)InterlockedExchangeAdd(p, x) + x;
}
ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, -((int32_t)x)) - x;
return (uint32_t)InterlockedExchangeAdd(p, -((int32_t)x)) - x;
}
ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
{
return InterlockedCompareExchange((long *)v, _new, old);
return (uint32_t)InterlockedCompareExchange((long *)v, _new, old);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, x);
return (uint32_t)InterlockedExchangeAdd(p, x);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x)
{
return InterlockedOr((long *)p, x);
return (uint32_t)InterlockedOr((long *)p, x);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
{
return InterlockedAnd((long *)p, x);
return (uint32_t)InterlockedAnd((long *)p, x);
}
/* Signed */
@@ -205,9 +205,9 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
{
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
return InterlockedAnd8((char *)p, (char)b);
return (int8_t)InterlockedAnd8((char *)p, (char)b);
#else
return _InterlockedAnd8((char *)p, (char)b);
return (int8_t)_InterlockedAnd8((char *)p, (char)b);
#endif
}
@@ -215,9 +215,9 @@ ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
{
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
return InterlockedOr8((char *)p, (char)b);
return (int8_t)InterlockedOr8((char *)p, (char)b);
#else
return _InterlockedOr8((char *)p, (char)b);
return (int8_t)_InterlockedOr8((char *)p, (char)b);
#endif
}

View File

@@ -21,6 +21,7 @@
set(INC
.
../atomic
../../source/blender/blenlib
)
set(INC_SYS

View File

@@ -409,7 +409,7 @@ static void print_memhead_backtrace(MemHead *memh)
(void)memh; /* Ignored. */
}
# endif /* defined(__linux__) || defined(__APPLE__) */
#endif /* DEBUG_BACKTRACE */
#endif /* DEBUG_BACKTRACE */
static void make_memhead_header(MemHead *memh, size_t len, const char *str)
{

View File

@@ -30,6 +30,7 @@
/* to ensure strict conversions */
#include "../../source/blender/blenlib/BLI_strict_flags.h"
#include "../../source/blender/blenlib/BLI_asan.h"
#include "atomic_ops.h"
#include "mallocn_intern.h"
@@ -59,6 +60,9 @@ enum {
#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned *)ptr) - 1)
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t)MEMHEAD_ALIGN_FLAG)
#define MEM_POISON_MEMHEAD(vmemh) BLI_asan_poison(MEMHEAD_FROM_PTR(vmemh), sizeof(MemHead))
#define MEM_UNPOISON_MEMHEAD(vmemh) BLI_asan_unpoison(MEMHEAD_FROM_PTR(vmemh), sizeof(MemHead))
/* Uncomment this to have proper peak counter. */
#define USE_ATOMIC_MAX
@@ -93,7 +97,13 @@ print_error(const char *str, ...)
size_t MEM_lockfree_allocN_len(const void *vmemh)
{
if (vmemh) {
return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
size_t ret;
MEM_UNPOISON_MEMHEAD(vmemh);
ret = MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
MEM_POISON_MEMHEAD(vmemh);
return ret;
}
return 0;
@@ -119,6 +129,8 @@ void MEM_lockfree_freeN(void *vmemh)
atomic_sub_and_fetch_u(&totblock, 1);
atomic_sub_and_fetch_z(&mem_in_use, len);
MEM_UNPOISON_MEMHEAD(vmemh);
if (UNLIKELY(malloc_debug_memset && len)) {
memset(memh + 1, 255, len);
}
@@ -137,6 +149,9 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
if (vmemh) {
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
MEM_UNPOISON_MEMHEAD(vmemh);
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(
@@ -145,6 +160,8 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
else {
newp = MEM_lockfree_mallocN(prev_size, "dupli_malloc");
}
MEM_POISON_MEMHEAD(vmemh);
memcpy(newp, vmemh, prev_size);
}
return newp;
@@ -158,6 +175,8 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t old_len = MEM_lockfree_allocN_len(vmemh);
MEM_UNPOISON_MEMHEAD(vmemh);
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
newp = MEM_lockfree_mallocN(len, "realloc");
}
@@ -166,6 +185,8 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "realloc");
}
MEM_POISON_MEMHEAD(vmemh);
if (newp) {
if (len < old_len) {
/* shrink */
@@ -194,6 +215,8 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t old_len = MEM_lockfree_allocN_len(vmemh);
MEM_UNPOISON_MEMHEAD(vmemh);
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
newp = MEM_lockfree_mallocN(len, "recalloc");
}
@@ -201,6 +224,7 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "recalloc");
}
MEM_POISON_MEMHEAD(vmemh);
if (newp) {
if (len < old_len) {
@@ -241,6 +265,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str)
atomic_add_and_fetch_z(&mem_in_use, len);
update_maximum(&peak_mem, mem_in_use);
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
return PTR_FROM_MEMHEAD(memh);
}
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
@@ -286,6 +311,8 @@ void *MEM_lockfree_mallocN(size_t len, const char *str)
atomic_add_and_fetch_z(&mem_in_use, len);
update_maximum(&peak_mem, mem_in_use);
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
return PTR_FROM_MEMHEAD(memh);
}
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
@@ -357,6 +384,8 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
atomic_add_and_fetch_z(&mem_in_use, len);
update_maximum(&peak_mem, mem_in_use);
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
return PTR_FROM_MEMHEAD(memh);
}
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",

View File

@@ -70,9 +70,9 @@ static int check_if_canceled(float progress,
return cancel;
}
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
ATTR_NO_OPT void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
Parametrizer field;
VertexMap vertexMap;
@@ -80,6 +80,12 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
/* Get remeshing parameters. */
int faces = qrd->target_faces;
field.flag_adaptive_scale = 1;
field.flag_minimum_cost_flow = 1;
field.flag_preserve_boundary = 1;
field.flag_preserve_sharp = 1;
// field.flag_aggresive_sat = 1;
if (qrd->preserve_sharp) {
field.flag_preserve_sharp = 1;
}
@@ -106,6 +112,7 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
/* Copy mesh to quadriflow data structures. */
std::vector<Vector3d> positions;
std::vector<uint32_t> indices;
std::vector<uint32_t> eflags;
std::vector<ObjVertex> vertices;
for (int i = 0; i < qrd->totverts; i++) {
@@ -114,16 +121,18 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
}
for (int q = 0; q < qrd->totfaces; q++) {
Vector3i f(qrd->faces[q * 3], qrd->faces[q * 3 + 1], qrd->faces[q * 3 + 2]);
Vector3i f(qrd->faces[q].v[0], qrd->faces[q].v[1], qrd->faces[q].v[2]);
ObjVertex tri[6];
int nVertices = 3;
const int nVertices = 3;
tri[0] = ObjVertex(f[0]);
tri[1] = ObjVertex(f[1]);
tri[2] = ObjVertex(f[2]);
for (int i = 0; i < nVertices; ++i) {
eflags.push_back(qrd->faces[q].eflag[i]);
const ObjVertex &v = tri[i];
VertexMap::const_iterator it = vertexMap.find(v);
if (it == vertexMap.end()) {
@@ -138,7 +147,10 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
}
field.F.resize(3, indices.size() / 3);
// field.FF.resize(3, indices.size() / 3);
memcpy(field.F.data(), indices.data(), sizeof(uint32_t) * indices.size());
// memcpy(field.FF.data(), eflags.data(), sizeof(uint32_t) * eflags.size());
field.V.resize(3, vertices.size());
for (uint32_t i = 0; i < vertices.size(); ++i) {
@@ -157,12 +169,17 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
return;
}
const int steps = 2;
/* Setup mesh boundary constraints if needed */
if (field.flag_preserve_boundary) {
#if 0
if (true) { // field.flag_preserve_boundary) {
Hierarchy &mRes = field.hierarchy;
mRes.clearConstraints();
for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
if (mRes.mE2E[i] == -1) {
if (mRes.mFF((i) % 3, i / 3) & QFLOW_CONSTRAINED) {
// if (mRes.mE2E[i] == -1) {
uint32_t i0 = mRes.mF(i % 3, i / 3);
uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
@@ -172,15 +189,20 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
mRes.mCO[0].col(i0) = p0;
mRes.mCO[0].col(i1) = p1;
mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 1.0;
mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 0.1;
}
}
}
mRes.propagateConstraints();
for (int j = 0; j < 10; j++) {
mRes.propagateConstraints();
}
}
#endif
/* Optimize the mesh field orientations (tangental field etc) */
Optimizer::optimize_orientations(field.hierarchy);
for (int i = 0; i < steps; i++) {
Optimizer::optimize_orientations(field.hierarchy);
}
field.ComputeOrientationSingularities();
if (check_if_canceled(0.3f, update_cb, update_cb_data)) {
@@ -195,11 +217,13 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
return;
}
Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
field.flag_adaptive_scale = 1;
Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
for (int i = 0; i < steps; i++) {
Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
}
for (int i = 0; i < steps; i++) {
Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
}
field.ComputePositionSingularities();
if (check_if_canceled(0.5f, update_cb, update_cb_data)) {

View File

@@ -23,9 +23,16 @@
extern "C" {
#endif
enum { QFLOW_CONSTRAINED = 1 };
typedef struct QuadriflowFace {
int v[3];
char eflag[3];
} QuadriflowFace;
typedef struct QuadriflowRemeshData {
float *verts;
int *faces;
QuadriflowFace *faces;
int totfaces;
int totverts;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -4299,6 +4299,28 @@ def km_curve(params):
# Radial control setup helpers, this operator has a lot of properties.
def radial_control_properties_channels(paint, prop, secondary_prop, secondary_rotation=False, color=False, zoom=False, type="float"):
brush_path = 'tool_settings.' + paint + '.brush'
channels_path = brush_path + ".channels.channels"
unified = "tool_settings." + paint + ".channels.channels"
rotation = 'mask_texture_slot_angle' if secondary_rotation else 'texture_slot_angle'
return {
"properties": [
("data_path_primary", '%s["%s"].%s_value' % (channels_path, prop, type)),
("data_path_secondary", '%s["%s"].%s_value' % (unified, prop, type) if secondary_prop else ''),
("use_secondary", '%s["%s"].inherit' % (channels_path, prop) if secondary_prop else ''),
#("rotation_path", '%s["%s"].float_value' % (channels_path, rotation)),
#("color_path", brush_path + '.cursor_color_add'),
#("fill_color_path", brush_path + '.color' if color else ''),
#("fill_color_override_path", unified_path + '.color' if color else ''),
#("fill_color_override_test_path", unified_path + '.use_unified_color' if color else ''),
#("zoom_path", 'space_data.zoom' if zoom else ''),
#("image_id", brush_path + ''),
#("secondary_tex", secondary_rotation),
],
}
def radial_control_properties(paint, prop, secondary_prop, secondary_rotation=False, color=False, zoom=False):
brush_path = 'tool_settings.' + paint + '.brush'
@@ -4348,6 +4370,32 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal
return items
def _template_paint_radial_control_channels(paint, rotation=False, secondary_rotation=False, color=False, zoom=False):
items = []
items.extend([
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
radial_control_properties_channels(paint, 'radius', 'use_unified_size', type="float", secondary_rotation=secondary_rotation, color=color, zoom=zoom)),
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
radial_control_properties_channels(paint, 'strength', 'use_unified_strength', type="factor", secondary_rotation=secondary_rotation, color=color)),
])
"""
if rotation:
items.extend([
("wm.radial_control", {"type": 'F', "value": 'PRESS', "ctrl": True},
radial_control_properties_channels(paint, 'texture_slot_angle', None, color=color)),
])
if secondary_rotation:
items.extend([
("wm.radial_control", {"type": 'F', "value": 'PRESS', "ctrl": True, "alt": True},
radial_control_properties_channels(paint, 'mask_texture_slot_angle', None, secondary_rotation=secondary_rotation, color=color)),
])
"""
return items
def km_image_paint(params):
items = []
keymap = (
@@ -4515,6 +4563,9 @@ def km_sculpt(params):
{"properties": [("mode", 'INVERT')]}),
("sculpt.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("mode", 'SMOOTH')]}),
# Face Set by Topology
("sculpt.face_set_by_topology", {"type": 'W', "value": 'PRESS', "ctrl": True},
{"properties": [("mode", "POLY_LOOP"), ("repeat_previous", True)]}),
# Expand
("sculpt.expand", {"type": 'A', "value": 'PRESS', "shift": True},
{"properties": [("target", "MASK"), ("falloff_type", "GEODESIC"), ("invert", True)]}),
@@ -4524,6 +4575,8 @@ def km_sculpt(params):
{"properties": [("target", "FACE_SETS"), ("falloff_type", "GEODESIC"), ("invert", False), ("use_modify_active", False)]}),
("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True, "alt": True},
{"properties": [("target", "FACE_SETS"), ("falloff_type", "BOUNDARY_FACE_SET"),("invert", False), ("use_modify_active", True)]}),
("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("target", "FACE_SETS"), ("falloff_type", "POLY_LOOP"), ("invert", False), ("use_modify_active", False)]}),
# Partial Visibility Show/hide
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS'},
{"properties": [("mode", 'TOGGLE')]}),
@@ -4531,10 +4584,6 @@ def km_sculpt(params):
{"properties": [("mode", 'HIDE_ACTIVE')]}),
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS', "alt": True},
{"properties": [("mode", 'SHOW_ALL')]}),
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True},
{"properties": [("mode", 'GROW')]}),
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("mode", 'SHRINK')]}),
# Subdivision levels
*_template_items_object_subdivision_set(),
("object.subdivision_set", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True},
@@ -4566,7 +4615,8 @@ def km_sculpt(params):
{"properties": [("scalar", 0.9)]}),
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
{"properties": [("scalar", 1.0 / 0.9)]}),
*_template_paint_radial_control("sculpt", rotation=True),
*_template_paint_radial_control_channels("sculpt", rotation=True),
#*_template_paint_radial_control("sculpt", rotation=True),
# Stencil
("brush.stencil_control", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
{"properties": [("mode", 'TRANSLATION')]}),
@@ -5640,7 +5690,8 @@ def km_sculpt_expand_modal(_params):
("FALLOFF_TOPOLOGY", {"type": 'TWO', "value": 'PRESS', "any": True}, None),
("FALLOFF_TOPOLOGY_DIAGONALS", {"type": 'THREE', "value": 'PRESS', "any": True}, None),
("FALLOFF_SPHERICAL", {"type": 'FOUR', "value": 'PRESS', "any": True}, None),
("SNAP_TOGGLE", {"type": 'LEFT_CTRL', "value": 'ANY'}, None),
("SNAP_ENABLE", {"type": 'LEFT_CTRL', "value": 'PRESS'}, None),
("SNAP_DISABLE", {"type": 'LEFT_CTRL', "value": 'RELEASE'}, None),
("LOOP_COUNT_INCREASE", {"type": 'W', "value": 'PRESS', "any": True, "repeat": True}, None),
("LOOP_COUNT_DECREASE", {"type": 'Q', "value": 'PRESS', "any": True, "repeat": True}, None),
("BRUSH_GRADIENT_TOGGLE", {"type": 'B', "value": 'PRESS', "any": True}, None),
@@ -6628,6 +6679,26 @@ def km_3d_view_tool_sculpt_line_project(params):
]},
)
def km_3d_view_tool_sculpt_lasso_project(params):
return (
"3D View Tool: Sculpt, Lasso Project",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
("sculpt.project_lasso_gesture", {"type": params.tool_tweak, "value": 'ANY'},
None),
]},
)
def km_3d_view_tool_sculpt_box_project(params):
return (
"3D View Tool: Sculpt, Box Project",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
("sculpt.project_box_gesture", {"type": params.tool_tweak, "value": 'ANY'},
None),
]},
)
def km_3d_view_tool_sculpt_mesh_filter(params):
return (
@@ -6639,6 +6710,16 @@ def km_3d_view_tool_sculpt_mesh_filter(params):
]},
)
def km_3d_view_tool_sculpt_ipmask_filter(params):
return (
"3D View Tool: Sculpt, IPMask Filter",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
("sculpt.ipmask_filter", {"type": params.tool_tweak, "value": 'ANY'},
None)
]},
)
def km_3d_view_tool_sculpt_cloth_filter(params):
return (
@@ -7256,7 +7337,10 @@ def generate_keymaps(params=None):
km_3d_view_tool_sculpt_lasso_trim(params),
km_3d_view_tool_sculpt_line_mask(params),
km_3d_view_tool_sculpt_line_project(params),
km_3d_view_tool_sculpt_lasso_project(params),
km_3d_view_tool_sculpt_box_project(params),
km_3d_view_tool_sculpt_mesh_filter(params),
km_3d_view_tool_sculpt_ipmask_filter(params),
km_3d_view_tool_sculpt_cloth_filter(params),
km_3d_view_tool_sculpt_color_filter(params),
km_3d_view_tool_sculpt_mask_by_color(params),

View File

@@ -522,6 +522,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")

View File

@@ -19,6 +19,16 @@
# <pep8 compliant>
from bpy.types import Menu
channel_name_map = {
"size" : "radius",
"autosmooth_fset_slide":"fset_slide",
"auto_smooth_factor": "autosmooth",
"auto_smooth_projection": "autosmooth_projection",
"auto_smooth_radius_factor": "autosmooth_radius_scale",
"boundary_smooth_factor": "boundary_smooth",
"autosmooth_fset_slide": "fset_slide",
"topology_rake_factor": "topology_rake"
};
class UnifiedPaintPanel:
# subclass must set
@@ -97,6 +107,136 @@ class UnifiedPaintPanel:
return tool_settings.gpencil_vertex_paint
return None
@staticmethod
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
slider=False, header=False, expand=None, toolsettings_only=False):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle, if they exist. """
ch = brush.channels.channels[prop_name]
finalch = ch
l1 = layout
#if ch.ui_expanded:
# layout = layout.box().column() #.column() is a bit more compact
if ch.type == "BITMASK":
layout = layout.box()
row = layout.row(align=True)
typeprop = "float_value"
if ch.type == "INT":
typeprop = "int_value"
elif ch.type == "BOOL":
typeprop = "bool_value"
elif ch.type == "ENUM":
typeprop = "enum_value"
elif ch.type == "BITMASK":
typeprop = "flags_value"
elif ch.type == "VEC3":
typeprop = "color3_value"
elif ch.type == "VEC4":
typeprop = "color4_value"
if text is None:
s = prop_name.lower().replace("_", " ").split(" ");
text = ''
for k in s:
text += k[0].upper() + k[1:] + " "
text = text.strip()
path = ""
is_toolset = False
if ch.inherit or toolsettings_only:
sd = context.tool_settings.sculpt
#ensure channel exists in tool settings channel set
sd.channels.ensure(ch)
finalch = sd.channels.channels[prop_name]
is_toolset = True
path = "tool_settings.sculpt.channels.channels[\"%s\"]" % ch.idname
else:
path = "tool_settings.sculpt.brush.channels.channels[\"%s\"]" % ch.idname
if ch.type == "BITMASK":
row.label(text=text)
if header:
row.prop_menu_enum(finalch, typeprop)
else:
col = layout.column()
col.emboss = "NONE"
for item in finalch.enum_items:
if item.identifier in finalch.flags_value:
itemicon = "CHECKBOX_HLT"
else:
itemicon = "CHECKBOX_DEHLT"
col.prop_enum(finalch, typeprop, item.identifier, icon=itemicon)
elif expand is not None:
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider, expand=expand)
else:
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider)
pressure = pressure and ch.type not in ["BOOL", "ENUM", "BITMASK"]
if pressure:
row.prop(finalch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
#if pressure_name:
# row.prop(brush, pressure_name, text="")
#if unified_name and not header:
# # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
# row.prop(ups, unified_name, text="", icon='BRUSHES_ALL')
if not header and ch.type != "BOOL":
if ch.type == "BITMASK" and not toolsettings_only and ch == finalch:
row.prop(ch, "inherit_if_unset", text="Combine With Defaults")
if not toolsettings_only:
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
if ch.type == "BITMASK":
return
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
if ch.ui_expanded:
for mp in finalch.mappings:
row2 = layout.row()
name = mp.type.lower()
if len(name) > 0:
name = name[0].upper() + name[1:]
else:
name = "name error"
row2.label(text=name)
row2.prop(mp, "enabled", text="", icon="STYLUS_PRESSURE")
row2.prop(mp, "ui_expanded", text="", icon="TRIA_DOWN" if mp.ui_expanded else "TRIA_RIGHT")
if mp.ui_expanded:
layout.template_curve_mapping(mp, "curve", brush=True)
col = layout.column(align=True)
row = col.row(align=True)
path2 = path + ".mappings[\"%s\"].curve" % (mp.type)
shapes = ['SMOOTH', 'ROUND', 'ROOT', 'SHARP', 'LINE', 'MAX']
icons = ['SMOOTHCURVE', 'SPHERECURVE', 'ROOTCURVE', 'SHARPCURVE', 'LINCURVE', 'NOCURVE']
for i, shape in enumerate(shapes):
props = row.operator("brush.curve_preset_load", icon=icons[i], text="")
props.shape = shape
props.path = path2
#row2.prop(mp, "curve")
return row
@staticmethod
def prop_unified(
layout,
@@ -112,6 +252,14 @@ class UnifiedPaintPanel:
):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle, if they exist. """
if prop_name in channel_name_map:
prop_name = channel_name_map[prop_name]
if prop_name in brush.channels.channels:
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False):
return UnifiedPaintPanel.channel_unified(layout, context, brush, prop_name, icon=icon, text=text, slider=slider, header=header)
row = layout.row(align=True)
ups = context.tool_settings.unified_paint_settings
prop_owner = brush
@@ -131,6 +279,12 @@ class UnifiedPaintPanel:
@staticmethod
def prop_unified_color(parent, context, brush, prop_name, *, text=None):
if context.mode == 'SCULPT':
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
# slider=False, header=False, expand=None, toolsettings_only=False):
return UnifiedPaintPanel.channel_unified(parent, context, brush, prop_name, text=text)
ups = context.tool_settings.unified_paint_settings
prop_owner = ups if ups.use_unified_color else brush
parent.prop(prop_owner, prop_name, text=text)
@@ -549,15 +703,27 @@ def brush_settings(layout, context, brush, popover=False):
if context.preferences.experimental.use_sculpt_tools_tilt and capabilities.has_tilt:
layout.prop(brush, "tilt_strength_factor", slider=True)
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
"hard_edge_mode",
slider=True,
unified_name="use_unified_hard_edge_mode",
)
row = layout.row(align=True)
row.prop(brush, "hardness", slider=True)
row.prop(brush, "invert_hardness_pressure", text="")
row.prop(brush, "use_hardness_pressure", text="")
# auto_smooth_factor and use_inverse_smooth_pressure
if capabilities.has_auto_smooth:
box = layout.box().column() #.column() is a bit more compact
UnifiedPaintPanel.prop_unified(
layout,
box,
context,
brush,
"auto_smooth_factor",
@@ -565,13 +731,83 @@ def brush_settings(layout, context, brush, popover=False):
slider=True,
)
# topology_rake_factor
#box.prop(brush, "boundary_smooth_factor")
#box.prop(brush, "use_weighted_smooth")
#box.prop(brush, "preserve_faceset_boundary")
UnifiedPaintPanel.prop_unified(box, context, brush, "boundary_smooth_factor", slider=True)
UnifiedPaintPanel.prop_unified(box, context, brush, "use_weighted_smooth")
UnifiedPaintPanel.prop_unified(box, context, brush, "preserve_faceset_boundary")
if 1: #brush.preserve_faceset_boundary:
UnifiedPaintPanel.prop_unified(box, context, brush, "autosmooth_fset_slide", slider=True)
#box.prop(brush, "autosmooth_fset_slide")
box.prop(brush, "use_custom_auto_smooth_spacing", text="Custom Spacing")
if brush.use_custom_auto_smooth_spacing:
UnifiedPaintPanel.prop_unified(
box,
context,
brush,
"auto_smooth_spacing",
slider=True,
text="Spacing"
)
UnifiedPaintPanel.prop_unified(
box,
context,
brush,
"auto_smooth_projection",
slider=True
)
UnifiedPaintPanel.prop_unified(
box,
context,
brush,
"auto_smooth_radius_factor",
slider=True
)
elif brush.sculpt_tool == "SMOOTH":
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
"auto_smooth_projection",
slider=True
)
if capabilities.has_vcol_boundary_smooth:
layout.prop(brush, "vcol_boundary_factor", slider=True)
if (
capabilities.has_topology_rake and
context.sculpt_object.use_dynamic_topology_sculpting
):
layout.prop(brush, "topology_rake_factor", slider=True)
box = layout.box().column() #.column() is a bit more compact
#box.prop(brush, "topology_rake_factor", slider=True)
UnifiedPaintPanel.prop_unified(
box,
context,
brush,
"topology_rake_factor",
slider=True,
text="Topology Rake"
)
box.prop(brush, "use_custom_topology_rake_spacing", text="Custom Spacing")
if brush.use_custom_topology_rake_spacing:
box.prop(brush, "topology_rake_spacing", text="Spacing")
box.prop(brush, "topology_rake_projection")
box.prop(brush, "topology_rake_radius_factor", slider=True)
box.prop(brush, "use_curvature_rake")
box.prop(brush, "ignore_falloff_for_topology_rake")
if context.sculpt_object.use_dynamic_topology_sculpting:
layout.prop(brush.dyntopo, "disabled", text="Disable Dyntopo")
# normal_weight
if capabilities.has_normal_weight:
layout.prop(brush, "normal_weight", slider=True)
@@ -620,16 +856,27 @@ def brush_settings(layout, context, brush, popover=False):
if capabilities.has_color:
ups = context.scene.tool_settings.unified_paint_settings
row = layout.row(align=True)
if context.mode == "SCULPT":
row = layout.column(align=True)
else:
row = layout.row(align=True)
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
row.separator()
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
row.prop(ups, "use_unified_color", text="", icon='BRUSHES_ALL')
if context.mode != "SCULPT":
row.separator()
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
row.prop(ups, "use_unified_color", text="", icon='BRUSHES_ALL')
layout.prop(brush, "blend", text="Blend Mode")
# Per sculpt tool options.
if sculpt_tool == "VCOL_BOUNDARY":
row = layout.row()
row.prop(brush, "vcol_boundary_exponent")
if sculpt_tool == 'CLAY_STRIPS':
row = layout.row()
row.prop(brush, "tip_roundness")
@@ -638,6 +885,7 @@ def brush_settings(layout, context, brush, popover=False):
layout.separator()
layout.prop(brush, "elastic_deform_type")
layout.prop(brush, "elastic_deform_volume_preservation", slider=True)
layout.prop(brush, "use_surface_falloff")
layout.separator()
elif sculpt_tool == 'SNAKE_HOOK':
@@ -701,6 +949,7 @@ def brush_settings(layout, context, brush, popover=False):
elif sculpt_tool == 'GRAB':
layout.prop(brush, "use_grab_active_vertex")
layout.prop(brush, "use_grab_silhouette")
layout.prop(brush, "use_surface_falloff")
elif sculpt_tool == 'PAINT':
row = layout.row(align=True)
@@ -754,9 +1003,28 @@ def brush_settings(layout, context, brush, popover=False):
col.prop(brush, "use_multiplane_scrape_dynamic")
col.prop(brush, "show_multiplane_scrape_planes_preview")
elif sculpt_tool == 'SCENE_PROJECT':
col = layout.column()
col.prop(brush, "scene_project_direction_type")
elif sculpt_tool == 'ARRAY':
col = layout.column()
col.prop(brush, "array_deform_type")
col.prop(brush, "array_count")
col.prop(brush, "use_array_lock_orientation")
col.prop(brush, "use_array_fill_holes")
elif sculpt_tool == 'SMOOTH':
col = layout.column()
col.prop(brush, "boundary_smooth_factor")
col.prop(brush, "use_weighted_smooth")
col.prop(brush, "preserve_faceset_boundary")
if brush.preserve_faceset_boundary:
col.prop(brush, "autosmooth_fset_slide")
col.prop(brush, "smooth_deform_type")
if brush.smooth_deform_type == 'SURFACE':
col.prop(brush, "surface_smooth_shape_preservation")
col.prop(brush, "surface_smooth_current_vertex")
@@ -769,6 +1037,10 @@ def brush_settings(layout, context, brush, popover=False):
elif sculpt_tool == 'MASK':
layout.row().prop(brush, "mask_tool", expand=True)
layout.template_curve_mapping(brush, "pressure_size_curve")
layout.template_curve_mapping(brush, "pressure_strength_curve", brush=True)
# End sculpt_tool interface.
# 3D and 2D Texture Paint Mode.
@@ -858,7 +1130,21 @@ def brush_shared_settings(layout, context, brush, popover=False):
size_prop = "size"
if size_mode and (size_owner.use_locked_size == 'SCENE'):
size_prop = "unprojected_radius"
if size or size_mode:
if size:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"radius" if size_prop == "size" else size_prop.upper(),
text="Radius",
slider=True,
)
if size_mode:
layout.row().prop(size_owner, "use_locked_size", expand=True)
layout.separator()
elif size or size_mode:
if size:
UnifiedPaintPanel.prop_unified(
layout,
@@ -874,7 +1160,16 @@ def brush_shared_settings(layout, context, brush, popover=False):
layout.row().prop(size_owner, "use_locked_size", expand=True)
layout.separator()
if strength:
if strength:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"strength",
slider=True
)
layout.separator()
elif strength:
pressure_name = "use_pressure_strength" if strength_pressure else None
UnifiedPaintPanel.prop_unified(
layout,
@@ -886,9 +1181,13 @@ def brush_shared_settings(layout, context, brush, popover=False):
slider=True,
)
layout.separator()
if direction:
layout.row().prop(brush, "direction", expand=True)
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"direction", expand=True)
#layout.row().prop(brush, "direction", expand=True)
def brush_settings_advanced(layout, context, brush, popover=False):
@@ -911,11 +1210,31 @@ def brush_settings_advanced(layout, context, brush, popover=False):
use_accumulate = capabilities.has_accumulate
use_frontface = True
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"automasking", expand=False)
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"automasking_boundary_edges_propagation_steps")
"""
col = layout.column(heading="Auto-Masking", align=True)
# topology automasking
col.prop(brush, "use_automasking_topology", text="Topology")
col.prop(brush, "use_automasking_concave")
col2 = col.column()
col2.enabled = brush.use_automasking_concave
col2.prop(brush, "concave_mask_factor", text="Cavity Factor")
col2.prop(brush, "invert_automasking_concavity", text="Invert Cavity Mask")
# face masks automasking
col.prop(brush, "use_automasking_face_sets", text="Face Sets")
@@ -923,6 +1242,7 @@ def brush_settings_advanced(layout, context, brush, popover=False):
col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
col.prop(brush, "automasking_boundary_edges_propagation_steps")
"""
layout.separator()

View File

@@ -279,9 +279,16 @@ class _defs_annotate:
class _defs_transform:
def draw_transform_sculpt_tool_settings(context, layout):
if context.mode != 'SCULPT':
return
layout.prop(context.tool_settings.sculpt, "transform_deform_target")
layout.prop(context.tool_settings.sculpt, "transform_mode")
@ToolDef.from_fn
def translate():
def draw_settings(context, layout, _tool):
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
return dict(
idname="builtin.move",
@@ -297,6 +304,7 @@ class _defs_transform:
@ToolDef.from_fn
def rotate():
def draw_settings(context, layout, _tool):
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2)
return dict(
idname="builtin.rotate",
@@ -312,6 +320,7 @@ class _defs_transform:
@ToolDef.from_fn
def scale():
def draw_settings(context, layout, _tool):
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3)
return dict(
idname="builtin.scale",
@@ -367,6 +376,7 @@ class _defs_transform:
props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo")
layout.prop(props, "drag_action")
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
return dict(
@@ -1294,7 +1304,9 @@ class _defs_sculpt:
# Use 'bpy.context' instead of 'context' since it can be None.
prefs = bpy.context.preferences
if not prefs.experimental.use_sculpt_vertex_colors:
exclude_filter = {'PAINT', 'SMEAR'}
exclude_filter = {'PAINT' : True, 'SMEAR' : True}
if not prefs.experimental.use_sculpt_uvsmooth:
exclude_filter['UV_SMOOTH'] = True
return generate_from_enum_ex(
context,
@@ -1412,6 +1424,7 @@ class _defs_sculpt:
props = tool.operator_properties("sculpt.trim_lasso_gesture")
layout.prop(props, "trim_mode", expand=False)
layout.prop(props, "trim_orientation", expand=False)
layout.prop(props, "trim_location", expand=False)
layout.prop(props, "use_cursor_depth", expand=False)
return dict(
idname="builtin.lasso_trim",
@@ -1426,6 +1439,7 @@ class _defs_sculpt:
def project_line():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.project_line_gesture")
layout.prop(props, "deformation_mode", expand=False)
layout.prop(props, "use_limit_to_segment", expand=False)
return dict(
@@ -1437,6 +1451,26 @@ class _defs_sculpt:
draw_settings=draw_settings,
)
@ToolDef.from_fn
def project_lasso():
return dict(
idname="builtin.lasso_project",
label="Lasso Project",
icon="ops.sculpt.lasso_project",
widget=None,
keymap=(),
)
@ToolDef.from_fn
def project_box():
return dict(
idname="builtin.box_project",
label="Box Project",
icon="ops.sculpt.box_project",
widget=None,
keymap=(),
)
@ToolDef.from_fn
def mesh_filter():
def draw_settings(_context, layout, tool):
@@ -1453,6 +1487,8 @@ class _defs_sculpt:
layout.prop(props, "sharpen_smooth_ratio", expand=False)
layout.prop(props, "sharpen_intensify_detail_strength", expand=False)
layout.prop(props, "sharpen_curvature_smooth_iterations", expand=False)
elif props.type == 'SPHERE':
layout.prop(props, "sphere_center", expand=False)
return dict(
idname="builtin.mesh_filter",
@@ -1463,6 +1499,23 @@ class _defs_sculpt:
draw_settings=draw_settings,
)
@ToolDef.from_fn
def ipmask_filter():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.ipmask_filter")
layout.prop(props, "filter_type", expand=False)
layout.prop(props, "iterations", expand=False)
layout.prop(props, "use_step_interpolation", expand=False)
return dict(
idname="builtin.ipmask_filter",
label="IPMask Filter",
icon="ops.sculpt.ipmask_filter",
widget=None,
keymap=(),
draw_settings=draw_settings,
)
@ToolDef.from_fn
def cloth_filter():
def draw_settings(_context, layout, tool):
@@ -1471,6 +1524,8 @@ class _defs_sculpt:
layout.prop(props, "strength")
row = layout.row(align=True)
row.prop(props, "force_axis")
if props.type == "PINCH":
layout.prop(props, "pinch_origin", expand=False)
layout.prop(props, "orientation", expand=False)
layout.prop(props, "cloth_mass")
layout.prop(props, "cloth_damping")
@@ -2845,10 +2900,15 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_sculpt.trim_box,
_defs_sculpt.trim_lasso,
),
(
_defs_sculpt.project_line,
_defs_sculpt.project_box,
_defs_sculpt.project_lasso,
),
None,
_defs_sculpt.mesh_filter,
_defs_sculpt.cloth_filter,
_defs_sculpt.ipmask_filter,
lambda context: (
(_defs_sculpt.color_filter,)
if context is None or (

View File

@@ -2248,6 +2248,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
self._draw_items(
context, (
({"property": "use_sculpt_vertex_colors"}, "T71947"),
({"property": "use_sculpt_uvsmooth"}, ""),
({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),

View File

@@ -171,6 +171,7 @@ class VIEW3D_HT_tool_header(Header):
row.popover(panel="VIEW3D_PT_tools_weightpaint_symmetry_for_topbar", text="")
elif mode_string == 'SCULPT':
row.popover(panel="VIEW3D_PT_sculpt_symmetry_for_topbar", text="")
layout.prop(context.object.data, "use_fset_boundary_mirror");
elif mode_string == 'PAINT_VERTEX':
row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="")
@@ -3061,6 +3062,12 @@ class VIEW3D_MT_sculpt(Menu):
props = layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")
props.use_eyedropper = True
props.flash_object = False
layout.separator()
layout.operator("sculpt.reset_brushes")
class VIEW3D_MT_mask(Menu):
@@ -3699,6 +3706,8 @@ class VIEW3D_MT_edit_mesh(Menu):
if with_bullet:
layout.operator("mesh.convex_hull")
layout.operator("mesh.fair_vertices", text="Fair")
layout.separator()
layout.operator("mesh.symmetrize")
@@ -5302,24 +5311,24 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
op = pie.operator("paint.mask_flood_fill", text='Clear Mask')
op.mode = 'VALUE'
op.value = 0.0
op = pie.operator("sculpt.mask_filter", text='Smooth Mask')
op.filter_type = 'SMOOTH'
op.auto_iteration_count = True
op = pie.operator("sculpt.mask_filter", text='Sharpen Mask')
op.filter_type = 'SHARPEN'
op.auto_iteration_count = True
op = pie.operator("sculpt.mask_filter", text='Grow Mask')
op.filter_type = 'GROW'
op.auto_iteration_count = True
op = pie.operator("sculpt.mask_filter", text='Shrink Mask')
op.filter_type = 'SHRINK'
op.auto_iteration_count = True
op = pie.operator("sculpt.mask_filter", text='Increase Contrast')
op.filter_type = 'CONTRAST_INCREASE'
op.auto_iteration_count = False
op = pie.operator("sculpt.mask_filter", text='Decrease Contrast')
op.filter_type = 'CONTRAST_DECREASE'
op.auto_iteration_count = False
op = pie.operator("sculpt.ipmask_filter", text='IPMask Smooth')
op.filter_type = "SMOOTH_SHARPEN"
op.iterations = 1
op = pie.operator("sculpt.ipmask_filter", text='IPMask Grow')
op.filter_type = "GROW_SHRINK"
op.iterations = 1
op = pie.operator("sculpt.ipmask_filter", text='IPMask Harder')
op.filter_type = "HARDER_SOFTER"
op.iterations = 1
op = pie.operator("sculpt.ipmask_filter", text='IPMask Contrast')
op.filter_type = "CONTRAST"
op.iterations = 1
class VIEW3D_MT_sculpt_automasking_pie(Menu):
@@ -5358,6 +5367,18 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
op.mode = 'SHOW_ALL'
op = pie.operator("sculpt.face_sets_init", text='Init by UV Seams')
op.mode = 'UV_SEAMS'
op = pie.operator("sculpt.face_sets_init", text='Init by Loose Parts')
op.mode = 'LOOSE_PARTS'
op = pie.operator("sculpt.face_sets_init", text='Init by Face Sets Boundaries')
op.mode = 'FACE_SET_BOUNDARIES'
op = pie.operator("sculpt.face_sets_create", text='Face Set from Selection')
op.mode = 'SELECTION'
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
bl_label = "Vertex Group Locks"

View File

@@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from bpy.types import Menu, Panel, UIList
from bpy.types import Menu, Panel, UIList, WindowManager
from bl_ui.properties_grease_pencil_common import (
GreasePencilSculptOptionsPanel,
GreasePencilDisplayPanel,
@@ -754,10 +754,78 @@ class VIEW3D_PT_tools_brush_falloff_normal(View3DPaintPanel, Panel):
layout.prop(ipaint, "normal_angle", text="Angle")
# TODO, move to space_view3d.py
class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Dyntopo (Advanced)"
#bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 12
@classmethod
def poll(cls, context):
paint_settings = cls.paint_settings(context)
return (context.sculpt_object and context.tool_settings.sculpt and paint_settings)
def draw_header(self, context):
pass
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
settings = self.paint_settings(context)
brush = settings.brush
col = layout.column()
col.label(text="Local Brush Settings")
row = col.row()
row.prop(brush.dyntopo, "disabled", text="Disable Dyntopo locally for this brush")
col.label(text="Overrides")
inherit_all = "ALL" in brush.dyntopo.inherit
col.prop_enum(brush.dyntopo, "inherit", value="ALL", text="Use All Defaults", icon="LOCKED" if inherit_all else "UNLOCKED")
def do_prop(key):
row = col.row()
if key.upper() in brush.dyntopo.inherit:
icon = "UNLOCKED"
else:
icon = "LOCKED"
row.prop_enum(brush.dyntopo, "inherit", value=key.upper(), icon=icon, text="")
row2 = row.row()
row2.prop(brush.dyntopo, key)
if icon == "UNLOCKED":
row2.enabled = False
if inherit_all:
row.enabled = False
col = layout.column()
do_prop("subdivide")
do_prop("collapse")
do_prop("cleanup")
do_prop("spacing")
do_prop("local_subdivide")
do_prop("local_collapse")
do_prop("detail_size")
do_prop("detail_range")
do_prop("detail_percent")
do_prop("constant_detail")
do_prop("mode")
do_prop("radius_scale")
# TODO, move to space_view3d.py
class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Dyntopo"
bl_label = "Dynamic Mode"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 12
@@ -789,6 +857,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
col = layout.column()
col.active = context.sculpt_object.use_dynamic_topology_sculpting
col.prop(sculpt, "use_dyntopo");
sub = col.column()
sub.active = (brush and brush.sculpt_tool != 'MASK')
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
@@ -806,7 +876,15 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
col.operator("sculpt.detail_flood_fill")
col.prop(sculpt, "use_dyntopo_cleanup")
col.prop(sculpt, "use_smooth_shading")
col.prop(sculpt, "use_flat_vcol_shading")
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_spacing", slider=True)
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_radius_scale", slider=True)
#col.prop(sculpt, "dyntopo_spacing")
#col.prop(sculpt, "dyntopo_radius_scale");
class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
@@ -837,6 +915,7 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
@@ -865,15 +944,36 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
col = layout.column(heading="Display", align=True)
col.prop(sculpt, "show_low_resolution")
col.prop(sculpt, "use_sculpt_delay_updates")
col.prop(sculpt, "use_fast_draw")
col.prop(sculpt, "use_deform_only")
col.prop(sculpt, "show_sculpt_pivot")
col.prop(sculpt, "smooth_strength_factor")
col.separator()
brush = sculpt.brush
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"automasking", toolsettings_only=True)
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"automasking_boundary_edges_propagation_steps",
toolsettings_only=True)
"""
col = layout.column(heading="Auto-Masking", align=True)
col.prop(sculpt, "use_automasking_topology", text="Topology")
col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
"""
col.separator()
col.operator("sculpt.set_limit_surface")
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
@@ -938,6 +1038,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
row.prop(sculpt, "tile_z", text="Z", toggle=True)
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
layout.prop(mesh, "use_fset_boundary_mirror")
layout.prop(sculpt, "radial_symmetry", text="Radial")
layout.prop(sculpt, "tile_offset", text="Tile Offset")
@@ -945,6 +1046,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
layout.prop(sculpt, "symmetrize_direction")
layout.operator("sculpt.symmetrize")
layout.prop(WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
@@ -2278,6 +2380,7 @@ classes = (
VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
VIEW3D_PT_sculpt_dyntopo_advanced
)
if __name__ == "__main__": # only for live edit.

View File

@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 22
#define BLENDER_FILE_SUBVERSION 24
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@@ -36,6 +36,8 @@ struct Main;
struct Scene;
struct ToolSettings;
struct UnifiedPaintSettings;
struct DynTopoSettings;
struct Sculpt;
// enum eCurveMappingPreset;
@@ -108,8 +110,13 @@ const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *
const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int size);
int BKE_brush_size_get(const struct Scene *scene,
const struct Brush *brush,
bool use_brush_channel);
void BKE_brush_size_set(struct Scene *scene,
struct Brush *brush,
int size,
bool use_brush_channel);
float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_unprojected_radius_set(struct Scene *scene,
@@ -137,6 +144,8 @@ void BKE_brush_scale_size(int *r_brush_size,
float new_unprojected_radius,
float old_unprojected_radius);
void BKE_brush_default_input_curves_set(struct Brush *brush);
/* Accessors */
#define BKE_brush_tool_get(brush, p) \
(CHECK_TYPE_ANY(brush, struct Brush *, const struct Brush *), \
@@ -151,6 +160,13 @@ void BKE_brush_scale_size(int *r_brush_size,
/* debugging only */
void BKE_brush_debug_print_state(struct Brush *br);
void BKE_brush_get_dyntopo(struct Brush *brush, struct Sculpt *sd, struct DynTopoSettings *out);
bool BKE_brush_hard_edge_mode_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_hard_edge_mode_set(struct Scene *scene, struct Brush *brush, bool val);
float BKE_brush_fset_slide_get(const struct Scene *scene, const struct Brush *brush);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,267 @@
#pragma once
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
/** \file
* \ingroup bke
* \brief New brush engine for sculpt
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "RNA_types.h"
/*
The new brush engine is based on command lists. These lists
will eventually be created by a node editor.
Key is the concept of BrushChannels. A brush channel is
a logical parameter with a type, input settings (e.g. pen),
a falloff curve, etc.
Brush channels have a concept of inheritance. There is a
BrushChannelSet (collection of channels) in Sculpt,
in Brush, and in BrushCommand. Inheritence behavior
is controller via BrushChannel->flag.
This should completely replace UnifiedPaintSettings.
*/
#include "DNA_sculpt_brush_types.h"
struct BrushChannel;
struct BlendWriter;
struct BlendDataReader;
struct Brush;
struct Sculpt;
//#define DEBUG_CURVE_MAPPING_ALLOC
#ifdef DEBUG_CURVE_MAPPING_ALLOC
void namestack_push(const char *name);
void *namestack_pop(void *passthru);
#endif
typedef struct BrushMappingDef {
int curve;
bool enabled;
bool inv;
float min, max;
int blendmode;
float factor; // if 0, will default to 1.0
} BrushMappingDef;
typedef struct BrushMappingPreset {
// must match order of BRUSH_MAPPING_XXX enums
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed;
} BrushMappingPreset;
typedef struct BrushMappingData {
float pressure, xtilt, ytilt, angle, speed;
} BrushMappingData;
#define MAX_BRUSH_ENUM_DEF 32
typedef struct BrushEnumDef {
int value;
const char identifier[64];
char icon[32];
const char name[64];
const char description[512];
} BrushEnumDef;
typedef struct BrushChannelType {
char name[64], idname[64], tooltip[512];
float min, max, soft_min, soft_max;
BrushMappingPreset mappings;
int type, flag;
int ivalue;
float fvalue;
float vector[4];
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
EnumPropertyItem *rna_enumdef;
bool user_defined;
} BrushChannelType;
typedef struct BrushCommand {
int tool;
float last_spacing_t[512]; // for different symmetry passes
struct BrushChannelSet *params;
struct BrushChannelSet *params_final;
struct BrushChannelSet *params_mapped;
} BrushCommand;
typedef struct BrushCommandList {
BrushCommand *commands;
int totcommand;
} BrushCommandList;
void BKE_brush_channel_free_data(BrushChannel *ch);
void BKE_brush_channel_free(BrushChannel *ch);
void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src);
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
BrushChannelSet *BKE_brush_channelset_create();
#ifdef DEBUG_CURVE_MAPPING_ALLOC
BrushChannelSet *_BKE_brush_channelset_copy(BrushChannelSet *src);
# define BKE_brush_channelset_copy(src) \
(namestack_push(__func__), (BrushChannelSet *)namestack_pop(_BKE_brush_channelset_copy(src)))
#else
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src);
#endif
void BKE_brush_channelset_free(BrushChannelSet *chset);
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch);
// makes a copy of ch
void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch);
// does not add to namemap ghash
void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch);
// does not free ch or its data
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch);
// does not free ch or its data
bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname);
// checks is a channel with existing->idname exists; if not a copy of existing is made and inserted
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing);
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent);
void BKE_brush_resolve_channels(struct Brush *brush, struct Sculpt *sd);
void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
int value);
int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
BrushMappingData *mapdata);
int BKE_brush_channelset_get_int(BrushChannelSet *chset,
const char *idname,
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val);
void BKE_brush_channel_set_int(BrushChannel *ch, int val);
float BKE_brush_channel_get_int(BrushChannel *ch, BrushMappingData *mapdata);
// mapdata is optional, can be NULL
/* mapdata may be NULL */
float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData *mapdata);
void BKE_brush_channel_set_float(BrushChannel *ch, float val);
/* mapdata may be NULL */
float BKE_brush_channelset_get_float(BrushChannelSet *chset,
const char *idname,
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname, float val);
float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
BrushMappingData *mapdata);
void BKE_brush_channelset_set_final_float(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
float value);
void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4]);
int BKE_brush_channel_get_vector_size(BrushChannel *ch);
/* returns size of vector */
int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingData *mapdata);
float BKE_brush_channelset_get_final_vector(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
float r_vec[4],
BrushMappingData *mapdata);
void BKE_brush_channelset_set_final_vector(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
float vec[4]);
int BKE_brush_channelset_get_vector(BrushChannelSet *chset,
const char *idname,
float r_vec[4],
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_vector(BrushChannelSet *chset, const char *idname, float vec[4]);
void BKE_brush_init_toolsettings(struct Sculpt *sd);
void BKE_brush_builtin_create(struct Brush *brush, int tool);
BrushCommandList *BKE_brush_commandlist_create();
void BKE_brush_commandlist_free(BrushCommandList *cl);
BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
BrushChannelSet *chset_template,
bool auto_inherit);
BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
void BKE_builtin_commandlist_create(struct Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *map_data); // map_data may be NULL
void BKE_brush_channelset_read(struct BlendDataReader *reader, BrushChannelSet *cset);
void BKE_brush_channelset_write(struct BlendWriter *writer, BrushChannelSet *cset);
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src);
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping);
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping);
void BKE_brush_channelset_flag_clear(BrushChannelSet *chset, const char *channel, int flag);
void BKE_brush_channelset_flag_set(BrushChannelSet *chset, const char *channel, int flag);
/* adds missing channels to exising .channels in brush.
* if channels do not exist use BKE_brush_builtin_create.
*/
void BKE_brush_builtin_patch(struct Brush *brush, int tool);
void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
struct Brush *brush,
bool to_channels);
// merge in channels the ui requested
void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override);
void BKE_brush_channeltype_rna_check(BrushChannelType *def,
int (*getIconFromName)(const char *name));
bool BKE_brush_mapping_ensure_write(BrushMapping *mp);
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
void BKE_brush_check_toolsettings(struct Sculpt *sd);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,26 @@
struct GHash;
struct CurveMapping;
typedef struct CurveMappingCache {
struct GHash *gh;
} CurveMappingCache;
bool BKE_curvemapping_equals(const struct CurveMapping *a, const struct CurveMapping *b);
uint BKE_curvemapping_calc_hash(const struct CurveMapping *cumap);
CurveMappingCache *BKE_curvemapping_cache_create(void);
CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
CurveMapping *curve,
bool free_input);
void BKE_curvemapping_cache_free(CurveMappingCache *cache);
CurveMappingCache *BKE_curvemapping_cache_global(void);
// takes a curve that's already in the cache and increases its user count
void BKE_curvemapping_cache_aquire(CurveMappingCache *cache, CurveMapping *curve);
void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve);
bool BKE_curvemapping_in_cache(CurveMapping *curve);
void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache, CurveMapping *curve);
void BKE_curvemapping_cache_exit();

View File

@@ -105,6 +105,8 @@ bool CustomData_has_math(const struct CustomData *data);
bool CustomData_has_interp(const struct CustomData *data);
bool CustomData_bmesh_has_free(const struct CustomData *data);
bool CustomData_layout_is_same(const struct CustomData *_a, const struct CustomData *_b);
/**
* Checks if any of the customdata layers is referenced.
*/
@@ -141,6 +143,10 @@ void CustomData_copy(const struct CustomData *source,
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
/* copies all customdata layers without allocating data,
* and without respect to type masks or NO_COPY/etc flags*/
void CustomData_copy_all_layout(const struct CustomData *source, struct CustomData *dest);
/* same as the above, except that this will preserve existing layers, and only
* add the layers that were not there yet */
bool CustomData_merge(const struct CustomData *source,
@@ -277,6 +283,16 @@ void CustomData_copy_data_named(const struct CustomData *source,
int dest_index,
int count);
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count);
// ignores CD_MESH_ID layer if it exists
void CustomData_bmesh_swap_data(struct CustomData *source,
struct CustomData *dest,
void *src_block,
void **dest_block);
// simple pointer swap; will unswaps ids if a CD_MESH_ID layer exists
void CustomData_bmesh_swap_data_simple(CustomData *data, void **block1, void **block2);
void CustomData_bmesh_copy_data(const struct CustomData *source,
struct CustomData *dest,
void *src_block,
@@ -605,6 +621,11 @@ void CustomData_blend_write(struct BlendWriter *writer,
struct ID *id);
void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count);
void CustomData_unmark_temporary_nocopy(struct CustomData *data);
void CustomData_mark_temporary_nocopy(struct CustomData *data);
int CustomData_get_elem_size(CustomDataLayer *layer);
#ifdef __cplusplus
}
#endif

View File

@@ -54,9 +54,11 @@ enum {
DT_TYPE_UV = 1 << 24,
DT_TYPE_SHARP_FACE = 1 << 25,
DT_TYPE_FREESTYLE_FACE = 1 << 26,
#define DT_TYPE_MAX 27
DT_TYPE_PROPCOL = 1 << 27,
#define DT_TYPE_MAX 28
DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT,
DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT |
DT_TYPE_PROPCOL,
DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE |
DT_TYPE_FREESTYLE_EDGE,
DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV,
@@ -74,7 +76,7 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type);
int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
#define DT_DATATYPE_IS_VERT(_dt) \
ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT)
ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT, DT_TYPE_PROPCOL)
#define DT_DATATYPE_IS_EDGE(_dt) \
ELEM(_dt, \
DT_TYPE_CREASE, \
@@ -94,7 +96,8 @@ enum {
DT_MULTILAYER_INDEX_SHAPEKEY = 1,
DT_MULTILAYER_INDEX_VCOL = 2,
DT_MULTILAYER_INDEX_UV = 3,
DT_MULTILAYER_INDEX_MAX = 4,
DT_MULTILAYER_INDEX_PROPCOL = 4,
DT_MULTILAYER_INDEX_MAX = 5,
};
/* Below we keep positive values for real layers idx (generated dynamically). */

View File

@@ -0,0 +1,24 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bke
* \brief Dynamic topology remeshing API
*/
typedef struct DynTopo DynTopo;

View File

@@ -78,8 +78,12 @@ typedef struct FModifierTypeInfo {
short size;
/** #eFMI_Action_Types. */
short acttype;
#ifdef __cplusplus
short requires_;
#else
/** #eFMI_Requirement_Flags. */
short requires;
#endif
/** name of modifier in interface. */
char name[64];
/** name of struct for SDNA. */

View File

@@ -69,7 +69,8 @@ extern "C" {
/* *** mesh.c *** */
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Mesh *me,
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Object *ob,
const struct Mesh *me,
const struct BMeshCreateParams *create_params,
const struct BMeshFromMeshParams *convert_params);
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me,
@@ -636,7 +637,7 @@ void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
/* In DerivedMesh.cc */
void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval,
const CustomData_MeshMasks *cd_mask_finalize);
const struct CustomData_MeshMasks *cd_mask_finalize);
/* **** Depsgraph evaluation **** */

View File

@@ -36,6 +36,7 @@ extern "C" {
typedef enum eMeshFairingDepth {
MESH_FAIRING_DEPTH_POSITION = 1,
MESH_FAIRING_DEPTH_TANGENCY = 2,
MESH_FAIRING_DEPTH_CURVATURE = 3,
} eMeshFairingDepth;
/* affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when

View File

@@ -105,20 +105,28 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *mpoly,
const struct MLoop *mloop,
int totvert,
int totpoly,
int totloop);
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *mpoly,
const struct MLoop *mloop,
int totvert,
int totpoly,
int totloop);
void BKE_mesh_vert_poly_map_create(
MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert, // only needed if sort_disk_cycles is true
const struct MEdge *medge, // only needed if sort_disk_cycles is true
const struct MPoly *mpoly,
const struct MLoop *mloop,
int totvert,
int totpoly,
int totloop,
const bool sort_disk_cycles); // put polys in sorted geometric order
void BKE_mesh_vert_loop_map_create(
MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert, // only needed if sort_disk_cycles is true
const struct MEdge *medge, // only needed if sort_disk_cycles is true
const struct MPoly *mpoly,
const struct MLoop *mloop,
int totvert,
int totpoly,
int totloop,
const bool sort_disk_cycles); // put loops in sorted geometric order
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert,
@@ -128,7 +136,13 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
const struct MLoop *mloop,
const int totloop);
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert, // only needed if sort_disk_cycles is true
const struct MEdge *medge,
int totvert,
int totedge,
bool sort_disk_cycles); // sort verts in geometric order around edges
void BKE_mesh_vert_edge_vert_map_create(
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,

View File

@@ -32,7 +32,7 @@ struct Mesh;
struct MirrorModifierData;
struct Object;
struct Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(struct MirrorModifierData *mmd,
struct Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(struct Object *ob, struct MirrorModifierData *mmd,
const struct Mesh *mesh,
int axis,
const float plane_co[3],

View File

@@ -47,6 +47,8 @@ struct Mesh *BKE_mesh_remesh_quadriflow(const struct Mesh *mesh,
void BKE_mesh_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *source);
void BKE_remesh_reproject_vertex_paint(struct Mesh *target, const struct Mesh *source);
void BKE_remesh_reproject_sculpt_face_sets(struct Mesh *target, struct Mesh *source);
void BKE_remesh_reproject_materials(struct Mesh *target, struct Mesh *source);
void BKE_mesh_remesh_sculpt_array_update(struct Object *ob, struct Mesh *target, struct Mesh *source);
#ifdef __cplusplus
}

View File

@@ -39,6 +39,7 @@ struct MultiresModifierData;
struct Object;
struct Scene;
struct SubdivCCG;
struct BMesh;
struct MLoop;
struct MLoopTri;
@@ -217,6 +218,7 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3]
const float dPdv[3],
const int corner);
void BKE_multires_bmesh_space_set(struct Object *ob, struct BMesh *bm, int mode);
/* Versioning. */
/* Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark

View File

@@ -25,6 +25,8 @@
#include "BLI_sys_types.h"
#include "DNA_object_enums.h"
#include "DNA_userdef_types.h"
#include "BKE_lib_id.h"
#ifdef __cplusplus
extern "C" {
@@ -154,8 +156,8 @@ bool BKE_object_obdata_is_libdata(const struct Object *ob);
struct Object *BKE_object_duplicate(struct Main *bmain,
struct Object *ob,
uint dupflag,
const uint duplicate_options);
eDupli_ID_Flags dupflag,
const eLibIDDuplicateFlags duplicate_options);
void BKE_object_obdata_size_init(struct Object *ob, const float size);

View File

@@ -23,15 +23,21 @@
* \ingroup bke
*/
#include "BKE_brush_engine.h"
#include "BKE_pbvh.h"
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
#include "DNA_brush_enums.h"
#include "DNA_customdata_types.h"
#include "DNA_object_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
struct SculptCustomLayer;
struct MDynTopoVert;
struct BMFace;
struct BMesh;
struct BlendDataReader;
@@ -260,6 +266,11 @@ typedef struct SculptPoseIKChain {
SculptPoseIKChainSegment *segments;
int tot_segments;
float grab_delta_offset[3];
float bend_mat[4][4];
float bend_mat_inv[4][4];
float bend_factor;
float bend_limit;
float bend_upper_limit;
} SculptPoseIKChain;
/* Cloth Brush */
@@ -335,6 +346,7 @@ typedef struct SculptClothSimulation {
float (*softbody_pos)[3];
float (*prev_pos)[3];
float (*last_iteration_pos)[3];
float (*init_normal)[3];
struct ListBase *collider_list;
@@ -342,6 +354,11 @@ typedef struct SculptClothSimulation {
/** #PBVHNode pointer as a key, index in #SculptClothSimulation.node_state as value. */
struct GHash *node_state_index;
eSculptClothNodeSimState *node_state;
// persistent base customdata layer offsets
int cd_pers_co;
int cd_pers_no;
int cd_pers_disp;
} SculptClothSimulation;
typedef struct SculptPersistentBase {
@@ -356,11 +373,15 @@ typedef struct SculptVertexInfo {
/* Indexed by base mesh vertex index, stores if that vertex is a boundary. */
BLI_bitmap *boundary;
/* Indexed by vertex, stores the symmetrical topology vertex index found by symmetrize. */
int *symmetrize_map;
} SculptVertexInfo;
typedef struct SculptBoundaryEditInfo {
/* Vertex index from where the topology propagation reached this vertex. */
int original_vertex;
SculptVertRef original_vertex;
int original_vertex_i;
/* How many steps were needed to reach this vertex from the boundary. */
int num_propagation_steps;
@@ -371,13 +392,23 @@ typedef struct SculptBoundaryEditInfo {
/* Edge for drawing the boundary preview in the cursor. */
typedef struct SculptBoundaryPreviewEdge {
int v1;
int v2;
SculptVertRef v1;
SculptVertRef v2;
} SculptBoundaryPreviewEdge;
#define MAX_STORED_COTANGENTW_EDGES 7
typedef struct StoredCotangentW {
float static_weights[MAX_STORED_COTANGENTW_EDGES];
float *weights;
int length;
} StoredCotangentW;
typedef struct SculptBoundary {
/* Vertex indices of the active boundary. */
int *vertices;
SculptVertRef *vertices;
int *vertex_indices;
int vertices_capacity;
int num_vertices;
@@ -386,6 +417,14 @@ typedef struct SculptBoundary {
* a distance of 0. */
float *distance;
float (*smoothco)[3];
float *boundary_dist; // distances from verts to boundary
float (*boundary_tangents)[3];
StoredCotangentW *boundary_cotangents;
SculptVertRef *boundary_closest;
int sculpt_totvert;
/* Data for drawing the preview. */
SculptBoundaryPreviewEdge *edges;
int edges_capacity;
@@ -395,12 +434,12 @@ typedef struct SculptBoundary {
bool forms_loop;
/* Initial vertex in the boundary which is closest to the current sculpt active vertex. */
int initial_vertex;
SculptVertRef initial_vertex;
/* Vertex that at max_propagation_steps from the boundary and closest to the original active
* vertex that was used to initialize the boundary. This is used as a reference to check how much
* the deformation will go into the mesh and to calculate the strength of the brushes. */
int pivot_vertex;
SculptVertRef pivot_vertex;
/* Stores the initial positions of the pivot and boundary initial vertex as they may be deformed
* during the brush action. This allows to use them as a reference positions and vectors for some
@@ -418,7 +457,7 @@ typedef struct SculptBoundary {
/* Bend Deform type. */
struct {
float (*pivot_rotation_axis)[3];
float (*pivot_positions)[3];
float (*pivot_positions)[4];
} bend;
/* Slide Deform type. */
@@ -431,8 +470,61 @@ typedef struct SculptBoundary {
float rotation_axis[3];
float pivot_position[3];
} twist;
/* Cicrle Deform type. */
struct {
float (*origin)[3];
float *radius;
} circle;
} SculptBoundary;
/* Array Brush. */
typedef struct SculptArrayCopy {
int index;
int symm_pass;
float mat[4][4];
float imat[4][4];
float origin[3];
} SculptArrayCopy;
typedef struct ScultpArrayPathPoint {
float length;
float strength;
float co[3];
float orco[3];
float direction[3];
} ScultpArrayPathPoint;
typedef struct SculptArray {
SculptArrayCopy *copies[PAINT_SYMM_AREAS];
int num_copies;
struct {
ScultpArrayPathPoint *points;
int tot_points;
int capacity;
float total_length;
} path;
int mode;
float normal[3];
float direction[3];
float radial_angle;
float initial_radial_angle;
bool source_mat_valid;
float source_origin[3];
float source_mat[4][4];
float source_imat[4][4];
float (*orco)[3];
int *copy_index;
int *symmetry_pass;
float *smooth_strength;
} SculptArray;
typedef struct SculptFakeNeighbors {
bool use_fake_neighbors;
@@ -440,7 +532,7 @@ typedef struct SculptFakeNeighbors {
float current_max_distance;
/* Indexed by vertex, stores the vertex index of its fake neighbor if available. */
int *fake_neighbor_index;
SculptVertRef *fake_neighbor_index;
} SculptFakeNeighbors;
@@ -459,8 +551,15 @@ typedef struct SculptSession {
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
struct MVert *mvert;
struct MPoly *mpoly;
struct MEdge *medge;
struct MLoop *mloop;
struct MPoly *mpoly;
// only assigned in PBVH_FACES and PBVH_GRIDS
CustomData *vdata, *edata, *ldata, *pdata;
// for grids
CustomData temp_vdata, temp_pdata;
/* These contain the vertex and poly counts of the final mesh. */
int totvert, totpoly;
@@ -495,8 +594,13 @@ typedef struct SculptSession {
/* BMesh for dynamic topology sculpting */
struct BMesh *bm;
int cd_dyn_vert;
int cd_vert_node_offset;
int cd_face_node_offset;
int cd_vcol_offset;
int cd_faceset_offset;
int cd_face_areas;
bool bm_smooth_shading;
/* Undo/redo log for dynamic topology sculpting */
struct BMLog *bm_log;
@@ -509,6 +613,10 @@ typedef struct SculptSession {
bool show_mask;
bool show_face_sets;
/* Setting this to true allows a PBVH rebuild when evaluating the object even if the stroke or
* filter caches are active. */
bool needs_pbvh_rebuild;
/* Painting on deformed mesh */
bool deform_modifiers_active; /* Object is deformed with some modifiers. */
float (*orig_cos)[3]; /* Coords of un-deformed mesh. */
@@ -524,9 +632,9 @@ typedef struct SculptSession {
struct ExpandCache *expand_cache;
/* Cursor data and active vertex for tools */
int active_vertex_index;
SculptVertRef active_vertex_index;
SculptFaceRef active_face_index;
int active_face_index;
int active_grid_index;
/* When active, the cursor draws with faded colors, indicating that there is an action enabled.
@@ -540,6 +648,7 @@ typedef struct SculptSession {
/* For Sculpt trimming gesture tools, initial raycast data from the position of the mouse when
* the gesture starts (intersection with the surface and if they ray hit the surface or not). */
float gesture_initial_back_location[3];
float gesture_initial_location[3];
float gesture_initial_normal[3];
bool gesture_initial_hit;
@@ -548,9 +657,17 @@ typedef struct SculptSession {
struct RegionView3D *rv3d;
struct View3D *v3d;
struct Scene *scene;
int cd_origvcol_offset;
int cd_origco_offset;
int cd_origno_offset;
/* Face Sets by topology. */
int face_set_last_created;
SculptFaceRef face_set_last_poly;
SculptEdgeRef face_set_last_edge;
/* Dynamic mesh preview */
int *preview_vert_index_list;
SculptVertRef *preview_vert_index_list;
int preview_vert_index_count;
/* Pose Brush Preview */
@@ -564,9 +681,15 @@ typedef struct SculptSession {
/* This is freed with the PBVH, so it is always in sync with the mesh. */
SculptPersistentBase *persistent_base;
// float (*limit_surface)[3];
struct SculptCustomLayer *limit_surface;
SculptVertexInfo vertex_info;
SculptFakeNeighbors fake_neighbors;
/* Array. */
SculptArray *array;
/* Transform operator */
float pivot_pos[3];
float pivot_rot[4];
@@ -612,6 +735,13 @@ typedef struct SculptSession {
*/
char needs_flush_to_id;
// id of current stroke, used to detect
// if vertex original data needs to be updated
int stroke_id, boundary_symmetry;
bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth
struct MDynTopoVert *mdyntopo_verts; // for non-bmesh
int mdyntopo_verts_size;
} SculptSession;
void BKE_sculptsession_free(struct Object *ob);
@@ -619,6 +749,7 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert);
/* Create new color layer on object if it doesn't have one and if experimental feature set has
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
@@ -655,6 +786,8 @@ void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
char BKE_get_fset_boundary_symflag(struct Object *object);
enum {
SCULPT_MASK_LAYER_CALC_VERT = (1 << 0),
SCULPT_MASK_LAYER_CALC_LOOP = (1 << 1),

View File

@@ -22,25 +22,103 @@
*/
#include "BLI_bitmap.h"
#include "BLI_compiler_compat.h"
#include "BLI_ghash.h"
/* For embedding CCGKey in iterator. */
#include "BKE_ccg.h"
#include <stdint.h>
//#define DEFRAGMENT_MEMORY
#ifdef __cplusplus
extern "C" {
#endif
// experimental feature to detect quad diagonals and mark (but not dissolve) them
//#define SCULPT_DIAGONAL_EDGE_MARKS
typedef struct SculptVertRef {
intptr_t i;
} SculptVertRef;
typedef struct SculptEdgeRef {
intptr_t i;
} SculptEdgeRef;
typedef struct SculptFaceRef {
intptr_t i;
} SculptFaceRef;
#define SCULPT_REF_NONE ((intptr_t)-1)
#if 0
typedef struct SculptLoopRef {
intptr_t i;
} SculptLoopRef;
#endif
BLI_INLINE SculptVertRef BKE_pbvh_make_vref(intptr_t i)
{
SculptVertRef ret = {i};
return ret;
}
BLI_INLINE SculptEdgeRef BKE_pbvh_make_eref(intptr_t i)
{
SculptEdgeRef ret = {i};
return ret;
}
BLI_INLINE SculptFaceRef BKE_pbvh_make_fref(intptr_t i)
{
SculptFaceRef ret = {i};
return ret;
}
#ifdef DEFRAGMENT_MEMORY
# include "BLI_smallhash.h"
#endif
typedef struct PBVHTri {
int v[3]; // references into PBVHTriBuf->verts
intptr_t l[3]; // loops
int eflag; // bitmask of which edges in the tri are real edges in the mesh
float no[3];
SculptFaceRef f;
} PBVHTri;
typedef struct PBVHTriBuf {
PBVHTri *tris;
SculptVertRef *verts;
int *edges;
int totvert, totedge, tottri;
int verts_size, edges_size, tris_size;
SmallHash vertmap; // maps vertex ptrs to indices within verts
// private field
intptr_t *loops;
int totloop, mat_nr;
float min[3], max[3];
} PBVHTriBuf;
struct BMLog;
struct BMesh;
struct BMVert;
struct BMEdge;
struct BMFace;
struct CCGElem;
struct CCGKey;
struct CustomData;
struct TableGSet;
struct DMFlagMat;
struct GPU_PBVH_Buffers;
struct IsectRayPrecalc;
struct MLoop;
struct MLoopTri;
struct MDynTopoVert;
struct MPoly;
struct MVert;
struct Mesh;
@@ -52,12 +130,86 @@ struct TaskParallelSettings;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
//#define PROXY_ADVANCED
// experimental performance test of "data-based programming" approach
#ifdef PROXY_ADVANCED
typedef struct ProxyKey {
int node;
int pindex;
} ProxyKey;
# define MAX_PROXY_NEIGHBORS 12
typedef struct ProxyVertArray {
float **ownerco;
short **ownerno;
float (*co)[3];
float (*fno)[3];
short (*no)[3];
float *mask, **ownermask;
SculptVertRef *index;
float **ownercolor, (*color)[4];
ProxyKey (*neighbors)[MAX_PROXY_NEIGHBORS];
int size;
int datamask;
bool neighbors_dirty;
GHash *indexmap;
} ProxyVertArray;
typedef enum {
PV_OWNERCO = 1,
PV_OWNERNO = 2,
PV_CO = 4,
PV_NO = 8,
PV_MASK = 16,
PV_OWNERMASK = 32,
PV_INDEX = 64,
PV_OWNERCOLOR = 128,
PV_COLOR = 256,
PV_NEIGHBORS = 512
} ProxyVertField;
typedef struct ProxyVertUpdateRec {
float *co, *no, *mask, *color;
SculptVertRef index, newindex;
} ProxyVertUpdateRec;
# define PBVH_PROXY_DEFAULT CO | INDEX | MASK
struct SculptSession;
void BKE_pbvh_ensure_proxyarrays(
struct SculptSession *ss, PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
void BKE_pbvh_load_proxyarrays(PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
void BKE_pbvh_ensure_proxyarray(
struct SculptSession *ss,
struct PBVH *pbvh,
struct PBVHNode *node,
int mask,
struct GHash
*vert_node_map, // vert_node_map maps vertex SculptVertRefs to PBVHNode indices; optional
bool check_indexmap,
bool force_update);
void BKE_pbvh_gather_proxyarray(PBVH *pbvh, PBVHNode **nodes, int totnode);
void BKE_pbvh_free_proxyarray(struct PBVH *pbvh, struct PBVHNode *node);
void BKE_pbvh_update_proxyvert(struct PBVH *pbvh, struct PBVHNode *node, ProxyVertUpdateRec *rec);
ProxyVertArray *BKE_pbvh_get_proxyarrays(struct PBVH *pbvh, struct PBVHNode *node);
#endif
typedef struct {
float (*co)[3];
} PBVHProxyNode;
typedef struct {
float (*color)[4];
int size;
} PBVHColorBufferNode;
typedef enum {
@@ -78,6 +230,15 @@ typedef enum {
PBVH_UpdateTopology = 1 << 13,
PBVH_UpdateColor = 1 << 14,
PBVH_Delete = 1 << 15,
PBVH_UpdateCurvatureDir = 1 << 16,
PBVH_UpdateTris = 1 << 17,
PBVH_RebuildNodeVerts = 1 << 18,
/* tri areas are not guaranteed to be up to date, tools should
update all nodes on first step of brush*/
PBVH_UpdateTriAreas = 1 << 19,
PBVH_UpdateOtherVerts = 1 << 20
} PBVHNodeFlags;
typedef struct PBVHFrustumPlanes {
@@ -98,6 +259,9 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float *tmin);
void BKE_pbvh_get_nodes(PBVH *pbvh, int flag, PBVHNode ***r_array, int *r_totnode);
PBVHNode *BKE_pbvh_get_node(PBVH *pbvh, int node);
/* Building */
PBVH *BKE_pbvh_new(void);
@@ -106,27 +270,57 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
const struct MPoly *mpoly,
const struct MLoop *mloop,
struct MVert *verts,
struct MDynTopoVert *mdyntopo_verts,
int totvert,
struct CustomData *vdata,
struct CustomData *ldata,
struct CustomData *pdata,
const struct MLoopTri *looptri,
int looptri_num);
int looptri_num,
bool fast_draw);
void BKE_pbvh_build_grids(PBVH *pbvh,
struct CCGElem **grids,
int totgrid,
struct CCGKey *key,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
unsigned int **grid_hidden,
bool fast_draw);
void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset);
const int cd_face_node_offset,
const int cd_dyn_vert,
const int cd_face_areas,
bool fast_draw);
void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_dyn_vert,
const int cd_face_areas);
void BKE_pbvh_free(PBVH *pbvh);
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log);
/** update original data, only data whose r_** parameters are passed in will be updated*/
void BKE_pbvh_bmesh_update_origvert(
PBVH *pbvh, struct BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo);
void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_update_origco_bmesh(PBVH *pbvh, PBVHNode *node);
/**
checks if original data needs to be updated for v, and if so updates it. Stroke_id
is provided by the sculpt code and is used to detect updates. The reason we do it
inside the verts and not in the nodes is to allow splitting of the pbvh during the stroke.
*/
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, struct BMVert *v, int stroke_id);
/** used so pbvh can differentiate between different strokes,
see BKE_pbvh_bmesh_check_origdata */
void BKE_pbvh_set_stroke_id(PBVH *pbvh, int stroke_id);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
* - gather nodes in an array (easy to multithread) */
@@ -150,7 +344,8 @@ void BKE_pbvh_raycast(PBVH *pbvh,
void *data,
const float ray_start[3],
const float ray_normal[3],
bool original);
bool original,
int stroke_id);
bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
@@ -159,12 +354,16 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
int *hit_count,
float *depth,
int *active_vertex_index,
int *active_face_grid_index,
float *face_normal);
float *back_depth,
SculptVertRef *active_vertex_index,
SculptFaceRef *active_face_grid_index,
float *face_normal,
int stroke_id);
bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
bool BKE_pbvh_bmesh_node_raycast_detail(PBVH *pbvh,
PBVHNode *node,
const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
float *depth,
@@ -189,7 +388,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
float *depth,
float *dist_sq);
float *dist_sq,
int stroke_id);
/* Drawing */
@@ -238,22 +438,60 @@ int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
/* Only valid for type == PBVH_BMESH */
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size, float detail_range);
typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
PBVH_Subdivide = 1 << 0,
PBVH_Collapse = 1 << 1,
PBVH_Cleanup = 1 << 2, // dissolve verts surrounded by either 3 or 4 triangles then triangulate
PBVH_LocalSubdivide = 1 << 3,
PBVH_LocalCollapse = 1 << 4
} PBVHTopologyUpdateMode;
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
float radius,
const bool use_frontface,
const bool use_projected);
typedef float (*DyntopoMaskCB)(SculptVertRef vertex, void *userdata);
bool BKE_pbvh_bmesh_update_topology(
PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
float radius,
const bool use_frontface,
const bool use_projected,
int symaxis,
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data,
int custom_max_steps); // if 0, will use defaul hueristics for max steps
bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
bool (*searchcb)(PBVHNode *node, void *data),
void (*undopush)(PBVHNode *node, void *data),
void *searchdata,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
float radius,
const bool use_frontface,
const bool use_projected,
int sym_axis,
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data);
/* Node Access */
void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node);
// updates boundaries and valences for whole mesh
void BKE_pbvh_bmesh_on_mesh_change(PBVH *pbvh);
bool BKE_pbvh_bmesh_check_valence(PBVH *pbvh, SculptVertRef vertex);
void BKE_pbvh_bmesh_update_valence(int cd_dyn_vert, SculptVertRef vertex);
void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh);
void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh);
bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex);
void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node);
void BKE_pbvh_update_all_tri_areas(PBVH *pbvh);
void BKE_pbvh_node_mark_update(PBVHNode *node);
void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
void BKE_pbvh_node_mark_update_color(PBVHNode *node);
@@ -292,10 +530,14 @@ bool BKE_pbvh_node_frustum_contain_AABB(PBVHNode *node, void *frustum);
/* test if AABB is at least partially outside the PBVHFrustumPlanes volume */
bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *frustum);
struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
struct TableGSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
struct TableGSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
struct TableGSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh);
void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node);
// now generated PBVHTris
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
/* Update Bounding Box/Redraw and clear flags */
@@ -343,6 +585,7 @@ typedef struct PBVHVertexIter {
int gy;
int i;
int index;
SculptVertRef vertex;
bool respect_hide;
/* grid */
@@ -362,10 +605,14 @@ typedef struct PBVHVertexIter {
float *vmask;
/* bmesh */
struct GSetIterator bm_unique_verts;
struct GSetIterator bm_other_verts;
int bi;
struct TableGSet *bm_cur_set;
struct TableGSet *bm_unique_verts, *bm_other_verts;
struct CustomData *bm_vdata;
int cd_dyn_vert;
int cd_vert_mask_offset;
int cd_vcol_offset;
/* result: these are all computed in the macro, but we assume
* that compiler optimization's will skip the ones we don't use */
@@ -379,6 +626,8 @@ typedef struct PBVHVertexIter {
bool visible;
} PBVHVertexIter;
#define BKE_PBVH_DYNVERT(cd_dyn_vert, v) ((MDynTopoVert *)BM_ELEM_CD_GET_VOID_P(v, cd_dyn_vert))
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
@@ -388,7 +637,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
if (vi.grids) { \
vi.width = vi.gridsize; \
vi.height = vi.gridsize; \
vi.index = vi.grid_indices[vi.g] * vi.key.grid_area - 1; \
vi.vertex.i = vi.index = vi.grid_indices[vi.g] * vi.key.grid_area - 1; \
vi.grid = vi.grids[vi.grid_indices[vi.g]]; \
if (mode == PBVH_ITER_UNIQUE) { \
vi.gh = vi.grid_hidden[vi.grid_indices[vi.g]]; \
@@ -407,6 +656,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi.mask = vi.key.has_mask ? CCG_elem_mask(&vi.key, vi.grid) : NULL; \
vi.grid = CCG_elem_next(&vi.key, vi.grid); \
vi.index++; \
vi.vertex.i++; \
vi.visible = true; \
if (vi.gh) { \
if (BLI_BITMAP_TEST(vi.gh, vi.gy * vi.gridsize + vi.gx)) { \
@@ -427,7 +677,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
vi.co = vi.mvert->co; \
vi.no = vi.mvert->no; \
vi.index = vi.vert_indices[vi.i]; \
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
if (vi.vmask) { \
vi.mask = &vi.vmask[vi.index]; \
} \
@@ -436,22 +686,41 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
} \
else { \
if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \
BLI_gsetIterator_step(&vi.bm_unique_verts); \
BMVert *bv = NULL; \
while (!bv) { \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_cur_set->cur) { \
if (vi.bm_cur_set != vi.bm_other_verts && mode != PBVH_ITER_UNIQUE) { \
vi.bm_cur_set = vi.bm_other_verts; \
vi.bi = 0; \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_other_verts->cur) { \
break; \
} \
} \
else { \
break; \
} \
} \
else { \
bv = vi.bm_cur_set->elems[vi.bi++]; \
} \
} \
else { \
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \
BLI_gsetIterator_step(&vi.bm_other_verts); \
if (!bv) { \
continue; \
} \
vi.bm_vert = bv; \
if (vi.cd_vcol_offset >= 0) { \
MPropCol *vcol = BM_ELEM_CD_GET_VOID_P(bv, vi.cd_vcol_offset); \
vi.col = vcol->color; \
} \
vi.vertex.i = (intptr_t)bv; \
vi.index = BM_elem_index_get(vi.bm_vert); \
vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
} \
vi.co = vi.bm_vert->co; \
vi.fno = vi.bm_vert->no; \
vi.index = BM_elem_index_get(vi.bm_vert); \
vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
vi.mask = (float *)BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
}
#define BKE_pbvh_vertex_iter_end \
@@ -460,24 +729,32 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
((void)0)
#define BKE_pbvh_vertex_index_to_table(pbvh, v) \
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMVert *)(v.i)) : (v.i))
SculptVertRef BKE_pbvh_table_index_to_vertex(PBVH *pbvh, int idx);
#define BKE_pbvh_edge_index_to_table(pbvh, v) \
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMEdge *)(v.i)) : (v.i))
SculptEdgeRef BKE_pbvh_table_index_to_edge(PBVH *pbvh, int idx);
#define BKE_pbvh_face_index_to_table(pbvh, v) \
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMFace *)(v.i)) : (v.i))
SculptFaceRef BKE_pbvh_table_index_to_face(PBVH *pbvh, int idx);
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
void BKE_pbvh_node_free_proxies(PBVHNode *node);
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
float (**r_orco_coords)[3]);
bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
bool pbvh_has_mask(const PBVH *pbvh);
bool BKE_pbvh_draw_mask(const PBVH *pbvh);
void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
bool pbvh_has_face_sets(PBVH *pbvh);
bool BKE_pbvh_draw_face_sets(PBVH *pbvh);
void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
/* Parallelization */
@@ -490,6 +767,150 @@ struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node);
int BKE_pbvh_get_node_id(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_set_flat_vcol_shading(PBVH *pbvh, bool value);
#define DYNTOPO_CD_INTERP
void SCULPT_update_flat_vcol_shading(struct Object *ob, struct Scene *scene);
void BKE_pbvh_curvature_update_set(PBVHNode *node, bool state);
bool BKE_pbvh_curvature_update_get(PBVHNode *node);
int BKE_pbvh_get_totnodes(PBVH *pbvh);
bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node);
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
/*recalculates boundary flags for *all* vertices. used by
symmetrize.*/
void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh);
void BKE_pbvh_bmesh_remove_face(PBVH *pbvh, struct BMFace *f, bool log_face);
void BKE_pbvh_bmesh_remove_vertex(PBVH *pbvh, struct BMVert *v, bool log_vert);
void BKE_pbvh_bmesh_add_face(PBVH *pbvh, struct BMFace *f, bool log_face, bool force_tree_walk);
// note that e_tri and f_example are allowed to be NULL
struct BMFace *BKE_pbvh_face_create_bmesh(PBVH *pbvh,
struct BMVert *v_tri[3],
struct BMEdge *e_tri[3],
const struct BMFace *f_example);
// if node is NULL, one will be foudn in the pbvh, which potentially can be slow
struct BMVert *BKE_pbvh_vert_create_bmesh(
PBVH *pbvh, float co[3], float no[3], PBVHNode *node, struct BMVert *v_example);
PBVHNode *BKE_pbvh_node_from_face_bmesh(PBVH *pbvh, struct BMFace *f);
PBVHNode *BKE_pbvh_node_from_index(PBVH *pbvh, int node_i);
struct BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh);
void BKE_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
struct BMVert *v,
int symmetry);
#define DYNTOPO_DYNAMIC_TESS
PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i);
void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_areas, int valence);
void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry);
#if 0
typedef enum {
SCULPT_TEXTURE_UV = 1 << 0, // per-uv
// SCULPT_TEXTURE_PTEX?
} SculptTextureType;
typedef int TexLayerRef;
/*
Texture points are texels projected into 3d.
*/
typedef intptr_t TexPointRef;
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm);
typedef struct SculptTextureDef {
SculptTextureType type;
int settings_size;
void (*build_begin)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
/*vdms can cache data per node, which is freed to maintain memory limit.
they store cache in the same structure they return in buildNodeData.*/
void (*freeCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
void (*ensuredCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
/*builds all data that isn't cached.*/
void *(*buildNodeData)(PBVH *pbvh, PBVHNode *node);
bool (*validate)(PBVH *pbvh, TexLayerRef vdm);
void (*getPointsFromNode)(PBVH *pbvh,
PBVHNode *node,
TexLayerRef vdm,
TexPointRef **r_ids,
float ***r_cos,
float ***r_nos,
int *r_totpoint);
void (*releaseNodePoints)(
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, float **cos, float **nos);
# if 0
int (*getTrisFromNode)(PBVH *pbvh,
PBVHNode *node,
TexLayerRef vdm,
TexPointRef *((*r_tris)[3]),
TexPointRef **r_ids,
int tottri,
int totid);
void (*getTriInterpWeightsFromNode)(PBVH *pbvh,
PBVHNode *node,
TexLayerRef vdm,
float *((*r_tris)[3]),
SculptLoopRef ***r_src_loops,
int tottri,
int totloop);
int (*getTriCount)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
# endif
void (*getPointNeighbors)(PBVH *pbvh,
PBVHNode *node,
TexLayerRef vdm,
TexPointRef id,
TexPointRef **r_neighbor_ids,
int *r_totneighbor,
int maxneighbors,
TexPointRef **r_duplicates_id,
int r_totduplicate,
int maxduplicates);
void (*getPointValence)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef id);
void (*freeNodeData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, void *settings);
void (*getPointsFromIds)(
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
/*displacement texture stuff*/
// can be tangent, object space displacement, whatever
void (*worldToDelta)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
void (*deltaToWorld)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
} SculptDisplacementDef;
typedef struct SculptLayerEntry {
char name[64];
int type;
void *settings;
float factor;
struct SculptLayerEntry *parent;
} SculptLayerEntry;
#endif
int BKE_pbvh_do_fset_symmetry(int fset, const int symflag, const float *co);
bool BKE_pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v);
#ifdef __cplusplus
}
#endif

View File

@@ -124,6 +124,7 @@ set(SRC
intern/displist.cc
intern/displist_tangent.c
intern/dynamicpaint.c
intern/dyntopo.c
intern/editlattice.c
intern/editmesh.c
intern/editmesh_bvh.c
@@ -235,6 +236,7 @@ set(SRC
intern/particle_system.c
intern/pbvh.c
intern/pbvh_bmesh.c
intern/pbvh_displacement.c
intern/pointcache.c
intern/pointcloud.cc
intern/preferences.c
@@ -287,6 +289,9 @@ set(SRC
intern/workspace.c
intern/world.c
intern/writeavi.c
intern/brush_engine.c
intern/brush_engine_presets.c
intern/curvemapping_cache.c
BKE_DerivedMesh.h
BKE_action.h
@@ -335,6 +340,7 @@ set(SRC
BKE_curveprofile.h
BKE_customdata.h
BKE_customdata_file.h
BKE_curvemapping_cache.h
BKE_data_transfer.h
BKE_deform.h
BKE_displist.h
@@ -449,6 +455,7 @@ set(SRC
BKE_workspace.h
BKE_world.h
BKE_writeavi.h
BKE_brush_engine.h
nla_private.h
particle_private.h
@@ -794,3 +801,75 @@ if(WITH_GTESTS)
include(GTestTesting)
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
endif()
if(false)
set(PBVH_CACHE_TEST_INC
.
../blenfont
../blenlib
../blenloader
../blentranslation
../bmesh
../depsgraph
../draw
../functions
../gpencil_modifiers
../gpu
../ikplugin
../imbuf
../makesdna
../makesrna
../modifiers
../nodes
../render
../sequencer
../shader_fx
../simulation
../../../intern/eigen
../../../intern/ghost
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/iksolver/extern
../../../intern/atomic
../../../intern/clog
../../../intern/libmv
../../../intern/mantaflow/extern
../../../intern/memutil
../../../intern/mikktspace
../../../intern/opensubdiv
../../../extern/curve_fit_nd
)
set(PBVH_CACHE_TEST_SRC
intern/pbvh_cache_test_main.c
)
setup_libdirs()
add_executable(pbvh_cache_test ${PBVH_CACHE_TEST_SRC} ${PBVH_CACHE_TEST_INC})
setup_platform_linker_flags(pbvh_cache_test)
target_link_libraries(pbvh_cache_test bf_blenkernel bf_bmesh bf_intern_ghost bf_blenlib bf_intern_guardedalloc)
if(WIN32)
set_target_properties(pbvh_cache_test PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
set_target_properties(pbvh_cache_test PROPERTIES
PDB_NAME "pbvh_cache_test_private"
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
if(WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB)
# This is slightly messy, but single target generators like ninja will not have the
# CMAKE_CFG_INTDIR variable and multitarget generators like msbuild will not have
# CMAKE_BUILD_TYPE. This can be simplified by target_link_options and the $<CONFIG>
# generator expression in newer cmake (2.13+) but until that time this fill have suffice.
if(CMAKE_BUILD_TYPE)
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/pbvh_cache_test_public.pdb")
else()
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/pbvh_cache_test_public.pdb")
endif()
endif()
endif()
if (WIN32)
target_link_libraries(pbvh_cache_test Vfw32.lib Imm32.lib Version.lib Comctl32.lib Shcore.lib Pathcch.lib)
endif()
endif()

View File

@@ -1140,7 +1140,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
unsupported = true;
}
if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) {
if (scene->toolsettings->sculpt && scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) {
unsupported |= (mti->type != eModifierTypeType_OnlyDeform);
}

View File

@@ -425,7 +425,7 @@ void BKE_animdata_copy_id_action(Main *bmain, ID *id)
void BKE_animdata_duplicate_id_action(struct Main *bmain,
struct ID *id,
const eDupli_ID_Flags duplicate_flags)
const uint duplicate_flags)
{
if (duplicate_flags & USER_DUP_ACT) {
animdata_copy_id_action(bmain, id, true, (duplicate_flags & USER_DUP_LINKED_ID) != 0);

View File

@@ -34,6 +34,7 @@
#include "BLT_translation.h"
#include "BKE_brush.h"
#include "BKE_brush_engine.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
@@ -85,6 +86,8 @@ static void brush_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
}
brush_dst->curve = BKE_curvemapping_copy(brush_src->curve);
brush_dst->pressure_size_curve = BKE_curvemapping_copy(brush_src->pressure_size_curve);
brush_dst->pressure_strength_curve = BKE_curvemapping_copy(brush_src->pressure_strength_curve);
if (brush_src->gpencil_settings != NULL) {
brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings);
brush_dst->gpencil_settings->curve_sensitivity = BKE_curvemapping_copy(
@@ -119,6 +122,8 @@ static void brush_free_data(ID *id)
IMB_freeImBuf(brush->icon_imbuf);
}
BKE_curvemapping_free(brush->curve);
BKE_curvemapping_free(brush->pressure_size_curve);
BKE_curvemapping_free(brush->pressure_strength_curve);
if (brush->gpencil_settings != NULL) {
BKE_curvemapping_free(brush->gpencil_settings->curve_sensitivity);
@@ -138,6 +143,10 @@ static void brush_free_data(ID *id)
MEM_SAFE_FREE(brush->gradient);
BKE_previewimg_free(&(brush->preview));
if (brush->channels) {
BKE_brush_channelset_free(brush->channels);
}
}
static void brush_make_local(Main *bmain, ID *id, const int flags)
@@ -217,7 +226,7 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_texture_mtex_foreach_id(data, &brush->mask_mtex);
}
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
ATTR_NO_OPT static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Brush *brush = (Brush *)id;
@@ -227,6 +236,12 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (brush->curve) {
BKE_curvemapping_blend_write(writer, brush->curve);
}
if (brush->pressure_size_curve) {
BKE_curvemapping_blend_write(writer, brush->pressure_size_curve);
}
if (brush->pressure_strength_curve) {
BKE_curvemapping_blend_write(writer, brush->pressure_strength_curve);
}
if (brush->gpencil_settings) {
BLO_write_struct(writer, BrushGpencilSettings, brush->gpencil_settings);
@@ -262,15 +277,82 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (brush->gradient) {
BLO_write_struct(writer, ColorBand, brush->gradient);
}
if (brush->channels) {
BKE_brush_channelset_write(writer, brush->channels);
}
}
static void brush_reset_input_curve(CurveMapping *cumap)
{
cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
cumap->preset = CURVE_PRESET_LINE;
CurveMap *cuma = cumap->cm;
BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
BKE_curvemapping_changed(cumap, false);
BKE_curvemapping_init(cumap);
}
void BKE_brush_default_input_curves_set(Brush *brush)
{
if (brush->pressure_size_curve) {
BKE_curvemapping_free(brush->pressure_size_curve);
}
brush->pressure_size_curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
brush_reset_input_curve(brush->pressure_size_curve);
if (brush->pressure_strength_curve) {
BKE_curvemapping_free(brush->pressure_strength_curve);
}
brush->pressure_strength_curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
brush_reset_input_curve(brush->pressure_strength_curve);
}
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
{
Brush *brush = (Brush *)id;
if (brush->channels) {
BLO_read_data_address(reader, &brush->channels);
BKE_brush_channelset_read(reader, brush->channels);
BKE_brush_builtin_patch(brush, brush->sculpt_tool);
}
else {
BKE_brush_builtin_create(brush, brush->sculpt_tool);
}
if (brush->dyntopo.radius_scale == 0.0f) {
brush->dyntopo.radius_scale = 1.0f;
brush->dyntopo.inherit |= DYNTOPO_INHERIT_RADIUS_SCALE;
}
// detect old file data
if (brush->autosmooth_radius_factor == 0.0f) {
brush->autosmooth_radius_factor = 1.0f;
}
if (brush->topology_rake_radius_factor == 0.0f) {
brush->topology_rake_radius_factor = 1.0f;
}
if (brush->autosmooth_spacing == 0.0f) {
brush->autosmooth_spacing = 12;
}
if (brush->topology_rake_spacing == 0.0f) {
brush->topology_rake_spacing = 12;
brush->topology_rake_projection = 1.0f;
}
/* Falloff curve. */
BLO_read_data_address(reader, &brush->curve);
/* Input Curves. */
BLO_read_data_address(reader, &brush->pressure_size_curve);
BLO_read_data_address(reader, &brush->pressure_strength_curve);
BLO_read_data_address(reader, &brush->gradient);
if (brush->curve) {
@@ -280,6 +362,20 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
BKE_brush_curve_preset(brush, CURVE_PRESET_SHARP);
}
if (brush->pressure_size_curve) {
BKE_curvemapping_blend_read(reader, brush->pressure_size_curve);
}
else {
BKE_brush_default_input_curves_set(brush);
}
if (brush->pressure_strength_curve) {
BKE_curvemapping_blend_read(reader, brush->pressure_strength_curve);
}
else {
BKE_brush_default_input_curves_set(brush);
}
/* grease pencil */
BLO_read_data_address(reader, &brush->gpencil_settings);
if (brush->gpencil_settings != NULL) {
@@ -464,7 +560,13 @@ static void brush_defaults(Brush *brush)
FROM_DEFAULT(alpha);
FROM_DEFAULT(hardness);
FROM_DEFAULT(autosmooth_factor);
FROM_DEFAULT(autosmooth_projection);
FROM_DEFAULT(autosmooth_radius_factor);
FROM_DEFAULT(autosmooth_spacing);
FROM_DEFAULT(topology_rake_factor);
FROM_DEFAULT(topology_rake_radius_factor);
FROM_DEFAULT(topology_rake_projection);
FROM_DEFAULT(topology_rake_spacing);
FROM_DEFAULT(crease_pinch_factor);
FROM_DEFAULT(normal_radius_factor);
FROM_DEFAULT(wet_paint_radius_factor);
@@ -495,6 +597,7 @@ static void brush_defaults(Brush *brush)
FROM_DEFAULT(stencil_dimension);
FROM_DEFAULT(mtex);
FROM_DEFAULT(mask_mtex);
FROM_DEFAULT(dyntopo);
#undef FROM_DEFAULT
#undef FROM_DEFAULT_PTR
@@ -1662,6 +1765,8 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST(plane_offset, f);
BR_TEST(autosmooth_factor, f);
BR_TEST(autosmooth_projection, f);
BR_TEST(autosmooth_radius_factor, f);
BR_TEST(topology_rake_factor, f);
@@ -1693,8 +1798,19 @@ void BKE_brush_sculpt_reset(Brush *br)
* settings used by a brush: */
// BKE_brush_debug_print_state(br);
BKE_brush_builtin_create(br, br->sculpt_tool);
BrushChannel *ch;
for (ch = (BrushChannel *)br->channels->channels.first; ch; ch = ch->next) {
BrushChannelType *def = ch->def;
BKE_brush_channel_free_data(ch);
BKE_brush_channel_init(ch, def);
}
brush_defaults(br);
BKE_brush_curve_preset(br, CURVE_PRESET_SMOOTH);
BKE_brush_default_input_curves_set(br);
/* Use the curve presets by default */
br->curve_preset = BRUSH_CURVE_SMOOTH;
@@ -1703,10 +1819,17 @@ void BKE_brush_sculpt_reset(Brush *br)
* assign this so logic below can remain the same. */
br->alpha = 0.5f;
bool disable_dyntopo = false;
// XXX basic face set setup for all organic brushes
br->autosmooth_fset_slide = 1.0f;
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT;
/* Brush settings */
switch (br->sculpt_tool) {
case SCULPT_TOOL_DRAW_SHARP:
br->flag |= BRUSH_DIR_IN;
br->flag |= BRUSH_SIZE_PRESSURE;
br->curve_preset = BRUSH_CURVE_POW4;
br->spacing = 5;
break;
@@ -1714,11 +1837,28 @@ void BKE_brush_sculpt_reset(Brush *br)
br->curve_preset = BRUSH_CURVE_SMOOTHER;
br->spacing = 10;
br->alpha = 1.0f;
disable_dyntopo = true;
break;
case SCULPT_TOOL_FAIRING:
br->curve_preset = BRUSH_CURVE_SMOOTHER;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->spacing = 10;
br->alpha = 1.0f;
break;
case SCULPT_TOOL_SCENE_PROJECT:
br->curve_preset = BRUSH_CURVE_SMOOTHER;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->spacing = 10;
br->alpha = 1.0f;
break;
case SCULPT_TOOL_SLIDE_RELAX:
br->spacing = 10;
br->alpha = 1.0f;
br->slide_deform_type = BRUSH_SLIDE_DEFORM_DRAG;
disable_dyntopo = true;
break;
case SCULPT_TOOL_CLAY:
br->flag |= BRUSH_SIZE_PRESSURE;
@@ -1735,15 +1875,36 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag |= BRUSH_SIZE_PRESSURE;
br->flag &= ~BRUSH_SPACE_ATTEN;
break;
case SCULPT_TOOL_CLAY_STRIPS:
case SCULPT_TOOL_TWIST:
br->alpha = 0.5f;
br->normal_radius_factor = 1.0f;
br->spacing = 6;
br->hardness = 0.5f;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->flag &= ~BRUSH_SIZE_PRESSURE;
break;
case SCULPT_TOOL_CLAY_STRIPS: {
br->flag |= BRUSH_ACCUMULATE | BRUSH_SIZE_PRESSURE;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->alpha = 0.6f;
br->spacing = 5;
br->normal_radius_factor = 1.55f;
br->alpha = 0.8f;
br->spacing = 7;
br->normal_radius_factor = 1.35f;
br->tip_roundness = 0.18f;
br->curve_preset = BRUSH_CURVE_SMOOTHER;
break;
CurveMap *cuma = br->pressure_size_curve->cm;
cuma->curve[0].x = 0.0f;
cuma->curve[0].y = 0.55f;
BKE_curvemap_insert(cuma, 0.5f, 0.7f);
cuma->curve[2].x = 1.0f;
cuma->curve[2].y = 1.0f;
BKE_curvemapping_changed(br->pressure_size_curve, true);
cuma = br->pressure_strength_curve->cm;
BKE_curvemap_insert(cuma, 0.6f, 0.25f);
BKE_curvemapping_changed(br->pressure_strength_curve, true);
} break;
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
br->flag2 |= BRUSH_MULTIPLANE_SCRAPE_DYNAMIC | BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW;
br->alpha = 0.7f;
@@ -1766,18 +1927,29 @@ void BKE_brush_sculpt_reset(Brush *br)
break;
case SCULPT_TOOL_ROTATE:
br->alpha = 1.0;
disable_dyntopo = true;
break;
case SCULPT_TOOL_SMOOTH:
br->flag &= ~BRUSH_SPACE_ATTEN;
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT;
br->spacing = 5;
br->alpha = 0.7f;
br->surface_smooth_shape_preservation = 0.5f;
br->surface_smooth_current_vertex = 0.5f;
br->surface_smooth_iterations = 4;
disable_dyntopo = true;
break;
case SCULPT_TOOL_SNAKE_HOOK:
br->alpha = 1.0f;
br->rake_factor = 1.0f;
br->dyntopo.inherit = DYNTOPO_INHERIT_BITMASK &
~(DYNTOPO_INHERIT_ALL | DYNTOPO_LOCAL_COLLAPSE |
DYNTOPO_INHERIT_DETAIL_RANGE);
br->dyntopo.flag |= DYNTOPO_LOCAL_COLLAPSE;
br->dyntopo.detail_range = 0.4f;
break;
case SCULPT_TOOL_THUMB:
br->size = 75;
@@ -1791,6 +1963,8 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
disable_dyntopo = true;
break;
case SCULPT_TOOL_POSE:
br->pose_smooth_iterations = 4;
@@ -1799,18 +1973,24 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
disable_dyntopo = true;
break;
case SCULPT_TOOL_BOUNDARY:
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->curve_preset = BRUSH_CURVE_CONSTANT;
disable_dyntopo = true;
break;
case SCULPT_TOOL_DRAW_FACE_SETS:
br->alpha = 0.5f;
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
disable_dyntopo = true;
break;
case SCULPT_TOOL_GRAB:
br->alpha = 0.4f;
@@ -1818,6 +1998,8 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
disable_dyntopo = true;
break;
case SCULPT_TOOL_CLOTH:
br->cloth_mass = 1.0f;
@@ -1826,6 +2008,8 @@ void BKE_brush_sculpt_reset(Brush *br)
br->cloth_sim_falloff = 0.75f;
br->cloth_deform_type = BRUSH_CLOTH_DEFORM_DRAG;
br->flag &= ~(BRUSH_ALPHA_PRESSURE | BRUSH_SIZE_PRESSURE);
disable_dyntopo = true;
break;
case SCULPT_TOOL_LAYER:
br->flag &= ~BRUSH_SPACE_ATTEN;
@@ -1843,6 +2027,8 @@ void BKE_brush_sculpt_reset(Brush *br)
br->density = 1.0f;
br->flag &= ~BRUSH_SPACE_ATTEN;
zero_v3(br->rgb);
disable_dyntopo = true;
break;
case SCULPT_TOOL_SMEAR:
br->alpha = 1.0f;
@@ -1850,6 +2036,18 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->curve_preset = BRUSH_CURVE_SPHERE;
disable_dyntopo = true;
break;
case SCULPT_TOOL_VCOL_BOUNDARY:
br->flag &= ~BRUSH_SPACE_ATTEN;
br->spacing = 5;
br->alpha = 0.7f;
br->surface_smooth_shape_preservation = 0.5f;
br->surface_smooth_current_vertex = 0.5f;
br->surface_smooth_iterations = 4;
disable_dyntopo = true;
break;
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
br->alpha = 1.0f;
@@ -1858,11 +2056,17 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->curve_preset = BRUSH_CURVE_SMOOTHER;
disable_dyntopo = true;
break;
default:
break;
}
if (disable_dyntopo) {
// disabled flag is never inherited
br->dyntopo.flag |= DYNTOPO_DISABLED;
}
/* Cursor colors */
/* Default Alpha */
@@ -1910,6 +2114,7 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_POSE:
case SCULPT_TOOL_BOUNDARY:
case SCULPT_TOOL_SLIDE_RELAX:
case SCULPT_TOOL_TWIST:
br->add_col[0] = 1.0f;
br->add_col[1] = 0.95f;
br->add_col[2] = 0.005f;
@@ -1919,11 +2124,26 @@ void BKE_brush_sculpt_reset(Brush *br)
break;
case SCULPT_TOOL_SIMPLIFY:
// don't use DYNTOPO_INHERIT_BITMASK, we want to include
// future bits
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT |
BRUSH_CURVATURE_RAKE;
br->dyntopo.inherit = 0x7FFFFFFF &
~(DYNTOPO_INHERIT_ALL | DYNTOPO_SUBDIVIDE | DYNTOPO_COLLAPSE);
br->dyntopo.flag |= DYNTOPO_COLLAPSE | DYNTOPO_SUBDIVIDE;
br->autosmooth_factor = 0.05;
br->topology_rake_factor = 0.35;
br->topology_rake_projection = 0.975;
break;
case SCULPT_TOOL_VCOL_BOUNDARY:
case SCULPT_TOOL_PAINT:
case SCULPT_TOOL_MASK:
case SCULPT_TOOL_DRAW_FACE_SETS:
case SCULPT_TOOL_DISPLACEMENT_ERASER:
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
case SCULPT_TOOL_ARRAY:
br->add_col[0] = 0.75f;
br->add_col[1] = 0.75f;
br->add_col[2] = 0.75f;
@@ -2041,7 +2261,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene,
/* leave the coordinates relative to the screen */
/* use unadjusted size for tiled mode */
invradius = 1.0f / BKE_brush_size_get(scene, br);
invradius = 1.0f / BKE_brush_size_get(scene, br, false);
x = point_2d[0];
y = point_2d[1];
@@ -2154,7 +2374,7 @@ float BKE_brush_sample_masktex(
/* leave the coordinates relative to the screen */
/* use unadjusted size for tiled mode */
invradius = 1.0f / BKE_brush_size_get(scene, br);
invradius = 1.0f / BKE_brush_size_get(scene, br, false);
x = point_2d[0];
y = point_2d[1];
@@ -2244,8 +2464,19 @@ void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float c
}
}
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
void BKE_brush_size_set(Scene *scene, Brush *brush, int size, bool use_brush_channels)
{
if (use_brush_channels) {
if (scene->toolsettings->sculpt && scene->toolsettings->sculpt->channels) {
BKE_brush_channelset_set_final_float(
brush->channels, scene->toolsettings->sculpt->channels, "radius", (float)size);
return;
}
else {
BKE_brush_channelset_set_float(brush->channels, "radius", (float)size);
}
}
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
/* make sure range is sane */
@@ -2259,8 +2490,22 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
}
}
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
int BKE_brush_size_get(const Scene *scene, const Brush *brush, bool use_brush_channel)
{
if (!scene->toolsettings->sculpt || !scene->toolsettings->sculpt->channels || !brush->channels) {
use_brush_channel = false;
}
if (use_brush_channel) {
if (scene->toolsettings->sculpt) {
return (int)BKE_brush_channelset_get_final_float(
brush->channels, scene->toolsettings->sculpt->channels, "radius", NULL);
}
else {
return (int)BKE_brush_channelset_get_float(brush->channels, "radius", NULL);
}
}
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
@@ -2403,7 +2648,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
spread = 1.0;
}
else {
diameter = 2 * BKE_brush_size_get(scene, brush);
diameter = 2 * BKE_brush_size_get(scene, brush, false);
spread = brush->jitter;
}
/* find random position within a circle of diameter 1 */
@@ -2426,7 +2671,7 @@ void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
}
/* Uses the brush curve control to find a strength value */
float BKE_brush_curve_strength(const Brush *br, float p, const float len)
ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float len)
{
float strength = 1.0f;
@@ -2554,3 +2799,135 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool
return im;
}
void BKE_brush_get_dyntopo(Brush *brush, Sculpt *sd, DynTopoSettings *out)
{
*out = brush->dyntopo;
int inherit = out->inherit;
if (inherit & DYNTOPO_INHERIT_ALL) {
inherit = 0x7FFFFFFF;
}
if (!(sd->flags & SCULPT_DYNTOPO_ENABLED)) {
out->flag |= DYNTOPO_DISABLED;
}
if (inherit & DYNTOPO_INHERIT_MODE) {
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
out->mode = DYNTOPO_DETAIL_CONSTANT;
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
out->mode = DYNTOPO_DETAIL_BRUSH;
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL) {
out->mode = DYNTOPO_DETAIL_MANUAL;
}
else {
out->mode = DYNTOPO_DETAIL_RELATIVE;
}
}
if (inherit & DYNTOPO_INHERIT_RADIUS_SCALE) {
out->radius_scale = sd->dyntopo_radius_scale;
}
if (inherit & DYNTOPO_INHERIT_DETAIL_SIZE) {
out->detail_size = sd->detail_size;
}
if (inherit & DYNTOPO_INHERIT_DETAIL_RANGE) {
out->detail_range = sd->detail_range;
}
if (inherit & DYNTOPO_INHERIT_DETAIL_PERCENT) {
out->detail_percent = sd->detail_percent;
}
if (inherit & DYNTOPO_INHERIT_SPACING) {
out->spacing = sd->dyntopo_spacing;
}
if (inherit & DYNTOPO_INHERIT_CONSTANT_DETAIL) {
out->constant_detail = sd->constant_detail;
}
if (inherit & DYNTOPO_SUBDIVIDE) {
if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) {
out->flag |= DYNTOPO_SUBDIVIDE;
}
else {
out->flag &= ~DYNTOPO_SUBDIVIDE;
}
}
if (inherit & DYNTOPO_LOCAL_COLLAPSE) {
if (sd->flags & SCULPT_DYNTOPO_LOCAL_COLLAPSE) {
out->flag |= DYNTOPO_LOCAL_COLLAPSE;
}
else {
out->flag &= ~DYNTOPO_LOCAL_COLLAPSE;
}
}
if (inherit & DYNTOPO_LOCAL_SUBDIVIDE) {
if (sd->flags & SCULPT_DYNTOPO_LOCAL_SUBDIVIDE) {
out->flag |= DYNTOPO_LOCAL_SUBDIVIDE;
}
else {
out->flag &= ~DYNTOPO_LOCAL_SUBDIVIDE;
}
}
if (inherit & DYNTOPO_COLLAPSE) {
if (sd->flags & SCULPT_DYNTOPO_COLLAPSE) {
out->flag |= DYNTOPO_COLLAPSE;
}
else {
out->flag &= ~DYNTOPO_COLLAPSE;
}
}
if (inherit & DYNTOPO_CLEANUP) {
if (sd->flags & SCULPT_DYNTOPO_CLEANUP) {
out->flag |= DYNTOPO_CLEANUP;
}
else {
out->flag &= ~DYNTOPO_CLEANUP;
}
}
};
bool BKE_brush_hard_edge_mode_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
bool ret = (ups->flag & UNIFIED_PAINT_FLAG_HARD_EDGE_MODE) ? ups->hard_edge_mode :
brush->flag2 & BRUSH_HARD_EDGE_MODE;
return ret;
}
void BKE_brush_hard_edge_mode_set(Scene *scene, Brush *brush, bool val)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
if (ups->flag & UNIFIED_PAINT_FLAG_HARD_EDGE_MODE) {
ups->hard_edge_mode = val;
}
else {
if (val) {
brush->flag2 |= BRUSH_HARD_EDGE_MODE;
}
else {
brush->flag2 &= ~BRUSH_HARD_EDGE_MODE;
}
}
}
float BKE_brush_fset_slide_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return BKE_brush_hard_edge_mode_get(scene, brush) ? 0.0f : brush->autosmooth_fset_slide;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -171,8 +171,16 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
if (!cddm->pmap && ob->type == OB_MESH) {
Mesh *me = ob->data;
BKE_mesh_vert_poly_map_create(
&cddm->pmap, &cddm->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
BKE_mesh_vert_poly_map_create(&cddm->pmap,
&cddm->pmap_mem,
me->mvert,
me->medge,
me->mpoly,
me->mloop,
me->totvert,
me->totpoly,
me->totloop,
false);
}
return cddm->pmap;

View File

@@ -688,9 +688,12 @@ static Collection *collection_duplicate_recursive(Main *bmain,
Collection *BKE_collection_duplicate(Main *bmain,
Collection *parent,
Collection *collection,
eDupli_ID_Flags duplicate_flags,
eLibIDDuplicateFlags duplicate_options)
const uint duplicate_flags_in, // it's not const!! - joeedh
const uint duplicate_options_in) // not const!
{
uint duplicate_flags = duplicate_flags_in;
uint duplicate_options = duplicate_options_in;
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;

View File

@@ -85,7 +85,8 @@ void BKE_curvemapping_set_defaults(
cumap->changed_timestamp = 0;
}
CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
ATTR_NO_OPT CurveMapping *BKE_curvemapping_add(
int tot, float minx, float miny, float maxx, float maxy)
{
CurveMapping *cumap;
@@ -96,7 +97,7 @@ CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx,
return cumap;
}
void BKE_curvemapping_free_data(CurveMapping *cumap)
ATTR_NO_OPT void BKE_curvemapping_free_data(CurveMapping *cumap)
{
int a;
@@ -124,12 +125,57 @@ void BKE_curvemapping_free(CurveMapping *cumap)
}
}
static void *my_dupalloc_id(void *mem, const char *tag)
{
size_t size = MEM_allocN_len(mem);
void *ret = MEM_mallocN(size, tag);
memcpy(ret, mem, size);
return ret;
};
void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target,
const CurveMapping *cumap,
const char *tag)
{
int a;
bool not_cache = !(target->flag & CUMA_PART_OF_CACHE);
*target = *cumap;
if (not_cache) {
target->flag &= ~CUMA_PART_OF_CACHE;
}
target->cache_users = 0;
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve) {
target->cm[a].curve = my_dupalloc_id(cumap->cm[a].curve, tag);
}
if (cumap->cm[a].table) {
target->cm[a].table = my_dupalloc_id(cumap->cm[a].table, tag);
}
if (cumap->cm[a].premultable) {
target->cm[a].premultable = my_dupalloc_id(cumap->cm[a].premultable, tag);
}
}
}
void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
{
int a;
bool not_cache = !(target->flag & CUMA_PART_OF_CACHE);
*target = *cumap;
if (not_cache) {
target->flag &= ~CUMA_PART_OF_CACHE;
}
for (a = 0; a < CM_TOT; a++) {
if (cumap->cm[a].curve) {
target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
@@ -143,11 +189,12 @@ void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
}
}
CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
ATTR_NO_OPT CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
{
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
BKE_curvemapping_copy_data(cumapn, cumap);
cumapn->flag &= ~CUMA_PART_OF_CACHE;
return cumapn;
}
return NULL;
@@ -305,6 +352,15 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
case CURVE_PRESET_BELL:
cuma->totpoint = 3;
break;
case CURVE_PRESET_POW2:
cuma->totpoint = 5;
break;
case CURVE_PRESET_POW3:
cuma->totpoint = 6;
break;
case CURVE_PRESET_POW15:
cuma->totpoint = 6;
break;
}
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
@@ -401,8 +457,60 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
cuma->curve[2].x = 1.0f;
cuma->curve[2].y = 0.025f;
break;
}
case CURVE_PRESET_POW2:
cuma->curve[0].x = 0.0f;
cuma->curve[0].y = 0.0f;
cuma->curve[1].x = 0.25f;
cuma->curve[1].y = 0.0625f;
cuma->curve[2].x = 0.5;
cuma->curve[2].y = 0.25;
cuma->curve[3].x = 0.75f;
cuma->curve[3].y = 0.5625f;
cuma->curve[4].x = 1.0f;
cuma->curve[4].y = 1.0f;
case CURVE_PRESET_POW3:
cuma->curve[0].x = 0.0f;
cuma->curve[0].y = 0.0f;
cuma->curve[1].x = 0.135f;
cuma->curve[1].y = 0.002f;
cuma->curve[2].x = 0.318;
cuma->curve[2].y = 0.032;
cuma->curve[3].x = 0.528;
cuma->curve[3].y = 0.147f;
cuma->curve[4].x = 0.757f;
cuma->curve[4].y = 0.433f;
cuma->curve[5].x = 1.0f;
cuma->curve[5].y = 1.0f;
case CURVE_PRESET_POW15:
cuma->curve[0].x = 0.0f;
cuma->curve[0].y = 0.0f;
cuma->curve[1].x = 0.135f;
cuma->curve[1].y = 0.002f;
cuma->curve[2].x = 0.318;
cuma->curve[2].y = 0.032;
cuma->curve[3].x = 0.528;
cuma->curve[3].y = 0.147f;
cuma->curve[4].x = 0.757f;
cuma->curve[4].y = 0.433f;
cuma->curve[5].x = 1.0f;
cuma->curve[5].y = 1.0f;
}
//[[0,0], [0.134,0.002], [0.318,0.032], [0.528,0.147], [0.757,0.433], [1,1]
/* mirror curve in x direction to have positive slope
* rather than default negative slope */
if (slope == CURVEMAP_SLOPE_POSITIVE) {
@@ -1241,7 +1349,8 @@ void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap
BKE_curvemapping_curves_blend_write(writer, cumap);
}
void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping *cumap)
ATTR_NO_OPT void BKE_curvemapping_curves_blend_write(BlendWriter *writer,
const CurveMapping *cumap)
{
for (int a = 0; a < CM_TOT; a++) {
BLO_write_struct_array(writer, CurveMapPoint, cumap->cm[a].totpoint, cumap->cm[a].curve);
@@ -1252,7 +1361,7 @@ void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
{
/* flag seems to be able to hang? Maybe old files... not bad to clear anyway */
cumap->flag &= ~CUMA_PREMULLED;
cumap->flag &= ~(CUMA_PREMULLED | CUMA_PART_OF_CACHE);
for (int a = 0; a < CM_TOT; a++) {
BLO_read_data_address(reader, &cumap->cm[a].curve);

View File

@@ -351,7 +351,10 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md)
{
if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
if (md->type == eModifierType_Multires) {
return true;
}
if (md->type == eModifierType_Subsurf && md->mode & eModifierMode_OnCage) {
return true;
}
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);

View File

@@ -100,7 +100,7 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
* for #Curve.bevresol is 32. */
float *quarter_coords_x = alloca(sizeof(float) * (cu->bevresol + 1));
float *quarter_coords_y = alloca(sizeof(float) * (cu->bevresol + 1));
bevel_quarter_fill(cu, quarter_coords_x, quarter_coords_y);
bevel_quarter_fill((Curve *)cu, quarter_coords_x, quarter_coords_y);
int nr;
if (fill_type == FULL) {

View File

@@ -0,0 +1,318 @@
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_array.h"
#include "BLI_bitmap.h"
#include "BLI_compiler_attrs.h"
#include "BLI_compiler_compat.h"
#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_mempool.h"
#include "BLI_rand.h"
#include "BLI_rect.h"
#include "BLI_smallhash.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "DNA_brush_enums.h"
#include "DNA_brush_types.h"
#include "DNA_color_types.h"
#include "DNA_curveprofile_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_sculpt_brush_types.h"
#include "BKE_brush.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_brush_engine.h"
#include "BKE_curvemapping_cache.h"
#include "BKE_curveprofile.h"
#include "BLO_read_write.h"
/*
The brush system needs to make lots of copies of BrushChannels
as it resolves relationships between commands, brushes and the tool settings.
Unfortunately each brush command has five parameter curves, and copying
them over and over again has proven to be slow.
Solution: a kind of small string optimization approach but for curves
*/
static int curvmapping_curve_count(const CurveMapping *cumap)
{
int count = 0;
for (int i = 0; i < CM_TOT; i++) {
if (cumap->cm[i].curve) {
count++;
}
}
return count;
}
ATTR_NO_OPT bool BKE_curvemapping_equals(const CurveMapping *a, const CurveMapping *b)
{
int count = curvmapping_curve_count(a);
if (curvmapping_curve_count(b) != count) {
return false;
}
bool ok = true;
ok = ok && a->tone == b->tone;
for (int i = 0; i < 3; i++) {
ok = ok && a->black[i] == b->black[i];
ok = ok && a->white[i] == b->white[i];
ok = ok && a->bwmul[i] == b->bwmul[i];
}
if (!ok) {
return false;
}
for (int i = 0; i < count; i++) {
const CurveMap *c1 = a->cm + i;
const CurveMap *c2 = b->cm + i;
if (!c1 || !c2) {
return false;
}
if (c1->totpoint != c2->totpoint) {
return false;
}
for (int j = 0; j < c1->totpoint; j++) {
ok = ok && fabsf(c1->curve[j].x - c2->curve[j].x) <= FLT_EPSILON * 8;
ok = ok && fabsf(c1->curve[j].y - c2->curve[j].y) <= FLT_EPSILON * 8;
}
if (!ok) {
return false;
}
}
return true;
}
/*truncate float to avoid rounding errors
messing up the hash*/
#define FRACT_TRUNCATE_STEPS 8192.0f
ATTR_NO_OPT BLI_INLINE unsigned int get_float_hash(float f)
{
float f_floor = floor(f);
float fract = f - f_floor;
fract = floorf(fract * FRACT_TRUNCATE_STEPS) / FRACT_TRUNCATE_STEPS;
uint *ret = (uint *)&f;
return *ret;
}
#define HASHFLOAT(f) h = get_float_hash(f), hash ^= BLI_hash_int(h + hi++)
#define HASHINT(f) h = get_float_hash(f), hash ^= BLI_hash_int(f + hi++)
ATTR_NO_OPT uint BKE_curvemapping_calc_hash(const CurveMapping *cumap)
{
uint hash = 0;
uint h = 0;
uint hi = 0;
int totcurve = curvmapping_curve_count(cumap);
HASHINT(totcurve);
HASHINT(cumap->tone);
for (int i = 0; i < 3; i++) {
HASHFLOAT(cumap->white[i]);
HASHFLOAT(cumap->black[i]);
HASHFLOAT(cumap->bwmul[i]);
}
for (int i = 0; i < totcurve; i++) {
if (!cumap->cm[i].curve) {
break;
}
const CurveMap *cu = cumap->cm + i;
for (int j = 0; j < cu->totpoint; j++) {
HASHFLOAT(cu->curve[j].x);
HASHFLOAT(cu->curve[j].y);
}
}
return hash & ((1 << 29) - 1);
}
static bool curves_equals(const void *a, const void *b)
{
// ghash requires we invert here
return !BKE_curvemapping_equals(a, b);
}
static unsigned int curve_hash(const void *c)
{
return BKE_curvemapping_calc_hash(c);
}
CurveMappingCache *BKE_curvemapping_cache_create()
{
CurveMappingCache *ret = MEM_callocN(sizeof(*ret), "CurveMappingCache");
ret->gh = BLI_ghash_new(curve_hash, curves_equals, "CurveMappingCache ghash");
return ret;
}
void BKE_curvemapping_cache_aquire(CurveMappingCache *cache, CurveMapping *curve)
{
curve->cache_users++;
}
ATTR_NO_OPT void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve)
{
curve->cache_users--;
if ((curve->flag & CUMA_PART_OF_CACHE) && curve->cache_users < 0) {
if (!BLI_ghash_remove(cache->gh, curve, NULL, NULL)) {
printf("error, curve was not in cache! %p\n", curve);
}
BKE_curvemapping_free(curve);
}
}
bool BKE_curvemapping_in_cache(CurveMapping *curve)
{
return curve->flag & CUMA_PART_OF_CACHE;
}
ATTR_NO_OPT CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
CurveMapping *curve,
bool free_input)
{
void **key, **val;
CurveMapping *lookup;
if (BLI_ghash_ensure_p_ex(cache->gh, curve, &key, &val)) {
lookup = *key;
if (free_input && lookup != curve && !(curve->flag & CUMA_PART_OF_CACHE)) {
BKE_curvemapping_free(curve);
}
lookup->cache_users++;
return lookup;
}
printf("adding curve key %d\n", BKE_curvemapping_calc_hash(curve));
CurveMapping *curve2 = BKE_curvemapping_copy(curve);
*key = curve2;
*val = curve2;
curve2->flag |= CUMA_PART_OF_CACHE;
#if 1
printf("%d %d",
(int)BKE_curvemapping_calc_hash(curve2),
(int)BKE_curvemapping_equals(curve, curve2));
CurveMap *cu = curve2->cm;
printf("{\n");
for (int i = 0; i < cu->totpoint; i++) {
printf(" %f, %f\n", cu->curve[i].x, cu->curve[i].y);
}
printf("}\n");
#endif
if (free_input && !(curve->flag & CUMA_PART_OF_CACHE)) {
BKE_curvemapping_free(curve);
}
curve2->cache_users = 1;
return curve2;
}
void BKE_curvemapping_cache_free(CurveMappingCache *cache)
{
GHashIterator gi;
GHASH_ITER (gi, cache->gh) {
CurveMapping *curve = BLI_ghashIterator_getKey(&gi);
BKE_curvemapping_free(curve);
}
BLI_ghash_free(cache->gh, NULL, NULL);
MEM_freeN(cache);
}
static CurveMappingCache *the_global_cache = NULL;
void BKE_curvemapping_cache_exit()
{
if (the_global_cache) {
BKE_curvemapping_cache_free(the_global_cache);
}
}
CurveMappingCache *BKE_curvemapping_cache_global()
{
if (!the_global_cache) {
the_global_cache = BKE_curvemapping_cache_create();
}
return the_global_cache;
}
// releases a curve if it's in the cache, otherwise frees it
ATTR_NO_OPT void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache,
CurveMapping *curve)
{
if (curve->flag & CUMA_PART_OF_CACHE) {
BKE_curvemapping_cache_release(cache, curve);
}
else {
BKE_curvemapping_free(curve);
}
#if 0
CurveMap *cu1 = curve->cm;
CurveMap *cu2 = curve->cm;
if (cu1->totpoint != cu2->totpoint) {
printf("%s: curvemapping cache error; totpoint differed: %d %d\n",
__func__,
cu1->totpoint,
cu2->totpoint);
return;
}
printf("curve tables: {\n");
for (int i = 0; i < cu1->totpoint; i++) {
CurveMapPoint *p1 = cu1->curve + i;
CurveMapPoint *p2 = cu1->curve + i;
printf(" %f, %f, | %f, %f\n", p1->x, p1->y, p2->x, p2->y);
}
printf("}\n");
#endif
}

View File

@@ -35,6 +35,7 @@
#include "DNA_meshdata_types.h"
#include "BLI_bitmap.h"
#include "BLI_compiler_attrs.h"
#include "BLI_endian_switch.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
@@ -73,6 +74,32 @@ BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "siz
static CLG_LogRef LOG = {"bke.customdata"};
bool CustomData_layout_is_same(const CustomData *_a, const CustomData *_b)
{
CustomData a = *_a;
CustomData b = *_b;
a.layers = b.layers = NULL;
a.pool = b.pool = NULL;
if (memcmp((void *)&a, (void *)&b, sizeof(CustomData)) != 0) {
return false;
}
for (int i = 0; i < a.totlayer; i++) {
CustomDataLayer cla = _a->layers[i];
CustomDataLayer clb = _b->layers[i];
cla.data = clb.data = NULL;
if (memcmp((void *)&cla, (void *)&clb, sizeof(CustomDataLayer)) != 0) {
return false;
}
}
return true;
}
/** Update mask_dst with layers defined in mask_src (equivalent to a bitwise OR). */
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
const CustomData_MeshMasks *mask_src)
@@ -1475,6 +1502,93 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
static void layerDynTopoVert_copy(const void *source, void *dest, int count)
{
const MDynTopoVert *mv = (MDynTopoVert *)dest;
memcpy(dest, source, count * sizeof(MDynTopoVert));
}
static void layerDynTopoVert_interp(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
float co[3], no[3], origmask, color[4];
MDynTopoVert *mv = (MDynTopoVert *)dest;
float totweight = 0.0f;
if (count == 0) {
memset(mv, 0, sizeof(*mv));
return;
}
zero_v3(co);
zero_v3(no);
origmask = 0.0f;
zero_v4(color);
for (int i = 0; i < count; i++) {
MDynTopoVert *mv2 = (MDynTopoVert *)sources[i];
float w;
if (i == 0) { // copy flag from first source
mv->flag = mv2->flag;
mv->stroke_id = mv2->stroke_id;
}
if (sub_weights) {
w = sub_weights[i];
}
else {
w = 1.0f;
}
madd_v3_v3fl(co, mv2->origco, w);
madd_v3_v3fl(no, mv2->origno, w);
madd_v4_v4fl(color, mv2->origcolor, w);
origmask += mv2->origmask * w;
totweight += w;
}
float mul = 1.0f / totweight;
mul_v3_fl(co, mul);
normalize_v3(no);
mul_v4_fl(color, mul);
origmask *= mul;
copy_v3_v3(mv->origco, co);
copy_v3_v3(mv->origno, no);
copy_v4_v4(mv->origcolor, color);
mv->origmask = origmask;
}
static void layerCopy_noop(const void *UNUSED(source), void *UNUSED(dest), int UNUSED(count))
{
// do nothing
}
static void layerInterp_noop(const void **UNUSED(sources),
const float *UNUSED(weights),
const float *UNUSED(sub_weights),
int UNUSED(count),
void *UNUSED(dest))
{
// do nothing
}
static void layerDefault_mesh_id(void *data, int count)
{
int *val = (int *)data;
for (int i = 0; i < count; i++) {
// val[i] = -1;
val[i] = 0;
}
}
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -1856,7 +1970,24 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
NULL,
NULL,
NULL},
};
/* 51 CD_DYNTOPO_VERT */
{sizeof(MDynTopoVert),
"MDynTopoVert",
1,
NULL, // flag singleton layer
layerDynTopoVert_copy,
NULL,
layerDynTopoVert_interp},
/*52 CD_MESH_ID */
{sizeof(unsigned int),
"MIntProperty",
1,
NULL, // flag singleton layer
layerCopy_propInt,
NULL,
layerInterp_noop,
NULL,
layerDefault_mesh_id}};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert",
@@ -1912,62 +2043,65 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDPropFloat3",
"CDPropFloat2",
"CDPropBoolean",
};
"CDDyntopoVert"};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT,
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT,
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_MESH_ID,
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_MESH_ID,
.fmask = 0,
.lmask = CD_MASK_MLOOP,
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP,
.lmask = CD_MASK_MLOOP | CD_MASK_MESH_ID,
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_MESH_ID,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
.fmask = 0,
.lmask = CD_MASK_MLOOP,
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
.lmask = CD_MASK_MLOOP | CD_MASK_MESH_ID,
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
};
const CustomData_MeshMasks CD_MASK_MESH = {
.vmask = (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
.emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
.emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
.fmask = 0,
.lmask = (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL |
CD_MASK_MESH_ID),
.pmask = (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
};
const CustomData_MeshMasks CD_MASK_EDITMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
.emask = (CD_MASK_PROP_ALL),
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
.emask = (CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
.pmask = (CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
.pmask = (CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
.vmask = (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL |
CD_MASK_PROP_COLOR),
.emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
.emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
.fmask = (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
.lmask = (CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL |
CD_MASK_MESH_ID), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
.pmask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
};
const CustomData_MeshMasks CD_MASK_BMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
.emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR |
CD_MASK_DYNTOPO_VERT | CD_MASK_MESH_ID),
.emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL |
CD_MASK_MESH_ID),
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
.pmask = (CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
};
/**
* cover values copied by #mesh_loops_to_tessdata
@@ -2009,6 +2143,11 @@ static const LayerTypeInfo *layerType_getInfo(int type)
return &LAYERTYPEINFO[type];
}
int CustomData_get_elem_size(CustomDataLayer *layer)
{
return layerType_getInfo(layer->type)->size;
}
static const char *layerType_getName(int type)
{
if (type < 0 || type >= CD_NUMTYPES) {
@@ -2093,6 +2232,26 @@ static bool customdata_typemap_is_valid(const CustomData *data)
}
#endif
/* copies all customdata layers without allocating data,
* and without respect to type masks or NO_COPY/etc flags*/
void CustomData_copy_all_layout(const struct CustomData *source, struct CustomData *dest)
{
*dest = *source;
if (dest->pool) {
dest->pool = NULL;
}
if (source->layers) {
dest->layers = MEM_mallocN(sizeof(*dest->layers) * source->totlayer, __func__);
for (int i = 0; i < source->totlayer; i++) {
dest->layers[i] = source->layers[i];
dest->layers[i].data = NULL;
}
}
}
bool CustomData_merge(const struct CustomData *source,
struct CustomData *dest,
CustomDataMask mask,
@@ -2285,11 +2444,45 @@ static void customData_update_offsets(CustomData *data)
const LayerTypeInfo *typeInfo;
int offset = 0;
for (int i = 0; i < data->totlayer; i++) {
typeInfo = layerType_getInfo(data->layers[i].type);
// sort by alignment
int aligns[] = {16, 8, 12, 6, 4, 2, 1};
BLI_bitmap *donemap = BLI_BITMAP_NEW_ALLOCA(data->totlayer);
data->layers[i].offset = offset;
offset += typeInfo->size;
// do large structs first
for (int j = 0; j < data->totlayer; j++) {
typeInfo = layerType_getInfo(data->layers[j].type);
if (typeInfo->size > 16 || typeInfo->size == 10) {
int size = (int)typeInfo->size;
BLI_BITMAP_SET(donemap, j, true);
// align to 8-byte boundary
if (size & 7) {
size += 8 - (size & 7);
}
data->layers[j].offset = offset;
offset += size;
}
}
for (int i = 0; i < ARRAY_SIZE(aligns) + 1; i++) {
for (int j = 0; j < data->totlayer; j++) {
if (BLI_BITMAP_TEST(donemap, j)) {
continue;
}
typeInfo = layerType_getInfo(data->layers[j].type);
if (i < ARRAY_SIZE(aligns) && typeInfo->size != aligns[i]) {
continue;
}
BLI_BITMAP_SET(donemap, j, true);
data->layers[j].offset = offset;
offset += typeInfo->size;
}
}
data->totsize = offset;
@@ -2883,6 +3076,24 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type)
return (layer->flag & CD_FLAG_NOFREE) != 0;
}
void CustomData_unmark_temporary_nocopy(CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].flag & CD_FLAG_TEMPORARY) {
data->layers[i].flag &= ~CD_FLAG_NOCOPY;
}
}
}
void CustomData_mark_temporary_nocopy(CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].flag & CD_FLAG_TEMPORARY) {
data->layers[i].flag |= CD_FLAG_NOCOPY;
}
}
}
void CustomData_free_temporary(CustomData *data, int totelem)
{
int i, j;
@@ -3739,6 +3950,12 @@ static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n
int offset = data->layers[n].offset;
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
/* can't allow this to be called on CD_MESH_ID */
if (data->layers[n].type == CD_MESH_ID) {
return;
}
if (typeInfo->set_default) {
typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
}
@@ -3758,6 +3975,95 @@ void CustomData_bmesh_set_default(CustomData *data, void **block)
}
}
void CustomData_bmesh_swap_data_simple(CustomData *data, void **block1, void **block2)
{
int cd_id = data->typemap[CD_MESH_ID];
cd_id = cd_id >= 0 ? data->layers[cd_id].offset : -1;
void *tmp = *block1;
*block1 = *block2;
*block2 = tmp;
// unswap ids if they exist
if (cd_id != -1 && *block1 && *block2) {
int *id1 = (int *)(((char *)*block1) + cd_id);
int *id2 = (int *)(((char *)*block2) + cd_id);
tmp = *id1;
*id1 = *id2;
*id2 = tmp;
}
}
void CustomData_bmesh_swap_data(CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block)
{
int src_i = 0;
int dest_i = 0;
int dest_i_start = 0;
if (*dest_block == NULL) {
CustomData_bmesh_alloc_block(dest, dest_block);
if (*dest_block) {
memset(*dest_block, 0, dest->totsize);
CustomData_bmesh_set_default(dest, dest_block);
}
}
for (src_i = 0; src_i < source->totlayer; src_i++) {
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
*/
while (dest_i_start < dest->totlayer &&
dest->layers[dest_i_start].type < source->layers[src_i].type) {
dest_i_start++;
}
if (source->layers[src_i].type == CD_MESH_ID) {
// do not swap ids
continue;
}
/* if there are no more dest layers, we're done */
if (dest_i_start >= dest->totlayer) {
return;
}
dest_i = dest_i_start;
while (dest_i < dest->totlayer && dest->layers[dest_i].type == source->layers[src_i].type) {
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type &&
STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
const uint size = typeInfo->size;
// swap data
char *bsrc = (char *)src_data;
char *bdst = (char *)dest_data;
for (int j = 0; j < size; j++) {
char t = *bsrc;
*bsrc = *bdst;
*bdst = t;
bsrc++;
bdst++;
}
break;
}
dest_i++;
}
}
}
void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
CustomData *dest,
void *src_block,
@@ -3775,50 +4081,59 @@ void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
}
}
for (int dest_i = 0; dest_i < dest->totlayer; dest_i++) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
}
/* copies a layer at a time */
int dest_i = 0;
int dest_i_start = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
*/
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
while (dest_i_start < dest->totlayer &&
dest->layers[dest_i_start].type < source->layers[src_i].type) {
dest_i_start++;
}
/* if there are no more dest layers, we're done */
if (dest_i >= dest->totlayer) {
if (dest_i_start >= dest->totlayer) {
return;
}
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type &&
STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
if (typeInfo->copy) {
typeInfo->copy(src_data, dest_data, 1);
}
else {
memcpy(dest_data, src_data, typeInfo->size);
int dest_i = dest_i_start;
/*Previously this code was only checking one source layer against one destination.
Now it scans all the layers of that type. - joeedh
*/
while (dest_i < dest->totlayer && dest->layers[dest_i].type == source->layers[src_i].type) {
/* if we found a matching layer, copy the data */
if (STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
if (dest->layers[dest_i].flag & CD_FLAG_ELEM_NOCOPY) {
break;
}
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
if (typeInfo->copy) {
typeInfo->copy(src_data, dest_data, 1);
}
else {
memcpy(dest_data, src_data, typeInfo->size);
}
}
break;
}
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
* increment dest_i
*/
dest_i++;
}
}
while (dest_i < dest->totlayer) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
}
}
void CustomData_bmesh_copy_data(const CustomData *source,

View File

@@ -150,6 +150,7 @@ bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types,
case DT_TYPE_UV:
ret = true;
break;
case DT_TYPE_PROPCOL:
case DT_TYPE_VCOL:
*r_advanced_mixing = true;
*r_threshold = true;
@@ -230,12 +231,12 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
return CD_FAKE_SHARP;
case DT_TYPE_FREESTYLE_FACE:
return CD_FREESTYLE_FACE;
case DT_TYPE_VCOL:
return CD_MLOOPCOL;
case DT_TYPE_LNOR:
return CD_FAKE_LNOR;
case DT_TYPE_PROPCOL:
return CD_PROP_COLOR;
default:
BLI_assert(0);
}
@@ -253,6 +254,8 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
return DT_MULTILAYER_INDEX_UV;
case DT_TYPE_VCOL:
return DT_MULTILAYER_INDEX_VCOL;
case DT_TYPE_PROPCOL:
return DT_MULTILAYER_INDEX_PROPCOL;
default:
return DT_MULTILAYER_INDEX_INVALID;
}

File diff suppressed because it is too large Load Diff

View File

@@ -184,7 +184,7 @@ static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *pro
const ID *id = prop->data.pointer;
if (id != NULL) {
STR_APPEND_STR("bpy.data.");
STR_APPEND_STR(BKE_idtype_idcode_to_name_plural(GS(id->name)));
STR_APPEND_STR(BKE_idtype_idcode_to_name_plural((short)GS(id->name)));
STR_APPEND_STR("[");
STR_APPEND_STR_QUOTE(id->name + 2);
STR_APPEND_STR("]");

View File

@@ -674,7 +674,7 @@ ID *BKE_id_copy(Main *bmain, const ID *id)
* Invokes the appropriate copy method for the block and returns the result in
* newid, unless test. Returns true if the block can be copied.
*/
ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags)
ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const uint duplicate_flags)
{
if (id == NULL) {
return id;

View File

@@ -1123,14 +1123,15 @@ Mesh *BKE_mesh_copy_for_eval(const Mesh *source, bool reference)
return result;
}
BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me,
BMesh *BKE_mesh_to_bmesh_ex(const Object *ob,
const Mesh *me,
const struct BMeshCreateParams *create_params,
const struct BMeshFromMeshParams *convert_params)
{
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
BMesh *bm = BM_mesh_create(&allocsize, create_params);
BM_mesh_bm_from_me(bm, me, convert_params);
BM_mesh_bm_from_me((Object *)ob, bm, me, convert_params);
return bm;
}
@@ -1140,7 +1141,8 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me,
const bool add_key_index,
const struct BMeshCreateParams *params)
{
return BKE_mesh_to_bmesh_ex(me,
return BKE_mesh_to_bmesh_ex(ob,
me,
params,
&(struct BMeshFromMeshParams){
.calc_face_normal = false,
@@ -1156,8 +1158,13 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
{
BLI_assert(params->calc_object_remap == false);
Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
BM_mesh_bm_to_me(NULL, bm, mesh, params);
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
BM_mesh_bm_to_me(NULL, NULL, bm, mesh, params);
if (me_settings) {
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
}
return mesh;
}

View File

@@ -67,6 +67,12 @@ class FairingContext {
/* Get the other vertex index for a loop. */
virtual int other_vertex_index_from_loop(const int loop, const uint v) = 0;
virtual float *vertex_deformation_co_get(const int v) = 0;
virtual void vertex_deformation_co_set(const int v, const float co[3]) = 0;
virtual int vertex_index_from_loop(const int loop) = 0;
virtual float cotangent_loop_weight_get(const int loop) = 0;
int vertex_count_get()
{
return totvert_;
@@ -74,7 +80,7 @@ class FairingContext {
int loop_count_get()
{
return totvert_;
return totloop_;
}
MeshElemMap *vertex_loop_map_get(const int v)
@@ -82,11 +88,6 @@ class FairingContext {
return &vlmap_[v];
}
float *vertex_deformation_co_get(const int v)
{
return co_[v];
}
virtual ~FairingContext() = default;
void fair_vertices(bool *affected,
@@ -99,8 +100,6 @@ class FairingContext {
}
protected:
Vector<float *> co_;
int totvert_;
int totloop_;
@@ -123,8 +122,10 @@ class FairingContext {
EIG_linear_solver_matrix_add(solver, i, j, -multiplier);
return;
}
const float *co = vertex_deformation_co_get(v);
for (int j = 0; j < 3; j++) {
EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co_[v][j]);
EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co[j]);
}
return;
}
@@ -191,9 +192,11 @@ class FairingContext {
for (auto item : vert_col_map.items()) {
const int v = item.key;
const int col = item.value;
float co[3];
for (int j = 0; j < 3; j++) {
co_[v][j] = EIG_linear_solver_variable_get(solver, j, col);
co[j] = EIG_linear_solver_variable_get(solver, j, col);
}
vertex_deformation_co_set(v, co);
}
/* Free solver data */
@@ -213,26 +216,33 @@ class MeshFairingContext : public FairingContext {
mloop_ = mesh->mloop;
BKE_mesh_vert_loop_map_create(&vlmap_,
&vlmap_mem_,
mesh->mvert,
mesh->medge,
mesh->mpoly,
mesh->mloop,
mesh->totvert,
mesh->totpoly,
mesh->totloop,
false);
BKE_mesh_edge_loop_map_create(&elmap_,
&elmap_mem_,
mesh->medge,
mesh->totedge,
mesh->mpoly,
mesh->totpoly,
mesh->mloop,
mesh->totloop);
/* Deformation coords. */
co_.reserve(mesh->totvert);
if (deform_mverts) {
for (int i = 0; i < mesh->totvert; i++) {
co_[i] = deform_mverts[i].co;
}
deform_mvert_ = deform_mverts;
}
else {
for (int i = 0; i < mesh->totvert; i++) {
co_[i] = mesh->mvert[i].co;
}
deform_mvert_ = mesh->mvert;
}
loop_to_poly_map_.reserve(mesh->totloop);
loop_to_poly_map_.resize(mesh->totloop);
for (int i = 0; i < mesh->totpoly; i++) {
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
loop_to_poly_map_[l + mesh->mpoly[i].loopstart] = i;
@@ -244,6 +254,18 @@ class MeshFairingContext : public FairingContext {
{
MEM_SAFE_FREE(vlmap_);
MEM_SAFE_FREE(vlmap_mem_);
MEM_SAFE_FREE(elmap_);
MEM_SAFE_FREE(elmap_mem_);
}
float *vertex_deformation_co_get(const int v)
{
return deform_mvert_[v].co;
}
void vertex_deformation_co_set(const int v, const float co[3])
{
copy_v3_v3(deform_mvert_[v].co, co);
}
void adjacents_coords_from_loop(const int loop,
@@ -253,8 +275,8 @@ class MeshFairingContext : public FairingContext {
const int vert = mloop_[loop].v;
const MPoly *p = &mpoly_[loop_to_poly_map_[loop]];
const int corner = poly_find_loop_from_vert(p, &mloop_[p->loopstart], vert);
copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v]);
copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v]);
copy_v3_v3(r_adj_next, deform_mvert_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v].co);
copy_v3_v3(r_adj_prev, deform_mvert_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v].co);
}
int other_vertex_index_from_loop(const int loop, const uint v) override
@@ -266,12 +288,28 @@ class MeshFairingContext : public FairingContext {
return e->v1;
}
int vertex_index_from_loop(const int loop) override
{
return mloop_[loop].v;
}
float cotangent_loop_weight_get(const int UNUSED(loop)) override
{
/* TODO: Implement cotangent loop weights for meshes. */
return 1.0f;
}
protected:
Mesh *mesh_;
MLoop *mloop_;
MPoly *mpoly_;
MEdge *medge_;
Vector<int> loop_to_poly_map_;
MVert *deform_mvert_;
MeshElemMap *elmap_;
int *elmap_mem_;
};
class BMeshFairingContext : public FairingContext {
@@ -285,14 +323,7 @@ class BMeshFairingContext : public FairingContext {
BM_mesh_elem_table_ensure(bm, BM_VERT);
BM_mesh_elem_index_ensure(bm, BM_LOOP);
/* Deformation coords. */
co_.reserve(bm->totvert);
for (int i = 0; i < bm->totvert; i++) {
BMVert *v = BM_vert_at_index(bm, i);
co_[i] = v->co;
}
bmloop_.reserve(bm->totloop);
bmloop_.resize(bm->totloop);
vlmap_ = (MeshElemMap *)MEM_calloc_arrayN(sizeof(MeshElemMap), bm->totvert, "bmesh loop map");
vlmap_mem_ = (int *)MEM_malloc_arrayN(sizeof(int), bm->totloop, "bmesh loop map mempool");
@@ -307,6 +338,7 @@ class BMeshFairingContext : public FairingContext {
int loop_count = 0;
const int vert_index = BM_elem_index_get(v);
vlmap_[vert_index].indices = &vlmap_mem_[index_iter];
BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) {
const int loop_index = BM_elem_index_get(l);
bmloop_[loop_index] = l;
@@ -324,6 +356,16 @@ class BMeshFairingContext : public FairingContext {
MEM_SAFE_FREE(vlmap_mem_);
}
float *vertex_deformation_co_get(const int v)
{
return BM_vert_at_index(bm, v)->co;
}
void vertex_deformation_co_set(const int v, const float co[3])
{
copy_v3_v3(BM_vert_at_index(bm, v)->co, co);
}
void adjacents_coords_from_loop(const int loop,
float r_adj_next[3],
float r_adj_prev[3]) override
@@ -340,6 +382,47 @@ class BMeshFairingContext : public FairingContext {
return BM_elem_index_get(bm_other_vert);
}
int vertex_index_from_loop(const int loop) override
{
return BM_elem_index_get(bmloop_[loop]->v);
}
float cotangent_loop_weight_get(const int loop) override
{
return 1.0f;
/* TODO: enable this when it works. */
BMLoop *l = bmloop_[loop];
float *co_c[2];
int co_c_count = 1;
float *co_a = l->v->co;
float *co_b = l->next->v->co;
co_c[0] = l->prev->v->co;
if (!BM_edge_is_boundary(l->e)) {
co_c_count = 2;
co_c[1] = l->radial_next->next->next->v->co;
}
float weight = 0.0f;
for (int c = 0; c < co_c_count; c++) {
float v1[3];
float v2[3];
sub_v3_v3v3(v1, co_a, co_c[c]);
sub_v3_v3v3(v2, co_b, co_c[c]);
const float angle = angle_v3v3(v1, v2);
const float tangent = tan(angle);
if (tangent != 0) {
weight += 1.0f / tangent;
}
else {
weight += 1e-4;
}
}
weight *= 0.5f;
return weight;
}
protected:
BMesh *bm;
Vector<BMLoop *> bmloop_;
@@ -350,25 +433,35 @@ class UniformVertexWeight : public VertexWeight {
UniformVertexWeight(FairingContext *fairing_context)
{
const int totvert = fairing_context->vertex_count_get();
vertex_weights_.reserve(totvert);
fairing_context_ = fairing_context;
vertex_weights_.resize(totvert);
cached_.resize(totvert);
for (int i = 0; i < totvert; i++) {
const int tot_loop = fairing_context->vertex_loop_map_get(i)->count;
if (tot_loop != 0) {
vertex_weights_[i] = 1.0f / tot_loop;
}
else {
vertex_weights_[i] = FLT_MAX;
}
cached_[i] = false;
}
}
float weight_at_index(const int index) override
{
if (!cached_[index]) {
vertex_weights_[index] = uniform_weight_at_index(index);
cached_[index] = true;
}
return vertex_weights_[index];
}
private:
float uniform_weight_at_index(const int index)
{
const int tot_loop = fairing_context_->vertex_loop_map_get(index)->count;
if (tot_loop != 0) {
return 1.0f / tot_loop;
}
return FLT_MAX;
}
Vector<float> vertex_weights_;
Vector<bool> cached_;
FairingContext *fairing_context_;
};
class VoronoiVertexWeight : public VertexWeight {
@@ -376,52 +469,65 @@ class VoronoiVertexWeight : public VertexWeight {
public:
VoronoiVertexWeight(FairingContext *fairing_context)
{
fairing_context_ = fairing_context;
const int totvert = fairing_context->vertex_count_get();
vertex_weights_.reserve(totvert);
vertex_weights_.resize(totvert);
cached_.resize(totvert);
for (int i = 0; i < totvert; i++) {
float area = 0.0f;
float a[3];
copy_v3_v3(a, fairing_context->vertex_deformation_co_get(i));
const float acute_threshold = M_PI_2;
MeshElemMap *vlmap_elem = fairing_context->vertex_loop_map_get(i);
for (int l = 0; l < vlmap_elem->count; l++) {
const int l_index = vlmap_elem->indices[l];
float b[3], c[3], d[3];
fairing_context->adjacents_coords_from_loop(l_index, b, c);
if (angle_v3v3v3(c, fairing_context->vertex_deformation_co_get(i), b) < acute_threshold) {
calc_circumcenter(d, a, b, c);
}
else {
add_v3_v3v3(d, b, c);
mul_v3_fl(d, 0.5f);
}
float t[3];
add_v3_v3v3(t, a, b);
mul_v3_fl(t, 0.5f);
area += area_tri_v3(a, t, d);
add_v3_v3v3(t, a, c);
mul_v3_fl(t, 0.5f);
area += area_tri_v3(a, d, t);
}
vertex_weights_[i] = area != 0.0f ? 1.0f / area : 1e12;
cached_[i] = false;
}
}
float weight_at_index(const int index) override
{
if (!cached_[index]) {
vertex_weights_[index] = voronoi_weight_at_index(index);
cached_[index] = true;
}
return vertex_weights_[index];
}
private:
Vector<float> vertex_weights_;
Vector<bool> cached_;
FairingContext *fairing_context_;
float voronoi_weight_at_index(const int index)
{
float area = 0.0f;
float a[3];
copy_v3_v3(a, fairing_context_->vertex_deformation_co_get(index));
const float acute_threshold = M_PI_2;
MeshElemMap *vlmap_elem = fairing_context_->vertex_loop_map_get(index);
for (int l = 0; l < vlmap_elem->count; l++) {
const int l_index = vlmap_elem->indices[l];
float b[3], c[3], d[3];
fairing_context_->adjacents_coords_from_loop(l_index, b, c);
if (angle_v3v3v3(c, fairing_context_->vertex_deformation_co_get(index), b) <
acute_threshold) {
calc_circumcenter(d, a, b, c);
}
else {
add_v3_v3v3(d, b, c);
mul_v3_fl(d, 0.5f);
}
float t[3];
add_v3_v3v3(t, a, b);
mul_v3_fl(t, 0.5f);
area += area_tri_v3(a, t, d);
add_v3_v3v3(t, a, c);
mul_v3_fl(t, 0.5f);
area += area_tri_v3(a, d, t);
}
return area != 0.0f ? 1.0f / area : 1e12;
}
void calc_circumcenter(float r[3], const float a[3], const float b[3], const float c[3])
{
@@ -462,6 +568,35 @@ class UniformLoopWeight : public LoopWeight {
}
};
class CotangentLoopWeight : public LoopWeight {
public:
CotangentLoopWeight(FairingContext *fairing_context)
{
const int totloop = fairing_context->loop_count_get();
fairing_context_ = fairing_context;
loop_weights_.resize(totloop);
cached_.resize(totloop);
for (int i = 0; i < totloop; i++) {
cached_[i] = false;
}
}
~CotangentLoopWeight() = default;
float weight_at_index(const int index) override
{
if (!cached_[index]) {
loop_weights_[index] = fairing_context_->cotangent_loop_weight_get(index);
cached_[index] = true;
}
return loop_weights_[index];
}
private:
Vector<float> loop_weights_;
Vector<bool> cached_;
FairingContext *fairing_context_;
};
static void prefair_and_fair_vertices(FairingContext *fairing_context,
bool *affected_vertices,
const eMeshFairingDepth depth)
@@ -469,18 +604,23 @@ static void prefair_and_fair_vertices(FairingContext *fairing_context,
/* Prefair. */
UniformVertexWeight *uniform_vertex_weights = new UniformVertexWeight(fairing_context);
UniformLoopWeight *uniform_loop_weights = new UniformLoopWeight();
fairing_context->fair_vertices(
affected_vertices, depth, uniform_vertex_weights, uniform_loop_weights);
fairing_context->fair_vertices(affected_vertices,
MESH_FAIRING_DEPTH_POSITION,
uniform_vertex_weights,
uniform_loop_weights);
delete uniform_vertex_weights;
delete uniform_loop_weights;
/* Fair. */
VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context);
/* TODO: Implement cotangent loop weights. */
fairing_context->fair_vertices(
affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights);
CotangentLoopWeight *cotangent_loop_weights = new CotangentLoopWeight(fairing_context);
fairing_context->fair_vertices(
affected_vertices, depth, voronoi_vertex_weights, cotangent_loop_weights);
delete uniform_loop_weights;
delete voronoi_vertex_weights;
delete cotangent_loop_weights;
}
void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh,

View File

@@ -26,12 +26,16 @@
#include "DNA_meshdata_types.h"
#include "DNA_vec_types.h"
#include "BLI_alloca.h"
#include "BLI_bitmap.h"
#include "BLI_buffer.h"
#include "BLI_math.h"
#include "BLI_sort.h"
#include "BLI_sort_utils.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BLI_memarena.h"
@@ -194,6 +198,270 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
}
}
typedef struct DiskCycleSortData {
float th;
int i, elem;
const float *co;
} DiskCycleSortData;
/**
* Calculate a normal from a vertex cloud.
*
* \note We could make a higher quality version that takes all vertices into account.
* Currently it finds 4 outer most points returning its normal.
*/
static void calc_cloud_normal(DiskCycleSortData *varr,
int varr_len,
float r_normal[3],
float r_center[3],
int *r_index_tangent)
{
const float varr_len_inv = 1.0f / (float)varr_len;
/* Get the center point and collect vector array since we loop over these a lot. */
float center[3] = {0.0f, 0.0f, 0.0f};
for (int i = 0; i < varr_len; i++) {
madd_v3_v3fl(center, varr[i].co, varr_len_inv);
}
/* Find the 'co_a' point from center. */
int co_a_index = 0;
const float *co_a = NULL;
{
float dist_sq_max = -1.0f;
for (int i = 0; i < varr_len; i++) {
const float dist_sq_test = len_squared_v3v3(varr[i].co, center);
if (!(dist_sq_test <= dist_sq_max)) {
co_a = varr[i].co;
co_a_index = i;
dist_sq_max = dist_sq_test;
}
}
}
float dir_a[3];
sub_v3_v3v3(dir_a, co_a, center);
normalize_v3(dir_a);
const float *co_b = NULL;
float dir_b[3] = {0.0f, 0.0f, 0.0f};
{
float dist_sq_max = -1.0f;
for (int i = 0; i < varr_len; i++) {
if (varr[i].co == co_a) {
continue;
}
float dir_test[3];
sub_v3_v3v3(dir_test, varr[i].co, center);
project_plane_normalized_v3_v3v3(dir_test, dir_test, dir_a);
const float dist_sq_test = len_squared_v3(dir_test);
if (!(dist_sq_test <= dist_sq_max)) {
co_b = varr[i].co;
dist_sq_max = dist_sq_test;
copy_v3_v3(dir_b, dir_test);
}
}
}
if (varr_len <= 3) {
normal_tri_v3(r_normal, center, co_a, co_b);
goto finally;
}
normalize_v3(dir_b);
const float *co_a_opposite = NULL;
const float *co_b_opposite = NULL;
{
float dot_a_min = FLT_MAX;
float dot_b_min = FLT_MAX;
for (int i = 0; i < varr_len; i++) {
const float *co_test = varr[i].co;
float dot_test;
if (co_test != co_a) {
dot_test = dot_v3v3(dir_a, co_test);
if (dot_test < dot_a_min) {
dot_a_min = dot_test;
co_a_opposite = co_test;
}
}
if (co_test != co_b) {
dot_test = dot_v3v3(dir_b, co_test);
if (dot_test < dot_b_min) {
dot_b_min = dot_test;
co_b_opposite = co_test;
}
}
}
}
normal_quad_v3(r_normal, co_a, co_b, co_a_opposite, co_b_opposite);
finally:
if (r_center != NULL) {
copy_v3_v3(r_center, center);
}
if (r_index_tangent != NULL) {
*r_index_tangent = co_a_index;
}
}
static bool build_disk_cycle_face(const MPoly *mpoly,
const MLoop *mloop,
const MEdge *medge,
const MVert *mvert,
int vertex_i,
MeshElemMap *elem,
int *doneset,
int *donelen,
DiskCycleSortData *sortdata)
{
*donelen = 0;
for (int i = 0; i < elem->count; i++) {
const MPoly *mp = mpoly + elem->indices[i];
unsigned int loops[2];
if (poly_get_adj_loops_from_vert(mp, mloop, (unsigned int)vertex_i, loops)) {
for (int j = 0; j < 2; j++) {
if (loops[j] != (unsigned int)vertex_i) {
bool ok = true;
for (int k = 0; k < *donelen; k++) {
if ((unsigned int)doneset[k] == loops[j]) {
ok = false;
}
}
if (ok) {
doneset[*donelen] = (int)loops[j];
sortdata[*donelen].elem = elem->indices[i];
sortdata[*donelen].co = mvert[loops[j]].co;
(*donelen)++;
break;
}
}
}
}
else {
printf("sort error in sort_disk_cycle_face\n");
continue;
}
}
return *donelen == elem->count;
}
static bool build_disk_cycle_loop(const MPoly *mpoly,
const MLoop *mloop,
const MEdge *medge,
const MVert *mvert,
int vertex_i,
MeshElemMap *elem,
int *doneset,
int *donelen,
DiskCycleSortData *sortdata)
{
*donelen = 0;
for (int i = 0; i < elem->count; i++) {
int l1 = elem->indices[i];
const MLoop *ml = mloop + l1;
const MEdge *me = medge + ml->e;
unsigned int v = me->v1 != (unsigned int)vertex_i ? me->v1 : me->v2;
sortdata[i].co = mvert[v].co;
sortdata[i].elem = l1;
sortdata[i].i = i;
(*donelen)++;
}
return *donelen == elem->count;
}
static bool build_disk_cycle_edge(const MPoly *mpoly,
const MLoop *mloop,
const MEdge *medge,
const MVert *mvert,
int vertex_i,
MeshElemMap *elem,
int *doneset,
int *donelen,
DiskCycleSortData *sortdata)
{
*donelen = 0;
for (int i = 0; i < elem->count; i++) {
const MEdge *me = medge + elem->indices[i];
unsigned int v = me->v1 != (unsigned int)vertex_i ? me->v1 : me->v2;
sortdata[i].co = mvert[v].co;
sortdata[i].elem = elem->indices[i];
sortdata[i].i = i;
(*donelen)++;
}
return *donelen == elem->count;
}
static bool sort_disk_cycle(const MPoly *mpoly,
const MLoop *mloop,
const MEdge *medge,
const MVert *mvert,
int vertex_i,
MeshElemMap *elem,
bool is_loops,
bool is_edges)
{
DiskCycleSortData *sortdata = BLI_array_alloca(sortdata, (unsigned int)elem->count);
int *doneset = BLI_array_alloca(doneset, (unsigned int)elem->count);
int donelen = 0;
if (is_loops) {
if (!build_disk_cycle_face(
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
return false;
}
}
else if (is_edges) {
if (!build_disk_cycle_edge(
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
return false;
}
}
else {
if (!build_disk_cycle_loop(
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
return false;
}
}
float no[3], cent[3];
int vadj;
calc_cloud_normal(sortdata, donelen, no, cent, &vadj);
for (int i = 0; i < donelen; i++) {
sortdata[i].th = angle_signed_on_axis_v3v3v3_v3(sortdata[vadj].co, cent, sortdata[i].co, no);
}
qsort((void *)sortdata, (size_t)donelen, sizeof(DiskCycleSortData), BLI_sortutil_cmp_float);
for (int i = 0; i < donelen; i++) {
elem->indices[i] = sortdata[i].elem;
}
return true;
}
/**
* Generates a map where the key is the vertex and the value is a list
* of polys or loops that use that vertex as a corner. The lists are allocated
@@ -203,12 +471,15 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
*/
static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MVert *mvert,
const MEdge *medge,
const MPoly *mpoly,
const MLoop *mloop,
int totvert,
int totpoly,
int totloop,
const bool do_loops)
const bool do_loops,
const bool sort_disk_cycles)
{
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
int *indices, *index_iter;
@@ -246,6 +517,12 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
}
}
if (sort_disk_cycles) {
for (i = 0; i < totvert; i++) {
sort_disk_cycle(mpoly, mloop, medge, mvert, i, map + i, do_loops, false);
}
}
*r_map = map;
*r_mem = indices;
}
@@ -257,13 +534,26 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
*/
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const MVert *mvert,
const MEdge *medge,
const MPoly *mpoly,
const MLoop *mloop,
int totvert,
int totpoly,
int totloop)
int totloop,
const bool sort_disk_cycles)
{
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
mesh_vert_poly_or_loop_map_create(r_map,
r_mem,
mvert,
medge,
mpoly,
mloop,
totvert,
totpoly,
totloop,
false,
sort_disk_cycles);
}
/**
@@ -273,13 +563,17 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
*/
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MVert *mvert,
const MEdge *medge,
const MPoly *mpoly,
const MLoop *mloop,
int totvert,
int totpoly,
int totloop)
int totloop,
const bool sort_disk_cycles)
{
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
mesh_vert_poly_or_loop_map_create(
r_map, r_mem, mvert, medge, mpoly, mloop, totvert, totpoly, totloop, true, sort_disk_cycles);
}
/**
@@ -336,8 +630,13 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
* is a list of edges that use that vertex as an endpoint.
* The lists are allocated from one memory pool.
*/
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map,
int **r_mem,
const MVert *mvert,
const MEdge *medge,
int totvert,
int totedge,
bool sort_disk_cycles)
{
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
@@ -371,6 +670,12 @@ void BKE_mesh_vert_edge_map_create(
map[v[1]].count++;
}
if (sort_disk_cycles) {
for (i = 0; i < totvert; i++) {
sort_disk_cycle(NULL, NULL, medge, mvert, i, map + i, false, true);
}
}
*r_map = map;
*r_mem = indices;
}

View File

@@ -379,8 +379,16 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
/* Can we optimize by reusing an old `pmap`? How do we know an old `pmap` is stale? */
/* When called by `MOD_array.c` the `cddm` has just been created, so it has no valid `pmap`. */
BKE_mesh_vert_poly_map_create(
&poly_map, &poly_map_mem, mesh->mpoly, mesh->mloop, totvert, totpoly, totloop);
BKE_mesh_vert_poly_map_create(&poly_map,
&poly_map_mem,
mesh->mvert,
mesh->medge,
mesh->mpoly,
mesh->mloop,
totvert,
totpoly,
totloop,
false);
} /* done preparing for fast poly compare */
mp = mesh->mpoly;

View File

@@ -41,7 +41,8 @@
#include "MOD_modifiertypes.h"
Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mmd,
Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(Object *ob,
MirrorModifierData *mmd,
const Mesh *mesh,
int axis,
const float plane_co[3],
@@ -58,7 +59,8 @@ Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mm
BMIter viter;
BMVert *v, *v_next;
bm = BKE_mesh_to_bmesh_ex(mesh,
bm = BKE_mesh_to_bmesh_ex(ob,
mesh,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -102,7 +104,8 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
const int axis,
const float dist)
{
BMesh *bm = BKE_mesh_to_bmesh_ex(mesh,
BMesh *bm = BKE_mesh_to_bmesh_ex(NULL,
mesh,
&(struct BMeshCreateParams){
.use_toolflags = 1,
},
@@ -121,6 +124,7 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
true);
BM_mesh_bm_to_me(bmain,
NULL,
bm,
mesh,
(&(struct BMeshToMeshParams){
@@ -207,7 +211,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
Mesh *mesh_bisect = NULL;
if (do_bisect) {
mesh_bisect = BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(
mmd, mesh, axis, plane_co, plane_no);
ob, mmd, mesh, axis, plane_co, plane_no);
mesh = mesh_bisect;
}

View File

@@ -773,9 +773,11 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map,
&vert_to_edge_src_map_mem,
NULL,
edges_src,
num_verts_src,
num_edges_src);
num_edges_src,
false);
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2);
nearest.index = -1;
@@ -1431,19 +1433,25 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (use_from_vert) {
BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src,
&vert_to_loop_map_src_buff,
verts_src,
edges_src,
polys_src,
loops_src,
num_verts_src,
num_polys_src,
num_loops_src);
num_loops_src,
false);
if (mode & MREMAP_USE_POLY) {
BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src,
&vert_to_poly_map_src_buff,
verts_src,
edges_src,
polys_src,
loops_src,
num_verts_src,
num_polys_src,
num_loops_src);
num_loops_src,
false);
}
}

View File

@@ -35,6 +35,7 @@
#include "BLI_index_range.hh"
#include "BLI_span.hh"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -43,8 +44,10 @@
#include "BKE_editmesh.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remesh_voxel.h" /* own include */
#include "BKE_mesh_runtime.h"
#include "BKE_paint.h"
#include "bmesh_tools.h"
@@ -65,17 +68,28 @@ using blender::MutableSpan;
using blender::Span;
#ifdef WITH_QUADRIFLOW
static Mesh *remesh_quadriflow(const Mesh *input_mesh,
int target_faces,
int seed,
bool preserve_sharp,
bool preserve_boundary,
bool adaptive_scale,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
ATTR_NO_OPT static Mesh *remesh_quadriflow(const Mesh *input_mesh,
int target_faces,
int seed,
bool preserve_sharp,
bool preserve_boundary,
bool adaptive_scale,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
/* Ensure that the triangulated mesh data is up to data */
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
MeshElemMap *epmap = nullptr;
int *epmem = nullptr;
BKE_mesh_edge_poly_map_create(&epmap,
&epmem,
input_mesh->medge,
input_mesh->totedge,
input_mesh->mpoly,
input_mesh->totpoly,
input_mesh->mloop,
input_mesh->totloop);
/* Gather the required data for export to the internal quadriflow mesh format. */
MVertTri *verttri = (MVertTri *)MEM_callocN(
@@ -86,17 +100,63 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
const int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
const int totverts = input_mesh->totvert;
Array<float3> verts(totverts);
Array<int> faces(totfaces * 3);
Array<QuadriflowFace> faces(totfaces);
for (const int i : IndexRange(totverts)) {
verts[i] = input_mesh->mvert[i].co;
}
int *fsets = (int *)CustomData_get_layer(&input_mesh->pdata, CD_SCULPT_FACE_SETS);
for (const int i : IndexRange(totfaces)) {
MVertTri &vt = verttri[i];
faces[i * 3] = vt.tri[0];
faces[i * 3 + 1] = vt.tri[1];
faces[i * 3 + 2] = vt.tri[2];
faces[i].eflag[0] = faces[i].eflag[1] = faces[i].eflag[2] = 0;
faces[i].v[0] = vt.tri[0];
faces[i].v[1] = vt.tri[1];
faces[i].v[2] = vt.tri[2];
for (const int j : IndexRange(3)) {
MLoop *l = input_mesh->mloop + looptri[i].tri[j];
MEdge *e = input_mesh->medge + l->e;
if (e->flag & ME_SHARP) {
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
continue;
}
MeshElemMap *melem = epmap + looptri[i].poly;
if (melem->count == 1) {
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
continue;
}
int fset = 0;
int mat_nr = 0;
for (int k : IndexRange(melem->count)) {
MPoly *p = input_mesh->mpoly + melem->indices[k];
if (k > 0 && p->mat_nr != mat_nr) {
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
continue;
}
mat_nr = (int)p->mat_nr;
if (fsets) {
int fset2 = fsets[melem->indices[k]];
if (k > 0 && abs(fset) != abs(fset2)) {
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
break;
}
fset = fset2;
}
}
}
}
/* Fill out the required input data */
@@ -158,6 +218,14 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
MEM_freeN(qrd.out_faces);
MEM_freeN(qrd.out_verts);
if (epmap) {
MEM_freeN((void *)epmap);
}
if (epmem) {
MEM_freeN((void *)epmem);
}
return mesh;
}
#endif
@@ -328,6 +396,78 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
free_bvhtree_from_mesh(&bvhtree);
}
void BKE_mesh_remesh_sculpt_array_update(Object *ob, Mesh *target, Mesh *source)
{
SculptSession *ss = ob->sculpt;
if (!ss) {
return;
}
SculptArray *array = ss->array;
if (!array) {
return;
}
BVHTreeFromMesh bvhtree = {nullptr};
bvhtree.nearest_callback = nullptr;
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
const int target_totvert = target->totvert;
int *target_copy_index = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
int *target_symmertry = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
float (*target_orco)[3] = (float (*)[3])MEM_malloc_arrayN(target->totvert, sizeof(float) * 3, "array orco");
for (int i = 0; i < target_totvert; i++) {
target_copy_index[i] = -1;
target_symmertry[i] = 0;
copy_v3_v3(target_orco[i], target->mvert[i].co);
}
for (int i = 0; i < target->totvert; i++) {
float from_co[3];
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
copy_v3_v3(from_co, target_verts[i].co);
BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
target_copy_index[i] = array->copy_index[nearest.index];
target_symmertry[i] = array->symmetry_pass[nearest.index];
}
}
free_bvhtree_from_mesh(&bvhtree);
MEM_freeN(array->copy_index);
MEM_freeN(array->symmetry_pass);
MEM_freeN(array->orco);
array->copy_index = target_copy_index;
array->symmetry_pass = target_symmertry;
array->orco = target_orco;
for (int i = 0; i < target->totvert; i++) {
int array_index = target_copy_index[i];
int array_symm_pass = target_symmertry[i];
if (array_index == -1) {
continue;
}
SculptArrayCopy *copy = &array->copies[array_symm_pass][array_index];
float co[3];
float source_origin_symm[3];
copy_v3_v3(co, target->mvert[i].co);
/* TODO: MAke symmetry work here. */
//flip_v3_v3(source_origin_symm, array->source_origin, array_symm_pass);
mul_v3_m4v3(co, array->source_imat, co);
mul_v3_m4v3(co, copy->imat, co);
sub_v3_v3v3(co, co, source_origin_symm);
copy_v3_v3(array->orco[i], co);
}
}
void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
{
BVHTreeFromMesh bvhtree = {nullptr};
@@ -375,6 +515,33 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
free_bvhtree_from_mesh(&bvhtree);
}
void BKE_remesh_reproject_materials(Mesh *target, Mesh *source)
{
BVHTreeFromMesh bvhtree = {nullptr};
bvhtree.nearest_callback = nullptr;
const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
const MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
for (int i = 0; i < target->totpoly; i++) {
float from_co[3];
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
const MPoly *mpoly = &target_polys[i];
BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
target->mpoly[i].mat_nr = source->mpoly[looptri[nearest.index].poly].mat_nr;
}
}
free_bvhtree_from_mesh(&bvhtree);
}
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
{
BVHTreeFromMesh bvhtree = {nullptr};
@@ -415,7 +582,7 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
BMeshFromMeshParams bmesh_from_mesh_params{};
bmesh_from_mesh_params.calc_face_normal = true;
BM_mesh_bm_from_me(bm, mesh, &bmesh_from_mesh_params);
BM_mesh_bm_from_me(NULL, bm, mesh, &bmesh_from_mesh_params);
BMVert *v;
BMEdge *ed, *ed_next;
@@ -449,7 +616,7 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
if (BM_elem_flag_test(ed, BM_ELEM_TAG)) {
float co[3];
mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true);
BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true, false);
copy_v3_v3(vc->co, co);
}
}

View File

@@ -33,22 +33,31 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_scene.h"
#include "BKE_subdiv.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subdiv_eval.h"
#include "BKE_subsurf.h"
#include "BKE_object.h"
@@ -57,6 +66,8 @@
#include "DEG_depsgraph_query.h"
#include "bmesh.h"
#include "multires_inline.h"
#include "multires_reshape.h"
#include <math.h>
@@ -846,17 +857,461 @@ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, int x, int y
typedef struct MultiresThreadedData {
DispOp op;
MultiResSpace bmop;
BMesh *bm;
int lvl;
CCGElem **gridData, **subGridData;
CCGKey *key;
CCGKey *sub_key;
Subdiv *sd;
MPoly *mpoly;
MDisps *mdisps;
GridPaintMask *grid_paint_mask;
int *gridOffset;
int cd_mdisps_off, cd_mask_off;
int gridSize, dGridSize, dSkip;
float (*smat)[3];
bool has_grid_mask;
} MultiresThreadedData;
Object *multires_dump_grids_bmesh(Object *bmob, BMesh *bm)
{
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
printf("multires_dump_grids_bmesh: error: no multires grids\n");
return NULL;
}
bool spaceset = false;
if (bm->multiresSpace != MULTIRES_SPACE_ABSOLUTE) {
BKE_multires_bmesh_space_set(bmob, bm, MULTIRES_SPACE_ABSOLUTE);
spaceset = true;
}
Main *bmain = G.main;
char *name = "multires_dump";
bContext *ctx = CTX_create();
CTX_data_main_set(ctx, bmain);
CTX_wm_manager_set(ctx, G.main->wm.first);
CTX_data_scene_set(ctx, G.main->scenes.first);
ViewLayer *view_layer = CTX_data_view_layer(ctx);
Object *ob = BKE_object_add_only_object(bmain, OB_MESH, name);
LayerCollection *layer_collection;
ob->data = BKE_object_obdata_add_from_type(bmain, OB_MESH, name);
DEG_id_tag_update_ex(
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
// DEG_id_tag_update_ex(
// bmain, &ob->data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
layer_collection = BKE_layer_collection_get_active(view_layer);
BKE_collection_object_add(bmain, layer_collection->collection, ob);
DEG_id_type_tag(bmain, ID_OB);
DEG_relations_tag_update(bmain);
if (ob->data != NULL) {
DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
}
ob->modifiers.first = ob->modifiers.last = NULL;
zero_v3(ob->loc);
printf("users: %d\n", ob->id.us);
Mesh *me = ob->data;
BMIter iter;
BMFace *f;
int cd_mdisp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
int dimen = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
dimen = (int)floor(sqrt(md->totdisp) + 0.00001);
break;
}
if (!dimen) {
printf("multires_dump_grids_bmesh: error: corrupted multires data\n");
return NULL;
}
int totvert = bm->totloop * dimen * dimen;
int totface = bm->totloop * (dimen - 1) * (dimen - 1);
int totloop = totface * 4;
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
CustomData_free(&me->ldata, me->totloop);
CustomData_free(&me->pdata, me->totpoly);
me->totvert = totvert;
me->totpoly = totface;
me->totloop = totloop;
me->totedge = totvert + totface;
me->totface = 0;
me->act_face = -1;
EdgeHash *eh = BLI_edgehash_new_ex("multires_dump_bmesh", me->totedge);
MVert *mvert = me->totvert ?
MEM_callocN(sizeof(MVert) * me->totvert, "multires_dump_grids_bmesh.vert") :
NULL;
MEdge *medge = me->totedge ?
MEM_callocN(sizeof(MEdge) * me->totedge, "multires_dump_grids_bmesh.edge") :
NULL;
MLoop *mloop = me->totloop ?
MEM_callocN(sizeof(MLoop) * me->totloop, "multires_dump_grids_bmesh.loop") :
NULL;
MPoly *mpoly = me->totpoly ?
MEM_callocN(sizeof(MPoly) * me->totpoly, "multires_dump_grids_bmesh.poly") :
NULL;
me->cd_flag = 0;
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
BKE_mesh_update_customdata_pointers(me, 0);
int loopi = 0;
int outli = 0;
int medi = 0;
#define VINDEX(i, j) (loopi * dimen * dimen + ((j)*dimen + (i)))
// CustomData_daata_
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
do {
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
for (int i = 0; i < dimen; i++) {
for (int j = 0; j < dimen; j++) {
int vidx = loopi * dimen * dimen + (j * dimen + i);
int idx = j * dimen + i;
float *co = md->disps[idx];
MVert *mv = mvert + vidx;
copy_v3_v3(mv->co, co);
}
}
for (int i = 0; i < dimen - 1; i++) {
for (int j = 0; j < dimen - 1; j++) {
// do face
int fidx = loopi * (dimen - 1) * (dimen - 1) + (j * (dimen - 1) + i);
MPoly *mp = mpoly + fidx;
mp->totloop = 4;
mp->loopstart = outli;
MLoop *ml = mloop + outli;
ml[0].v = VINDEX(i, j);
ml[1].v = VINDEX(i, j + 1);
ml[2].v = VINDEX(i + 1, j + 1);
ml[3].v = VINDEX(i + 1, j);
for (int i2 = 0; i2 < 4; i2++) {
int a = ml[i2].v, b = ml[(i2 + 1) % 4].v;
int e;
if (!BLI_edgehash_haskey(eh, a, b)) {
BLI_edgehash_insert(eh, a, b, (void *)medi);
e = medi;
MEdge *med = medge + medi;
med->v1 = a;
med->v2 = b;
medi++;
}
else {
e = (int)BLI_edgehash_lookup(eh, a, b);
}
ml[i2].e = e;
}
outli += 4;
}
}
loopi++;
l = l->next;
} while (l != f->l_first);
}
for (int i = 0; i < me->totpoly; i++) {
if (!mpoly[i].totloop) {
printf("error 1! %d %d\n", i, me->totpoly);
}
if (mpoly[i].loopstart >= me->totloop) {
printf(
"error 2! %d %d l: %d totl: %d\n", i, me->totpoly, mpoly[i].loopstart, mpoly[i].totloop);
}
}
if (spaceset) {
BKE_multires_bmesh_space_set(bmob, bm, MULTIRES_SPACE_TANGENT);
}
BKE_mesh_calc_normals(me);
BKE_mesh_tessface_calc(me);
return ob;
}
//#define LIMIT_MAX_DISPLACEMENT
static void multires_bmesh_space_set_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
MultiresThreadedData *tdata = userdata;
int cd_mdisps_off = tdata->cd_mdisps_off;
BMesh *bm = tdata->bm;
MultiResSpace op = tdata->bmop;
BMFace *f = bm->ftable[pidx];
int gridSize = tdata->gridSize;
int S, x, y;
BMLoop *l;
#ifdef LIMIT_MAX_DISPLACEMENT
l = f->l_first;
float cent[3];
int tot = 0;
// get face center to calculate maximum allowable displacement length
zero_v3(cent);
do {
add_v3_v3(cent, l->v->co);
tot++;
l = l->next;
} while (l != f->l_first);
mul_v3_fl(cent, 1.0f / (float)tot);
#endif
l = f->l_first;
S = 0;
do {
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_mdisps_off);
float(*dispgrid)[3] = NULL;
dispgrid = mdisp->disps;
#ifdef LIMIT_MAX_DISPLACEMENT
/*try to limit numerical instability by clamping max displacement*/
float maxlen = len_v3v3(l->v->co, cent) * 15.0f;
maxlen = MAX2(maxlen, 0.00001f);
#endif
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
float sco[8], udv[3], vdv[3];
float *data = dispgrid[gridSize * y + x];
float mat[3][3], disp[3];
float grid_u = (float)x / (float)(gridSize - 1);
float grid_v = (float)y / (float)(gridSize - 1);
float u, v;
int corner = S;
if (f->len == 4) {
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
}
else {
u = 1.0 - grid_v;
v = 1.0 - grid_u;
}
BKE_subdiv_eval_limit_point_and_derivatives(tdata->sd, l->head.index, u, v, sco, udv, vdv);
BKE_multires_construct_tangent_matrix(mat, udv, vdv, f->len == 4 ? corner : 0);
copy_v3_v3(disp, data);
switch (op) {
case MULTIRES_SPACE_ABSOLUTE:
/* Convert displacement to object space
* and add to grid points */
mul_v3_m3v3(disp, mat, data);
add_v3_v3v3(data, disp, sco);
break;
case MULTIRES_SPACE_TANGENT:
/* Calculate displacement between new and old
* grid points and convert to tangent space */
invert_m3(mat);
sub_v3_v3v3(disp, data, sco);
mul_v3_m3v3(data, mat, disp);
// try to prevent errors
float len = len_v3(data);
#ifdef LIMIT_MAX_DISPLACEMENT
if (len > maxlen) {
mul_v3_fl(data, maxlen / len);
}
else if (isnan(len)) {
zero_v3(data);
}
#else
if (isnan(len)) {
zero_v3(data);
}
#endif
break;
}
}
}
S++;
l = l->next;
} while (l != f->l_first);
}
/* The original version of this function was broken (and subsequently removed)
because it didn't properly set the subdivision level; it also used the old
multires system. The new subdiv API is now used instead.
*/
void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
{
if (!bm->totface || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
return;
}
// get multires settings
MultiresModifierData *mmd = bm->haveMultiResSettings ? &bm->multires : NULL;
if (!mmd && ob) {
mmd = get_multires_modifier(NULL, ob, true);
}
if (!mmd || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
return;
}
// cache multires settings in bmesh
bm->multiresSpace = mode;
// create temporary mesh structure
Mesh _me, *me = &_me;
memset(me, 0, sizeof(Mesh));
CustomData_reset(&me->vdata);
CustomData_reset(&me->edata);
CustomData_reset(&me->ldata);
CustomData_reset(&me->fdata);
CustomData_reset(&me->pdata);
CustomData_MeshMasks extra = CD_MASK_DERIVEDMESH;
extra.lmask |= CD_MASK_MDISPS;
BM_mesh_bm_to_me_for_eval(bm, me, &extra);
SubdivSettings settings2;
// copy the settings and then set subdivision level to max
MultiresModifierData mmdcpy = *mmd;
mmdcpy.lvl = mmdcpy.sculptlvl = mmdcpy.renderlvl = mmdcpy.totlvl;
// set up subdivision surface
BKE_multires_subdiv_settings_init(&settings2, &mmdcpy);
Subdiv *sd = BKE_subdiv_new_from_mesh(&settings2, me);
BKE_subdiv_eval_begin_from_mesh(sd, me, NULL);
// create a fake object with .sculpt set to NULL
Object fakeob;
if (ob) {
fakeob = *ob;
fakeob.sculpt = NULL;
}
else {
memset(&fakeob, 0, sizeof(fakeob));
fakeob.data = me;
BLI_addtail(&fakeob.modifiers, &mmdcpy);
}
int i, gridSize;
int totpoly = bm->totface;
// force paranoia recalc of indices and lookup tables
bm->elem_index_dirty |= BM_FACE;
bm->elem_table_dirty |= BM_FACE;
BM_mesh_elem_index_ensure(bm, BM_FACE);
BM_mesh_elem_table_ensure(bm, BM_FACE);
gridSize = multires_side_tot[mmd->totlvl];
int cd_disp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
BMFace *f;
BMIter iter;
i = 0;
/*check that all grids are allocated and also set some indices*/
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMIter iter2;
BMLoop *l;
f->head.index = i;
BM_ITER_ELEM (l, &iter2, f, BM_LOOPS_OF_FACE) {
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_disp_off);
/* allocate new disps, this can happen with newly created faces */
if (!mdisp->disps) {
multires_reallocate_mdisps(1, mdisp, mmd->totlvl);
}
l->head.index = i;
if (f->len != 4) {
i++;
}
}
if (f->len == 4) {
i++;
}
}
// do the space conversion
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = CCG_TASK_LIMIT;
MultiresThreadedData data = {
.bmop = mode,
.sd = sd,
.lvl = mmd->totlvl,
.bm = bm,
.cd_mdisps_off = cd_disp_off,
.gridSize = gridSize,
};
BLI_task_parallel_range(0, totpoly, &data, multires_bmesh_space_set_cb, &settings);
BKE_mesh_free_data_for_undo(me);
BKE_subdiv_free(sd);
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
bm->elem_table_dirty |= BM_FACE | BM_LOOP;
}
static void multires_disp_run_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -1218,7 +1673,7 @@ void multires_stitch_grids(Object *ob)
int num_faces;
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
if (num_faces) {
BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
// XXX BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
}
}
@@ -1334,7 +1789,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
urat = u - x;
vrat = v - y;
uopp = 1 - urat;
uopp = 1.0f - urat;
mul_v3_v3fl(d[0], disps[y * st + x], uopp);
mul_v3_v3fl(d[1], disps[y * st + x2], urat);
@@ -1343,7 +1798,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
add_v3_v3v3(d2[0], d[0], d[1]);
add_v3_v3v3(d2[1], d[2], d[3]);
mul_v3_fl(d2[0], 1 - vrat);
mul_v3_fl(d2[0], 1.0f - vrat);
mul_v3_fl(d2[1], vrat);
add_v3_v3v3(out, d2[0], d2[1]);

View File

@@ -292,6 +292,12 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph,
multires_reshape_apply_base_update_mesh_coords(&reshape_context);
multires_reshape_apply_base_refit_base_mesh(&reshape_context);
/**
* Tag update so deform modifiers (e.g. smooth corrective)
* get updated original coordinates
*/
DEG_id_tag_update((ID *)object, ID_RECALC_GEOMETRY);
/* Reshape to the stored final state.
* Not that the base changed, so the subdiv is to be refined to the new positions. Unfortunately,
* this can not be done foe entirely cheap: if there were deformation modifiers prior to the

View File

@@ -87,11 +87,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
int *pmap_mem;
BKE_mesh_vert_poly_map_create(&pmap,
&pmap_mem,
base_mesh->mvert,
base_mesh->medge,
base_mesh->mpoly,
base_mesh->mloop,
base_mesh->totvert,
base_mesh->totpoly,
base_mesh->totloop);
base_mesh->totloop,
false);
float(*origco)[3] = MEM_calloc_arrayN(
base_mesh->totvert, sizeof(float[3]), "multires apply base origco");

View File

@@ -48,6 +48,39 @@
#include "atomic_ops.h"
#include "subdiv_converter.h"
bool debug_invert_m3_m3(float m1[3][3], const float m2[3][3], const char *func, int line)
{
float det;
int a, b;
bool success;
/* calc adjoint */
adjoint_m3_m3(m1, m2);
/* then determinant old matrix! */
det = determinant_m3_array(m2);
if (det > -0.0001 && det < 0.0001) {
fprintf(stderr, "matrix inverse error %s:%i\n\n", func, line);
}
success = (det != 0.0f);
if (LIKELY(det != 0.0f)) {
det = 1.0f / det;
for (a = 0; a < 3; a++) {
for (b = 0; b < 3; b++) {
m1[a][b] *= det;
}
}
}
return success;
}
//#define invert_m3_m3(m1, m2) debug_invert_m3_m3(m1, m2, __func__, __LINE__)
/* -------------------------------------------------------------------- */
/** \name Local Structs
* \{ */

View File

@@ -315,6 +315,8 @@ void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_contex
void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
{
ModifierData *md;
if (reshape_context->need_free_subdiv) {
BKE_subdiv_free(reshape_context->subdiv);
}

View File

@@ -881,7 +881,8 @@ static BMesh *get_bmesh_from_mesh(Mesh *mesh)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -1151,6 +1152,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
/* Store the new base-mesh as a mesh in context, free bmesh. */
context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
BM_mesh_bm_to_me(NULL,
NULL,
bm_base_mesh,
context->base_mesh,
(&(struct BMeshToMeshParams){

View File

@@ -51,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_idtype.h"
#include "BKE_image.h"
@@ -67,6 +68,7 @@
#include "BKE_pbvh.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -77,6 +79,15 @@
#include "bmesh.h"
// XXX todo: figure out bad cross module refs
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
BMesh *SCULPT_dyntopo_empty_bmesh();
void SCULPT_undo_ensure_bmlog(Object *ob);
static void init_mdyntopo_layer(SculptSession *ss, int totvert);
static void palette_init_data(ID *id)
{
Palette *palette = (Palette *)id;
@@ -1075,7 +1086,8 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
paint->symmetry_flags |= PAINT_SYMM_X;
/* Make sure at least dyntopo subdivision is enabled */
data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE | SCULPT_DYNTOPO_CLEANUP |
SCULPT_DYNTOPO_ENABLED;
}
else if ((GpPaint **)r_paint == &ts->gp_paint) {
GpPaint *data = MEM_callocN(sizeof(*data), __func__);
@@ -1375,20 +1387,23 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
if (ss->bm) {
if (ob->data) {
BMIter iter;
BMFace *efa;
BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
BM_elem_flag_set(efa, BM_ELEM_SMOOTH, ss->bm_smooth_shading);
}
if (reorder) {
BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
}
BM_mesh_bm_to_me(NULL,
ss->bm,
ob->data,
(&(struct BMeshToMeshParams){
.calc_object_remap = false,
}));
Mesh *me = BKE_object_get_original_mesh(ob);
BM_mesh_bm_to_me(
NULL,
NULL,
ss->bm,
ob->data,
(&(struct BMeshToMeshParams){.calc_object_remap = false,
/*
for memfile undo steps we need to
save id and temporary layers
*/
.copy_temp_cdlayers = true,
.ignore_mesh_id_layers = false,
.cd_mask_extra = CD_MASK_MESH_ID | CD_MASK_DYNTOPO_VERT
}));
}
}
}
@@ -1427,6 +1442,7 @@ static void sculptsession_free_pbvh(Object *object)
MEM_SAFE_FREE(ss->vemap_mem);
MEM_SAFE_FREE(ss->persistent_base);
MEM_SAFE_FREE(ss->limit_surface);
MEM_SAFE_FREE(ss->preview_vert_index_list);
ss->preview_vert_index_count = 0;
@@ -1435,6 +1451,7 @@ static void sculptsession_free_pbvh(Object *object)
MEM_SAFE_FREE(ss->vertex_info.connected_component);
MEM_SAFE_FREE(ss->vertex_info.boundary);
MEM_SAFE_FREE(ss->vertex_info.symmetrize_map);
MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index);
}
@@ -1466,7 +1483,19 @@ void BKE_sculptsession_free(Object *ob)
if (ob && ob->sculpt) {
SculptSession *ss = ob->sculpt;
if (ss->mdyntopo_verts) {
MEM_freeN(ss->mdyntopo_verts);
ss->mdyntopo_verts = NULL;
}
if (ss->bm_log && BM_log_free(ss->bm_log, true)) {
ss->bm_log = NULL;
}
/*try to save current mesh*/
if (ss->bm) {
SCULPT_on_sculptsession_bmesh_free(ss);
BKE_sculptsession_bm_to_me(ob, true);
BM_mesh_free(ss->bm);
}
@@ -1482,10 +1511,6 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->vemap);
MEM_SAFE_FREE(ss->vemap_mem);
if (ss->bm_log) {
BM_log_free(ss->bm_log);
}
MEM_SAFE_FREE(ss->texcache);
if (ss->tex_pool) {
@@ -1496,6 +1521,8 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->deform_cos);
MEM_SAFE_FREE(ss->deform_imats);
MEM_SAFE_FREE(ss->limit_surface);
if (ss->pose_ik_chain_preview) {
for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);
@@ -1608,6 +1635,12 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
return false;
}
char BKE_get_fset_boundary_symflag(Object *object)
{
const Mesh *mesh = BKE_mesh_from_object(object);
return mesh->flag & ME_SCULPT_MIRROR_FSET_BOUNDARIES ? mesh->symmetry : 0;
}
/**
* \param need_mask: So that the evaluated mesh that is returned has mask data.
*/
@@ -1621,7 +1654,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
Scene *scene = DEG_get_input_scene(depsgraph);
Sculpt *sd = scene->toolsettings->sculpt;
SculptSession *ss = ob->sculpt;
const Mesh *me = BKE_object_get_original_mesh(ob);
Mesh *me = BKE_object_get_original_mesh(ob);
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0;
@@ -1645,6 +1678,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
}
ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
ss->boundary_symmetry = (int)BKE_get_fset_boundary_symflag(ob);
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
* so no extra checks is needed here. */
@@ -1659,14 +1693,16 @@ static void sculpt_update_object(Depsgraph *depsgraph,
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
* and tools use the Face Sets data from the base mesh when Multires is active. */
ss->mvert = me->mvert;
ss->mpoly = me->mpoly;
ss->medge = me->medge;
ss->mloop = me->mloop;
ss->mpoly = me->mpoly;
}
else {
ss->totvert = me->totvert;
ss->totpoly = me->totpoly;
ss->totfaces = me->totpoly;
ss->mvert = me->mvert;
ss->medge = me->medge;
ss->mpoly = me->mpoly;
ss->mloop = me->mloop;
ss->multires.active = false;
@@ -1674,6 +1710,11 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->multires.level = 0;
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
ss->vcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
ss->vdata = &me->vdata;
ss->edata = &me->edata;
ss->ldata = &me->ldata;
ss->pdata = &me->pdata;
}
/* Sculpt Face Sets. */
@@ -1686,8 +1727,10 @@ static void sculpt_update_object(Depsgraph *depsgraph,
}
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
ss->fast_draw = (scene->toolsettings->sculpt->flags & SCULPT_FAST_DRAW) != 0;
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh);
UNUSED_VARS_NDEBUG(pbvh);
@@ -1697,8 +1740,16 @@ static void sculpt_update_object(Depsgraph *depsgraph,
BKE_pbvh_face_sets_color_set(ss->pbvh, me->face_sets_color_seed, me->face_sets_color_default);
if (need_pmap && ob->type == OB_MESH && !ss->pmap) {
BKE_mesh_vert_poly_map_create(
&ss->pmap, &ss->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
BKE_mesh_vert_poly_map_create(&ss->pmap,
&ss->pmap_mem,
me->mvert,
me->medge,
me->mpoly,
me->mloop,
me->totvert,
me->totpoly,
me->totloop,
false);
}
pbvh_show_mask_set(ss->pbvh, ss->show_mask);
@@ -1757,8 +1808,8 @@ void BKE_sculpt_update_object_before_eval(Object *ob)
/* Update before mesh evaluation in the dependency graph. */
SculptSession *ss = ob->sculpt;
if (ss && ss->building_vp_handle == false) {
if (!ss->cache && !ss->filter_cache && !ss->expand_cache) {
if (ss && (ss->building_vp_handle == false || ss->needs_pbvh_rebuild)) {
if (ss->needs_pbvh_rebuild || (!ss->cache && !ss->filter_cache && !ss->expand_cache)) {
/* We free pbvh on changes, except in the middle of drawing a stroke
* since it can't deal with changing PVBH node organization, we hope
* topology does not change in the meantime .. weak. */
@@ -1793,6 +1844,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
BLI_assert(me_eval != NULL);
sculpt_update_object(depsgraph, ob_orig, me_eval, false, false, false);
SCULPT_dynamic_topology_sync_layers(ob_orig, me_eval);
}
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
@@ -1809,19 +1861,21 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert);
BKE_mesh_update_customdata_pointers(orig_me, true);
DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES);
SCULPT_dynamic_topology_sync_layers(object, orig_me);
}
/** \warning Expects a fully evaluated depsgraph. */
void BKE_sculpt_update_object_for_edit(
Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors)
{
/* Update from sculpt operators and undo, to update sculpt session
* and PBVH after edits. */
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig);
Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
BLI_assert(ob_orig == DEG_get_original_object(ob_orig));
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
BLI_assert(me_eval != NULL);
sculpt_update_object(depsgraph, ob_orig, me_eval, need_pmap, need_mask, need_colors);
sculpt_update_object(depsgraph, ob_orig, me_eval, true, need_mask, need_colors);
}
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
@@ -1896,11 +1950,30 @@ void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
Sculpt *sd = scene->toolsettings->sculpt;
if (!sd->detail_size) {
sd->detail_size = 12;
sd->detail_size = 8.0f;
}
if (!sd->dyntopo_radius_scale) {
sd->dyntopo_radius_scale = 1.0f;
}
// we check these flags here in case versioning code fails
if (!sd->detail_range || !sd->dyntopo_spacing) {
sd->flags |= SCULPT_DYNTOPO_CLEANUP | SCULPT_DYNTOPO_ENABLED;
}
if (!sd->detail_range) {
sd->detail_range = 0.4f;
}
if (!sd->detail_percent) {
sd->detail_percent = 25;
}
if (!sd->dyntopo_spacing) {
sd->dyntopo_spacing = 35;
}
if (sd->constant_detail == 0.0f) {
sd->constant_detail = 3.0f;
}
@@ -2094,14 +2167,21 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
{
PBVH *pbvh = BKE_pbvh_new();
BKE_pbvh_set_symmetry(pbvh, 0, (int)BKE_get_fset_boundary_symflag(ob));
BKE_pbvh_build_bmesh(pbvh,
ob->sculpt->bm,
ob->sculpt->bm_smooth_shading,
ob->sculpt->bm_log,
ob->sculpt->cd_vert_node_offset,
ob->sculpt->cd_face_node_offset);
ob->sculpt->cd_face_node_offset,
ob->sculpt->cd_dyn_vert,
ob->sculpt->cd_face_areas,
ob->sculpt->fast_draw);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, false);
return pbvh;
}
@@ -2118,17 +2198,21 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
BKE_sculpt_sync_face_set_visibility(me, NULL);
BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
BKE_pbvh_build_mesh(pbvh,
me,
me->mpoly,
me->mloop,
me->mvert,
ob->sculpt->mdyntopo_verts,
me->totvert,
&me->vdata,
&me->ldata,
&me->pdata,
looptri,
looptris_num);
looptris_num,
ob->sculpt->fast_draw);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
@@ -2160,18 +2244,50 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
&key,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden);
subdiv_ccg->grid_hidden,
ob->sculpt->fast_draw);
BKE_sculptsession_check_mdyntopo(ob->sculpt, BKE_pbvh_get_grid_num_vertices(pbvh));
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
return pbvh;
}
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert)
{
if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
init_mdyntopo_layer(ss, totvert);
return true;
}
return false;
}
static void init_mdyntopo_layer(SculptSession *ss, int totvert)
{
if (ss->mdyntopo_verts) {
MEM_freeN(ss->mdyntopo_verts);
}
ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
ss->mdyntopo_verts_size = totvert;
MDynTopoVert *mv = ss->mdyntopo_verts;
for (int i = 0; i < totvert; i++, mv++) {
mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
mv->stroke_id = -1;
}
}
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
{
if (ob == NULL || ob->sculpt == NULL) {
return NULL;
}
Scene *scene = DEG_get_input_scene(depsgraph);
bool respect_hide = true;
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
if (!(BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob))) {
@@ -2181,6 +2297,8 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
PBVH *pbvh = ob->sculpt->pbvh;
if (pbvh != NULL) {
SCULPT_update_flat_vcol_shading(ob, scene);
/* NOTE: It is possible that grids were re-allocated due to modifier
* stack. Need to update those pointers. */
if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
@@ -2191,14 +2309,59 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
}
}
else if (BKE_pbvh_type(pbvh) == PBVH_BMESH) {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
SCULPT_dynamic_topology_sync_layers(ob, BKE_object_get_original_mesh(ob));
}
return pbvh;
}
if (ob->sculpt->bm != NULL) {
/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH. */
pbvh = build_pbvh_for_dynamic_topology(ob);
ob->sculpt->pbvh = pbvh;
}
else {
#if 1 // def WHEN_GLOBAL_UNDO_WORKS
/*detect if we are loading from an undo memfile step*/
Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
if (is_dyntopo) {
BMesh *bm = SCULPT_dyntopo_empty_bmesh();
ob->sculpt->bm = bm;
BM_mesh_bm_from_me(NULL,
bm,
mesh_orig,
(&(struct BMeshFromMeshParams){.calc_face_normal = true,
.use_shapekey = true,
.active_shapekey = ob->shapenr,
.ignore_id_layers = false,
.copy_temp_cdlayers = true,
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
SCULPT_dyntopo_node_layers_add(ob->sculpt);
SCULPT_undo_ensure_bmlog(ob);
pbvh = build_pbvh_for_dynamic_topology(ob);
}
else {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = object_eval->data;
if (mesh_eval->runtime.subdiv_ccg != NULL) {
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide);
}
else if (ob->type == OB_MESH) {
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
}
}
#else
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = object_eval->data;
if (mesh_eval->runtime.subdiv_ccg != NULL) {
@@ -2206,11 +2369,20 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
}
else if (ob->type == OB_MESH) {
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
BKE_sculptsession_check_mdyntopo(ob->sculpt, me_eval_deform->totvert);
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
}
#endif
}
ob->sculpt->pbvh = pbvh;
if (pbvh) {
SCULPT_update_flat_vcol_shading(ob, scene);
}
return pbvh;
}
@@ -2232,6 +2404,12 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *v3d)
return false;
}
#if 0
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
return !(v3d && (v3d->shading.type > OB_SOLID));
}
#endif
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
/* Regular mesh only draws from PBVH without modifiers and shape keys. */
const bool full_shading = (v3d && (v3d->shading.type > OB_SOLID));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
#include "MEM_guardedalloc.h"
#include "BLI_compiler_compat.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_pbvh.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "bmesh.h"
#include "pbvh_intern.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// void pbvh_bmesh_do_cache_test(void);
int main(int argc, char **argv)
{
printf("argc: %d\n", argc);
// pbvh_bmesh_do_cache_test();
return 0;
}

View File

@@ -0,0 +1,266 @@
#if 0
# include "MEM_guardedalloc.h"
# include "BLI_alloca.h"
# include "BLI_array.h"
# include "BLI_compiler_attrs.h"
# include "BLI_compiler_compat.h"
# include "BLI_ghash.h"
# include "BLI_linklist.h"
# include "BLI_math.h"
# include "BLI_memarena.h"
# include "BLI_memblock.h"
# include "BLI_mempool.h"
# include "BLI_utildefines.h"
# include "BLI_hash.h"
# include "BKE_context.h"
# include "BKE_global.h"
# include "BKE_image.h"
# include "BKE_mesh.h"
# include "BKE_multires.h"
# include "BKE_object.h"
# include "BKE_pbvh.h"
# include "BKE_scene.h"
# include "BLI_bitmap.h"
# include "DNA_customdata_types.h"
# include "DNA_image_types.h"
# include "DNA_material_types.h"
# include "DNA_mesh_types.h"
# include "DNA_meshdata_types.h"
# include "DNA_object_types.h"
# include "DNA_scene_types.h"
# include "pbvh_intern.h"
# include "bmesh.h"
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
{
return NULL; // implement me!
}
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm)
{
return NULL; // implement me!
}
typedef union TexelKey {
struct {
int idx; // index in image
int co_key; // used to differentiate same texel used in different 3d points in space
} key;
intptr_t i;
} TexelKey;
BLI_INLINE int calc_co_key(const float *co)
{
const int mul = 65535;
const int mask = 65535;
int x = (int)co[0] + (((int)co[0] * mul) & mask);
int y = (int)co[0] + (((int)co[0] * mul) & mask);
int z = (int)co[0] + (((int)co[0] * mul) & mask);
return BLI_hash_int_3d(x, y, z);
}
typedef struct TextureVDMSettings {
ImageUser ima_user;
ID *image;
bool tangent_space;
char uv_layer[64];
// used by texture_vdm_get_points
// BLI_bitmap *texel_used_map;
GSet *texel_used_map;
int width, height;
bool invalid;
} TextureVDMSettings;
typedef struct TextureNodeData {
TexPointRef *point_ids;
float (*point_cos)[3];
float (*point_uvs)[2];
float **point_cos_ptrs;
int totpoint;
} TextureNodeData;
void texture_vdm_begin(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
{
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
if (!settings->image) {
return;
}
Image *image = (Image *)settings->image;
int w = 0, h = 0;
BKE_image_get_size(image, &settings->ima_user, &w, &h);
// Image *image = settings->image.
settings->width = w;
settings->height = h;
// settings->texel_used_map = BLI_BITMAP_NEW(w * h, "texel_used_map");
settings->texel_used_map = BLI_gset_ptr_new("texel_used_map");
}
void texture_vdm_build_points(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
{
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
int idx;
if (!settings->uv_layer[0]) {
idx = CustomData_get_layer_index(&pbvh->bm->ldata, CD_MLOOPUV);
}
else {
idx = CustomData_get_named_layer_index(&pbvh->bm->ldata, CD_MLOOPUV, settings->uv_layer);
}
if (idx < 0) {
settings->invalid = true;
return;
}
const int cd_uv = pbvh->bm->ldata.layers[idx].offset;
const int w = settings->width, h = settings->height;
float **point_cos_ptrs = NULL;
float *uvs = NULL;
float *cos = NULL;
TexPointRef *ids = NULL;
BLI_array_declare(point_cos_ptrs);
BLI_array_declare(uvs);
BLI_array_declare(cos);
BLI_array_declare(ids);
for (int i = 0; i < node->tribuf->tottri; i++) {
PBVHTri *tri = node->tribuf->tris + i;
BMLoop *ls[3] = {(BMLoop *)tri->l[0], (BMLoop *)tri->l[1], (BMLoop *)tri->l[2]};
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
float tricos[3][3];
copy_v3_v3(tricos[0], ls[0]->v->co);
copy_v3_v3(tricos[1], ls[1]->v->co);
copy_v3_v3(tricos[2], ls[2]->v->co);
for (int j = 0; j < 3; j++) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[j], cd_uv);
minmax_v2v2_v2(min, max, luv->uv);
}
int dw = (int)((max[0] - min[0]) * (float)w + 0.000001f);
int dh = (int)((max[1] - min[1]) * (float)h + 0.000001f);
dw = MAX2(dw, 1);
dh = MAX2(dh, 1);
float du = (max[0] - min[0]) / dw;
float dv = (max[1] - min[1]) / dh;
float u = min[0], v = min[1];
for (int y = 0; y < dh; y++, v += dv) {
u = min[0];
for (int x = 0; x < dw; x++, u += du) {
int idx = y * w + x;
float co[3];
interp_barycentric_tri_v3(tricos, u, v, co);
TexelKey key;
key.key.idx = idx;
key.key.co_key = calc_co_key(co);
if (BLI_gset_haskey(settings->texel_used_map, (void *)key.i)) {
continue;
}
BLI_gset_insert(settings->texel_used_map, (void *)key.i);
BLI_array_append(uvs, u);
BLI_array_append(uvs, v);
BLI_array_append(cos, co[0]);
BLI_array_append(cos, co[1]);
BLI_array_append(cos, co[2]);
BLI_array_append(ids, (TexPointRef)key.i);
}
}
}
settings->invalid = false;
MEM_SAFE_FREE(data->point_cos);
MEM_SAFE_FREE(data->point_ids);
MEM_SAFE_FREE(data->point_uvs);
MEM_SAFE_FREE(data->point_cos_ptrs);
int totpoint = BLI_array_len(ids);
data->totpoint = totpoint;
data->point_cos_ptrs = MEM_malloc_arrayN(totpoint, sizeof(void *), "point_cos_ptrs");
// dumb casting trick
union {
float *cos;
float (*cos3)[3];
} castcos;
union {
float *uvs;
float (*uvs2)[2];
} castuvs;
castcos.cos = cos;
castuvs.uvs = uvs;
data->point_cos = castcos.cos3;
data->point_ids = ids;
data->point_uvs = castuvs.uvs2;
for (int i = 0; i < totpoint; i++) {
data->point_cos_ptrs[i] = cos + i * 3;
}
}
void texture_vdm_get_points(PBVH *pbvh,
PBVHNode *node,
TexLayerRef vdm,
TexPointRef **r_ids,
float ***r_cos,
float ***r_nos,
int *r_totpoint)
{
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
if (r_totpoint) {
*r_totpoint = data->totpoint;
}
if (r_cos) {
*r_cos = data->point_cos_ptrs;
}
if (r_ids) {
*r_ids = data->point_ids;
}
}
static SculptDisplacementDef texture_vdm = {
.type = SCULPT_TEXTURE_UV,
.settings_size = sizeof(TextureNodeData),
.getPointsFromNode = texture_vdm_get_points,
};
#endif

View File

@@ -16,9 +16,17 @@
#pragma once
#include "BLI_compiler_compat.h"
#include "BLI_ghash.h"
#include "DNA_customdata_types.h"
#include "DNA_material_types.h"
#include "bmesh.h"
/** \file
* \ingroup bli
*/
struct MDynTopoVert;
/* Axis-aligned bounding box */
typedef struct {
@@ -35,6 +43,10 @@ typedef struct {
struct PBVHNode {
/* Opaque handle for drawing code */
struct GPU_PBVH_Buffers *draw_buffers;
struct GPU_PBVH_Buffers **mat_draw_buffers; // currently only used by pbvh_bmesh
int tot_mat_draw_buffers;
int id;
/* Voxel bounds */
BB vb;
@@ -43,6 +55,7 @@ struct PBVHNode {
/* For internal nodes, the offset of the children in the PBVH
* 'nodes' array. */
int children_offset;
int subtree_tottri;
/* Pointer into the PBVH prim_indices array and the number of
* primitives used by this leaf node.
@@ -86,7 +99,7 @@ struct PBVHNode {
/* Indicates whether this node is a leaf or not; also used for
* marking various updates that need to be applied. */
PBVHNodeFlags flag : 16;
PBVHNodeFlags flag : 32;
/* Used for raycasting: how close bb is to the ray point. */
float tmin;
@@ -98,27 +111,39 @@ struct PBVHNode {
PBVHProxyNode *proxies;
/* Dyntopo */
GSet *bm_faces;
GSet *bm_unique_verts;
GSet *bm_other_verts;
float (*bm_orco)[3];
int (*bm_ortri)[3];
int bm_tot_ortri;
TableGSet *bm_faces;
TableGSet *bm_unique_verts;
TableGSet *bm_other_verts;
PBVHTriBuf *tribuf; // all triangles
PBVHTriBuf *tri_buffers; // tribuffers, one per material used
int tot_tri_buffers;
int updategen;
/* Used to store the brush color during a stroke and composite it over the original color */
PBVHColorBufferNode color_buffer;
#ifdef PROXY_ADVANCED
ProxyVertArray proxyverts;
#endif
};
typedef enum {
PBVH_DYNTOPO_SMOOTH_SHADING = 1,
PBVH_FAST_DRAW = 2 // hides facesets/masks and forces smooth to save GPU bandwidth
} PBVHFlags;
typedef struct PBVHBMeshLog PBVHBMeshLog;
struct DMFlagMat;
struct PBVH {
PBVHType type;
PBVHFlags flags;
int idgen;
bool dyntopo_stop;
PBVHNode *nodes;
int node_mem_count, totnode;
@@ -127,6 +152,7 @@ struct PBVH {
int totvert;
int leaf_limit;
int depth_limit;
/* Mesh data */
const struct Mesh *mesh;
@@ -146,7 +172,7 @@ struct PBVH {
CCGKey gridkey;
CCGElem **grids;
void **gridfaces;
const DMFlagMat *grid_flag_mats;
const struct DMFlagMat *grid_flag_mats;
int totgrid;
BLI_bitmap **grid_hidden;
@@ -168,14 +194,31 @@ struct PBVH {
BMesh *bm;
float bm_max_edge_len;
float bm_min_edge_len;
float bm_detail_range;
int cd_dyn_vert;
int cd_vert_node_offset;
int cd_face_node_offset;
int cd_vert_mask_offset;
int cd_vcol_offset;
int cd_faceset_offset;
int cd_face_area;
float planes[6][4];
int num_planes;
int symmetry;
int boundary_symmetry;
struct BMLog *bm_log;
struct SubdivCCG *subdiv_ccg;
bool flat_vcol_shading;
bool need_full_render; // used by pbvh drawing for PBVH_BMESH
int balance_counter;
int stroke_id; // used to keep origdata up to date in PBVH_BMESH
struct MDynTopoVert *mdyntopo_verts;
};
/* pbvh.c */
@@ -184,6 +227,9 @@ void BB_expand(BB *bb, const float co[3]);
void BB_expand_with_bb(BB *bb, BB *bb2);
void BBC_update_centroid(BBC *bbc);
int BB_widest_axis(const BB *bb);
void BB_intersect(BB *r_out, BB *a, BB *b);
float BB_volume(const BB *bb);
void pbvh_grow_nodes(PBVH *bvh, int totnode);
bool ray_face_intersection_quad(const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
@@ -217,20 +263,97 @@ bool ray_face_nearest_tri(const float ray_start[3],
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
bool ray_face_intersection_depth_tri(const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
const float t0[3],
const float t1[3],
const float t2[3],
float *r_depth,
float *r_back_depth,
int *hit_count);
/* pbvh_bmesh.c */
bool pbvh_bmesh_node_raycast(PBVHNode *node,
bool pbvh_bmesh_node_raycast(PBVH *pbvh,
PBVHNode *node,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
float *dist,
int *hit_count,
float *depth,
float *back_depth,
bool use_original,
int *r_active_vertex_index,
float *r_face_normal);
bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
SculptVertRef *r_active_vertex_index,
SculptFaceRef *r_active_face_index,
float *r_face_normal,
int stroke_id);
bool pbvh_bmesh_node_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
const float ray_start[3],
const float ray_normal[3],
float *depth,
float *dist_sq,
bool use_original);
bool use_original,
int stroke_id);
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
void pbvh_free_all_draw_buffers(PBVHNode *node);
void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node);
BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *pbvh, const BMVert *key)
{
const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_vert_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
BLI_assert(node_index < pbvh->totnode);
return node_index;
}
BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *pbvh, const BMFace *key)
{
const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_face_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
BLI_assert(node_index < pbvh->totnode);
return node_index;
}
BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *pbvh, const BMVert *key)
{
int ni = pbvh_bmesh_node_index_from_vert(pbvh, key);
return ni >= 0 ? pbvh->nodes + ni : NULL;
// return &pbvh->nodes[pbvh_bmesh_node_index_from_vert(pbvh, key)];
}
BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key)
{
int ni = pbvh_bmesh_node_index_from_face(pbvh, key);
return ni >= 0 ? pbvh->nodes + ni : NULL;
// return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)];
}
bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index);
void pbvh_bmesh_check_nodes(PBVH *pbvh);
void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni);
void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f);
void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
BMVert *v,
int bound_symmetry);
BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v)
{
MDynTopoVert *mv = (MDynTopoVert *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_dyn_vert);
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
bke_pbvh_update_vert_boundary(
pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v, pbvh->boundary_symmetry);
return true;
}
return false;
}
void pbvh_bmesh_check_other_verts(PBVHNode *node);
//#define DEFRAGMENT_MEMORY

View File

@@ -69,6 +69,7 @@
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_brush_engine.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_colortools.h"
@@ -849,6 +850,11 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
}
if (tos->sculpt) {
BLO_write_struct(writer, Sculpt, tos->sculpt);
if (tos->sculpt->channels) {
BKE_brush_channelset_write(writer, tos->sculpt->channels);
}
BKE_paint_blend_write(writer, &tos->sculpt->paint);
}
if (tos->uvsculpt) {
@@ -1050,6 +1056,18 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
if (sce->toolsettings->sculpt && sce->toolsettings->sculpt->channels) {
BLO_read_data_address(reader, &sce->toolsettings->sculpt->channels);
BKE_brush_channelset_read(reader, sce->toolsettings->sculpt->channels);
}
else if (sce->toolsettings->sculpt) {
sce->toolsettings->sculpt->channels = BKE_brush_channelset_create();
}
if (sce->toolsettings->sculpt) {
BKE_brush_check_toolsettings(sce->toolsettings->sculpt);
}
/* relink grease pencil interpolation curves */
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
if (sce->toolsettings->gp_interpolate.custom_ipo) {
@@ -1597,6 +1615,14 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
}
if (ts->sculpt) {
ts->sculpt = MEM_dupallocN(ts->sculpt);
if (ts->sculpt->channels) {
ts->sculpt->channels = BKE_brush_channelset_copy(ts->sculpt->channels);
}
else {
ts->sculpt->channels = BKE_brush_channelset_create();
}
BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
}
if (ts->uvsculpt) {
@@ -1652,6 +1678,11 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
}
if (toolsettings->sculpt) {
BKE_paint_free(&toolsettings->sculpt->paint);
if (toolsettings->sculpt->channels) {
BKE_brush_channelset_free(toolsettings->sculpt->channels);
}
MEM_freeN(toolsettings->sculpt);
}
if (toolsettings->uvsculpt) {
@@ -2393,6 +2424,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_mesh->bm;
BM_mesh_bm_to_me(bmain,
NULL,
bm,
mesh,
(&(struct BMeshToMeshParams){

View File

@@ -360,6 +360,7 @@ static void eval_displacement(SubdivDisplacement *displacement,
BKE_multires_construct_tangent_matrix(tangent_matrix, dPdu, dPdv, corner_of_quad);
mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
/* For the boundary points of grid average two (or all) neighbor grids. */
const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
}

View File

@@ -1866,11 +1866,14 @@ static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
BKE_mesh_vert_poly_map_create(&ccgdm->pmap,
&ccgdm->pmap_mem,
me->mvert,
me->medge,
me->mpoly,
me->mloop,
me->totvert,
me->totpoly,
me->totloop);
me->totloop,
false);
}
return ccgdm->pmap;

View File

@@ -21,7 +21,7 @@
# define __has_feature(x) 0
#endif
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && !defined(_MSC_VER)
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
# include "sanitizer/asan_interface.h"
#else
/* Ensure return value is used. Just using UNUSED_VARS results in a warning. */
@@ -40,3 +40,59 @@
* Mark a region of memory as usable again.
*/
#define BLI_asan_unpoison(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size)
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
# include "MEM_guardedalloc.h"
static void *BLI_asan_safe_malloc(size_t size, const char *tag)
{
// align size at 16 bytes
size += 15 - (size & 15);
// add safe padding
size += 32;
void *ret = MEM_mallocN(size, tag);
int *iptr = (int *)ret;
*iptr = (int)size;
char *ptr = (char *)ret;
ptr[4] = 't';
ptr[5] = 'a';
ptr[6] = 'g';
ptr[7] = '1';
BLI_asan_poison(ptr, 16);
BLI_asan_poison(ptr + size - 16, 16);
ret = (void *)(ptr + 16);
return ret;
}
static void BLI_asan_safe_free(void *mem)
{
if (!mem) {
return;
}
mem = (void *)(((char *)mem) - 16);
BLI_asan_unpoison(mem, 16);
int *iptr = (int *)mem;
volatile char *ptr = (char *)mem;
if (ptr[4] != 't' || ptr[5] != 'a' || ptr[6] != 'g' || ptr[7] != '1') {
BLI_asan_poison(mem, 16);
*ptr = 1; // deliberately trigger asan fault
}
BLI_asan_unpoison(ptr + iptr[0] - 16, 16);
MEM_freeN((void *)ptr);
}
#else
# define BLI_asan_safe_malloc(size, tag) MEM_mallocN(size, tag)
# define BLI_asan_safe_free(mem) MEM_SAFE_FREE(mem)
#endif

View File

@@ -33,6 +33,12 @@
/* hint to mark function arguments expected to be non-null
* if no arguments are given to the macro, all of pointer
* arguments would be expected to be non-null
*
* ONE-INDEXED!
*
* Example:
*
* void func(void *a, void *b, void *b) ATTR_NONNULL(1, 2, 3)
*/
#ifdef __GNUC__
# define ATTR_NONNULL(args...) __attribute__((nonnull(args)))
@@ -99,6 +105,17 @@
# define ATTR_ALIGN(x) __attribute__((aligned(x)))
#endif
/* Disable optimization for a function (for debugging use only!)*/
#ifdef __clang__
# define ATTR_NO_OPT __attribute__((optnone))
#elif defined(_MSC_VER)
# define ATTR_NO_OPT __pragma(optimize("", off))
#elif defined(__GNUC__)
# define ATTR_NO_OPT __attribute__((optimize("O0")))
#else
# define ATTR_NO_OPT
#endif
/* Alignment directive */
#ifdef _WIN64
# define ALIGN_STRUCT __declspec(align(64))

View File

@@ -101,6 +101,22 @@ void *BLI_ghash_lookup_default(const GHash *gh,
const void *key,
void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
/**
* Lookup a pointer to the value of \a key in \a gh.
*
* \param key: The key to lookup.
* \param r_key: Pointer to variable to store the key as stored in the ghash
* \param r_val: Similar to BLI_ghash_ensure_p, pointer to the ghash pointer
* that stores the value
*
* \returns true if the value was found
*
* \note This has 2 main benefits over #BLI_ghash_lookup.
* - The value can be modified in-place without further function calls (faster).
* - The key as stored in the ghash is returned in r_key
*/
bool BLI_ghash_lookup_p_ex(GHash *gh, const void *key, void **r_key, void ***r_val);
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val)
ATTR_WARN_UNUSED_RESULT;
@@ -188,6 +204,53 @@ BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi)
typedef struct GSet GSet;
struct SmallHash;
#include "BLI_smallhash.h"
typedef struct TableGSet {
struct SmallHash ptr_to_idx;
void **elems;
int size, length;
int cur;
} TableGSet;
TableGSet *BLI_table_gset_new(const char *info);
TableGSet *BLI_table_gset_new_ex(const char *info, int size);
void BLI_table_gset_free(TableGSet *ts, GHashKeyFreeFP freefp);
void BLI_table_gset_insert(TableGSet *ts, void *elem);
bool BLI_table_gset_add(TableGSet *ts, void *elem);
void BLI_table_gset_remove(TableGSet *ts, void *elem, GHashKeyFreeFP freefp);
bool BLI_table_gset_haskey(TableGSet *ts, void *elem);
int BLI_table_gset_len(TableGSet *ts);
#define TGSET_ITER(v, ts) \
{ \
int _i1; \
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
if (!(ts)->elems[_i1]) \
continue; \
v = (ts)->elems[_i1];
#define TGSET_ITER_END \
} \
}
#define TGSET_ITER_INDEX(v, ts, index) \
{ \
int _i1; \
index = -1; \
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
if (!(ts)->elems[_i1]) \
continue; \
v = (ts)->elems[_i1]; \
index++;
#define TGSET_ITER_INDEX_END \
} \
}
typedef GHashHashFP GSetHashFP;
typedef GHashCmpFP GSetCmpFP;
typedef GHashKeyFreeFP GSetKeyFreeFP;

View File

@@ -52,7 +52,7 @@
#define BLI_LINKSTACK_SIZE(var) BLI_mempool_len(var##_pool_)
/* check for typeof() */
#ifdef __GNUC__
#if defined(__GNUC__) || defined(__clang__)
# define BLI_LINKSTACK_PUSH(var, ptr) \
(CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \
BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))

View File

@@ -87,11 +87,35 @@ enum {
* order of allocation when no chunks have been freed.
*/
BLI_MEMPOOL_ALLOW_ITER = (1 << 0),
/* allow random access, implies BLI_MEMPOOL_ALLOW_ITER since we
need the freewords to detect free state of elements*/
BLI_MEMPOOL_RANDOM_ACCESS = (1 << 1) | (1 << 0)
};
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL();
void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/*
This preallocates a mempool suitable for threading. totelem elements are preallocated
in chunks of size pchunk, and returned in r_chunks.
*/
BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize,
int totelem,
const int pchunk,
void ***r_chunks,
int *r_totchunk,
int *r_esize,
int flag);
// memory coherence stuff
int BLI_mempool_find_elems_fuzzy(
BLI_mempool *pool, int idx, int range, void **r_elems, int r_elems_size);
int BLI_mempool_get_size(BLI_mempool *pool);
int BLI_mempool_find_real_index(BLI_mempool *pool, void *ptr);
#ifdef __cplusplus
}
#endif

View File

@@ -39,11 +39,13 @@ typedef struct {
#define SMSTACKSIZE 131
typedef struct SmallHash {
unsigned int nbuckets;
unsigned int nentries;
unsigned int nentries, nfreecells;
unsigned int cursize;
SmallHashEntry *buckets;
SmallHashEntry buckets_stack[SMSTACKSIZE];
bool using_stack;
} SmallHash;
typedef struct {
@@ -57,22 +59,25 @@ void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
int BLI_smallhash_len(const SmallHash *sh) ATTR_NONNULL(1);
bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
int BLI_smallhash_len(SmallHash *sh) ATTR_NONNULL(1);
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
void **BLI_smallhash_iternew_p(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/* void BLI_smallhash_print(SmallHash *sh); */ /* UNUSED */
void BLI_smallhash_clear(SmallHash *sh, uintptr_t key);
bool BLI_smallhash_ensure_p(SmallHash *sh, uintptr_t key, void ***item);
bool BLI_smallhash_remove_p(SmallHash *sh, uintptr_t key, void **val);
#ifdef DEBUG
double BLI_smallhash_calc_quality(SmallHash *sh);
#endif

Some files were not shown because too many files have changed in this diff Show More