Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xrelease/scripts/op/console_python.py284
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c6
-rw-r--r--source/blender/blenlib/BLI_array.h6
-rw-r--r--source/blender/blenlib/BLI_mempool.h80
-rwxr-xr-xsource/blender/blenlib/BLI_smallhash.h204
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c23
-rw-r--r--source/blender/blenlib/intern/math_geom.c2
-rw-r--r--source/blender/bmesh/bmesh_iterators.h1
-rw-r--r--source/blender/bmesh/bmesh_operator_api.h20
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c37
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_newcore.c11
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c8
-rw-r--r--source/blender/bmesh/operators/createops.c781
-rw-r--r--source/blender/bmesh/operators/mesh_conv.c14
-rwxr-xr-xsource/blender/editors/include/ED_toolmode.h80
-rw-r--r--source/blender/editors/mesh/bmesh_select.c11
-rw-r--r--source/blender/editors/mesh/bmesh_tools.c2
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.c20
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.h2
-rwxr-xr-xsource/blender/editors/mesh/knifetool.c1623
-rw-r--r--source/blender/editors/mesh/loopcut.c3
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
32 files changed, 3150 insertions, 127 deletions
diff --git a/release/scripts/op/console_python.py b/release/scripts/op/console_python.py
new file mode 100755
index 00000000000..81046322967
--- /dev/null
+++ b/release/scripts/op/console_python.py
@@ -0,0 +1,284 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import sys
+import bpy
+
+language_id = 'python'
+
+# store our own __main__ module, not 100% needed
+# but python expects this in some places
+_BPY_MAIN_OWN = True
+
+def add_scrollback(text, text_type):
+ for l in text.split('\n'):
+ bpy.ops.console.scrollback_append(text=l.replace('\t', ' '),
+ type=text_type)
+
+
+def get_console(console_id):
+ '''
+ helper function for console operators
+ currently each text datablock gets its own
+ console - code.InteractiveConsole()
+ ...which is stored in this function.
+
+ console_id can be any hashable type
+ '''
+ from code import InteractiveConsole
+
+ consoles = getattr(get_console, "consoles", None)
+ hash_next = hash(bpy.context.window_manager)
+
+ if consoles is None:
+ consoles = get_console.consoles = {}
+ get_console.consoles_namespace_hash = hash_next
+ else:
+ # check if clearning the namespace is needed to avoid a memory leak.
+ # the window manager is normally loaded with new blend files
+ # so this is a reasonable way to deal with namespace clearing.
+ # bpy.data hashing is reset by undo so cant be used.
+ hash_prev = getattr(get_console, "consoles_namespace_hash", 0)
+
+ if hash_prev != hash_next:
+ get_console.consoles_namespace_hash = hash_next
+ consoles.clear()
+
+ console_data = consoles.get(console_id)
+
+ if console_data:
+ console, stdout, stderr = console_data
+
+ # XXX, bug in python 3.1.2 ? (worked in 3.1.1)
+ # seems there is no way to clear StringIO objects for writing, have to make new ones each time.
+ import io
+ stdout = io.StringIO()
+ stderr = io.StringIO()
+ else:
+ if _BPY_MAIN_OWN:
+ import types
+ bpy_main_mod = types.ModuleType("__main__")
+ namespace = bpy_main_mod.__dict__
+ else:
+ namespace = {}
+
+ namespace["__builtins__"] = sys.modules["builtins"]
+ namespace["bpy"] = bpy
+ namespace["C"] = bpy.context
+
+ console = InteractiveConsole(locals=namespace, filename="<blender_console>")
+
+ if _BPY_MAIN_OWN:
+ console._bpy_main_mod = bpy_main_mod
+
+ import io
+ stdout = io.StringIO()
+ stderr = io.StringIO()
+
+ consoles[console_id] = console, stdout, stderr
+
+ return console, stdout, stderr
+
+
+# Both prompts must be the same length
+PROMPT = '>>> '
+PROMPT_MULTI = '... '
+
+
+def execute(context):
+ sc = context.space_data
+
+ try:
+ line_object = sc.history[-1]
+ except:
+ return {'CANCELLED'}
+
+ if sc.console_type != 'PYTHON':
+ return {'CANCELLED'}
+
+ console, stdout, stderr = get_console(hash(context.region))
+
+ # redirect output
+ sys.stdout = stdout
+ sys.stderr = stderr
+
+ # dont allow the stdin to be used, can lock blender.
+ stdin_backup = sys.stdin
+ sys.stdin = None
+
+ if _BPY_MAIN_OWN:
+ main_mod_back = sys.modules["__main__"]
+ sys.modules["__main__"] = console._bpy_main_mod
+
+ # incase exception happens
+ line = "" # incase of encodingf error
+ is_multiline = False
+
+ try:
+ line = line_object.body
+
+ # run the console, "\n" executes a multiline statement
+ line_exec = line if line.strip() else "\n"
+
+ is_multiline = console.push(line_exec)
+ except:
+ # unlikely, but this can happen with unicode errors for example.
+ import traceback
+ stderr.write(traceback.format_exc())
+
+ if _BPY_MAIN_OWN:
+ sys.modules["__main__"] = main_mod_back
+
+ stdout.seek(0)
+ stderr.seek(0)
+
+ output = stdout.read()
+ output_err = stderr.read()
+
+ # cleanup
+ sys.stdout = sys.__stdout__
+ sys.stderr = sys.__stderr__
+ sys.last_traceback = None
+
+ # So we can reuse, clear all data
+ stdout.truncate(0)
+ stderr.truncate(0)
+
+ bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
+
+ if is_multiline:
+ sc.prompt = PROMPT_MULTI
+ else:
+ sc.prompt = PROMPT
+
+ # insert a new blank line
+ bpy.ops.console.history_append(text="", current_character=0,
+ remove_duplicates=True)
+
+ # Insert the output into the editor
+ # not quite correct because the order might have changed,
+ # but ok 99% of the time.
+ if output:
+ add_scrollback(output, 'OUTPUT')
+ if output_err:
+ add_scrollback(output_err, 'ERROR')
+
+ # restore the stdin
+ sys.stdin = stdin_backup
+
+ return {'FINISHED'}
+
+
+def autocomplete(context):
+ from console import intellisense
+
+ sc = context.space_data
+
+ console = get_console(hash(context.region))[0]
+
+ if not console:
+ return {'CANCELLED'}
+
+ if sc.console_type != 'PYTHON':
+ return {'CANCELLED'}
+
+ # dont allow the stdin to be used, can lock blender.
+ # note: unlikely stdin would be used for autocomp. but its possible.
+ stdin_backup = sys.stdin
+ sys.stdin = None
+
+ scrollback = ""
+ scrollback_error = ""
+
+ if _BPY_MAIN_OWN:
+ main_mod_back = sys.modules["__main__"]
+ sys.modules["__main__"] = console._bpy_main_mod
+
+ try:
+ current_line = sc.history[-1]
+ line = current_line.body
+
+ # This function isnt aware of the text editor or being an operator
+ # just does the autocomp then copy its results back
+ current_line.body, current_line.current_character, scrollback = \
+ intellisense.expand(
+ line=current_line.body,
+ cursor=current_line.current_character,
+ namespace=console.locals,
+ private=bpy.app.debug)
+ except:
+ # unlikely, but this can happen with unicode errors for example.
+ # or if the api attribute access its self causes an error.
+ import traceback
+ scrollback_error = traceback.format_exc()
+
+ if _BPY_MAIN_OWN:
+ sys.modules["__main__"] = main_mod_back
+
+ # Separate automplete output by command prompts
+ if scrollback != '':
+ bpy.ops.console.scrollback_append(text=sc.prompt + current_line.body, type='INPUT')
+
+ # Now we need to copy back the line from blender back into the
+ # text editor. This will change when we dont use the text editor
+ # anymore
+ if scrollback:
+ add_scrollback(scrollback, 'INFO')
+
+ if scrollback_error:
+ add_scrollback(scrollback_error, 'ERROR')
+
+ # restore the stdin
+ sys.stdin = stdin_backup
+
+ context.area.tag_redraw()
+
+ return {'FINISHED'}
+
+
+def banner(context):
+ sc = context.space_data
+ version_string = sys.version.strip().replace('\n', ' ')
+
+ add_scrollback(" * Python Interactive Console %s *" % version_string, 'OUTPUT')
+ add_scrollback("Command History: Up/Down Arrow", 'OUTPUT')
+ add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT')
+ add_scrollback("Remove: Backspace/Delete", 'OUTPUT')
+ add_scrollback("Execute: Enter", 'OUTPUT')
+ add_scrollback("Autocomplete: Ctrl+Space", 'OUTPUT')
+ add_scrollback("Ctrl +/- Wheel: Zoom", 'OUTPUT')
+ add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bgl, blf, mathutils, geometry", 'OUTPUT')
+ add_scrollback("", 'OUTPUT')
+ add_scrollback(" WARNING!!! Blender 2.5 API is subject to change, see API reference for more info.", 'ERROR')
+ add_scrollback("", 'OUTPUT')
+ sc.prompt = PROMPT
+
+ return {'FINISHED'}
+
+
+def register():
+ pass
+
+
+def unregister():
+ pass
+
+
+if __name__ == "__main__":
+ register()
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 950ac6f3f4f..c9a1cfc4618 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1075,7 +1075,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
for(i=0; i<dm->numEdgeData; i++) *index++= i;
index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
- for(i=0; i<dm->numFaceData; i++) *index++= i;
+ for(i=0; i<dm->numPolyData; i++) *index++= i;
}
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 71abab93989..f43927e7df6 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1725,6 +1725,8 @@ int mesh_recalcTesselation(CustomData *fdata,
mf[k].v1 = f->v1->keyindex;
mf[k].v2 = f->v2->keyindex;
mf[k].v3 = f->v3->keyindex;
+ mf[k].v4 = f->v1->tmp.l;
+
mf[k].mat_nr = mp->mat_nr;
mf[k].flag = mp->flag;
origIndex[k] = use_face_origindex ? k : f->v1->tmp.l;
@@ -1766,7 +1768,9 @@ int mesh_recalcTesselation(CustomData *fdata,
mf->v3 = mloop[mf->v3].v;
mesh_loops_to_corners(fdata, ldata, pdata,
- lindex, i, origIndex[i], numTex, numCol);
+ lindex, i, mf->v4, numTex, numCol);
+
+ mf->v4 = 0;
}
return totface;
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index 7c1dfb1d3a4..b1db2538e6f 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -1,6 +1,5 @@
/**
- * Array library
- *
+ * Array Library
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -23,7 +22,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Geoffrey Bantle.
+ * Contributor(s): Joseph Eagar.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -90,6 +89,7 @@ behaviour, though it may not be the best in practice.
#define BLI_array_growitems(arr, num) {int _i; for (_i=0; _i<(num); _i++) {BLI_array_growone(arr);}}
#define BLI_array_free(arr) if (arr && arr != _##arr##_static) MEM_freeN(arr)
+#define BLI_array_pop(arr) ((arr&&_##arr##_count) ? arr[--_##arr##_count] : NULL)
/*resets the logical size of an array to zero, but doesn't
free the memory.*/
#define BLI_array_empty(arr) _##arr##_count=0
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index c7be8f50cf3..62714defd21 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -36,19 +36,42 @@ extern "C"
{
#endif
+#include "BKE_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_blenlib.h"
+#include <string.h>
+
#ifndef BLI_MEMPOOL_INTERN
-struct BLI_mempool;
-struct BLI_mempool_chunk;
-typedef struct BLI_mempool BLI_mempool;
+//struct BLI_mempool;
+//struct BLI_mempool_chunk;
+//typedef struct BLI_mempool BLI_mempool;
#endif
+typedef struct BLI_freenode{
+ struct BLI_freenode *next;
+ int freeword; /*used to identify this as a freed node*/
+}BLI_freenode;
+
+typedef struct BLI_mempool_chunk{
+ struct BLI_mempool_chunk *next, *prev;
+ void *data;
+}BLI_mempool_chunk;
+
+typedef struct BLI_mempool{
+ struct ListBase chunks;
+ int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/
+ BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/
+ int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
+ int use_sysmalloc, allow_iter;
+}BLI_mempool;
+
/*allow_iter allows iteration on this mempool. note: this requires that the
first four bytes of the elements never contain the character string
'free'. use with care.*/
BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk,
int use_sysmalloc, int allow_iter);
-void *BLI_mempool_alloc(BLI_mempool *pool);
+//void *BLI_mempool_alloc(BLI_mempool *pool);
void *BLI_mempool_calloc(BLI_mempool *pool);
void BLI_mempool_free(BLI_mempool *pool, void *addr);
void BLI_mempool_destroy(BLI_mempool *pool);
@@ -69,6 +92,55 @@ void BLI_mempool_allow_iter(BLI_mempool *pool);
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter);
void *BLI_mempool_iterstep(BLI_mempool_iter *iter);
+/************ inlined stuff ***********/
+#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
+#include "MEM_guardedalloc.h"
+
+BM_INLINE void *BLI_mempool_alloc(BLI_mempool *pool) {
+ void *retval=NULL;
+ BLI_freenode *curnode=NULL;
+ char *addr=NULL;
+ int j;
+
+ if (!pool) return NULL;
+
+ pool->totused++;
+
+ if(!(pool->free)){
+ /*need to allocate a new chunk*/
+ BLI_mempool_chunk *mpchunk = pool->use_sysmalloc ? (BLI_mempool_chunk*)malloc(sizeof(BLI_mempool_chunk)) : (BLI_mempool_chunk*)MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
+ mpchunk->next = mpchunk->prev = NULL;
+ mpchunk->data = pool->use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
+ BLI_addtail(&(pool->chunks), mpchunk);
+
+ pool->free = (BLI_freenode*)mpchunk->data; /*start of the list*/
+ if (pool->allow_iter)
+ pool->free->freeword = FREEWORD;
+ for(addr = (char*)mpchunk->data, j=0; j < pool->pchunk; j++){
+ curnode = ((BLI_freenode*)addr);
+ addr += pool->esize;
+ curnode->next = (BLI_freenode*)addr;
+
+ if (pool->allow_iter) {
+ curnode->freeword = FREEWORD;
+ if (j != pool->pchunk-1)
+ curnode->next->freeword = FREEWORD;
+ }
+ }
+ curnode->next = NULL; /*terminate the list*/
+
+ pool->totalloc += pool->pchunk;
+ }
+
+ retval = pool->free;
+ if (pool->allow_iter)
+ pool->free->freeword = 0x7FFFFFFF;
+
+ pool->free = pool->free->next;
+ //memset(retval, 0, pool->esize);
+ return retval;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
new file mode 100755
index 00000000000..5badff062b7
--- /dev/null
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -0,0 +1,204 @@
+/**
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_SMALLHASH_H
+#define BLI_SMALLHASH_H
+
+/*******a light stack-friendly hash library******
+ * (it uses stack space for smallish hash tables) */
+
+/*based on a doubling non-chaining approach */
+
+#include "MEM_guardedalloc.h"
+#include "BLO_sys_types.h"
+#include "BKE_utildefines.h"
+
+extern unsigned int hashsizes[];
+#define NONHASH -25436536
+typedef struct entry {intptr_t key; void *val;} entry;
+
+#define SMSTACKSIZE 521
+typedef struct SmallHash {
+ entry *table, _stacktable[SMSTACKSIZE], _copytable[SMSTACKSIZE];
+ entry *stacktable, *copytable;
+ int used;
+ int curhash;
+ int size;
+} SmallHash;
+
+/*CELL_UNUSED means this cell is inside a key series, while CELL_FREE
+ means this cell terminates a key series.
+
+ no chance of anyone shoving INT32_MAX-2 into a *val pointer, I
+ imagine. hopefully. */
+#define CELL_UNUSED ((void*)0x7FFFFFFD)
+#define CELL_FREE ((void*)0x7FFFFFFD)
+
+#define HASHNEXT(h) (((h) + ((h)==0))*2)
+
+BM_INLINE void BLI_smallhash_init(SmallHash *hash)
+{
+ int i;
+
+ memset(hash, 0, sizeof(*hash));
+
+ hash->table = hash->_stacktable;
+ hash->curhash = 2;
+ hash->size = hashsizes[hash->curhash];
+
+ hash->copytable = hash->_copytable;
+ hash->stacktable = hash->_stacktable;
+
+ for (i=0; i<hash->size; i++) {
+ hash->table[i].val = CELL_FREE;
+ }
+}
+
+/*NOTE: does *not* free *hash itself! only the direct data!*/
+BM_INLINE void BLI_smallhash_release(SmallHash *hash)
+{
+ if (!hash)
+ return;
+
+ if (hash->table != hash->stacktable)
+ MEM_freeN(hash->table);
+}
+
+BM_INLINE void BLI_smallhash_insert(SmallHash *hash, intptr_t key, void *item)
+{
+ int h;
+
+ if (hash->size < hash->used*3) {
+ int newsize = hashsizes[++hash->curhash];
+ entry *tmp;
+ int i = 0;
+
+ if (hash->table != hash->stacktable || newsize > SMSTACKSIZE) {
+ tmp = MEM_callocN(sizeof(*hash->table)*newsize, "new hashkeys");
+ } else {
+ SWAP(entry*, hash->stacktable, hash->copytable);
+ tmp = hash->stacktable;
+ }
+
+ SWAP(entry*, tmp, hash->table);
+
+ hash->size = newsize;
+
+ for (i=0; i<hash->size; i++) {
+ hash->table[i].val = CELL_FREE;
+ }
+
+ for (i=0; i<hashsizes[hash->curhash-1]; i++) {
+ if (ELEM(tmp[i].val, CELL_UNUSED, CELL_FREE))
+ continue;
+
+ h = tmp[i].key;
+ while (!ELEM(hash->table[h % newsize].val, CELL_UNUSED, CELL_FREE))
+ h = HASHNEXT(h);
+
+ h %= newsize;
+
+ hash->table[h].key = tmp[i].key;
+ hash->table[h].val = tmp[i].val;
+ }
+
+ if (tmp != hash->stacktable && tmp != hash->copytable) {
+ MEM_freeN(tmp);
+ }
+ }
+
+ h = key;
+ while (!ELEM(hash->table[h % hash->size].val, CELL_UNUSED, CELL_FREE))
+ h = HASHNEXT(h);
+
+ h %= hash->size;
+ hash->table[h].key = key;
+ hash->table[h].val = item;
+
+ hash->used++;
+}
+
+BM_INLINE void BLI_smallhash_remove(SmallHash *hash, intptr_t key)
+{
+ int h = key;
+
+ while (hash->table[h % hash->size].key != key
+ || hash->table[h % hash->size].val == CELL_UNUSED)
+ {
+ if (hash->table[h % hash->size].val == CELL_FREE)
+ return;
+ h = HASHNEXT(h);
+ }
+
+ h %= hash->size;
+ hash->table[h].key = 0;
+ hash->table[h].val = CELL_UNUSED;
+}
+
+BM_INLINE void *BLI_smallhash_lookup(SmallHash *hash, intptr_t key)
+{
+ int h = key;
+
+ if (!hash->table)
+ return NULL;
+
+ while (hash->table[h % hash->size].key != key
+ || hash->table[h % hash->size].val == CELL_UNUSED)
+ {
+ if (hash->table[h % hash->size].val == CELL_FREE)
+ return NULL;
+ h = HASHNEXT(h);
+ }
+
+ return hash->table[h % hash->size].val;
+}
+
+
+BM_INLINE int BLI_smallhash_haskey(SmallHash *hash, intptr_t key)
+{
+ int h = key;
+
+ if (!hash->table)
+ return 0;
+
+ while (hash->table[h % hash->size].key != key
+ || hash->table[h % hash->size].val == CELL_UNUSED)
+ {
+ if (hash->table[h % hash->size].val == CELL_FREE)
+ return 0;
+ h = HASHNEXT(h);
+ }
+
+ return 1;
+}
+
+BM_INLINE int BLI_smallhash_count(SmallHash *hash)
+{
+ return hash->used;
+}
+
+#endif // BLI_SMALLHASH_H
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index ed56a390719..686709d8879 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -42,26 +42,6 @@
#include <string.h>
-#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
-
-typedef struct BLI_freenode{
- struct BLI_freenode *next;
- intptr_t freeword; /*used to identify this as a freed node*/
-}BLI_freenode;
-
-typedef struct BLI_mempool_chunk{
- struct BLI_mempool_chunk *next, *prev;
- void *data;
-}BLI_mempool_chunk;
-
-typedef struct BLI_mempool{
- struct ListBase chunks;
- int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/
- struct BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/
- int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
- int use_sysmalloc, allow_iter;
-}BLI_mempool;
-
#define BLI_MEMPOOL_INTERN
#include "BLI_mempool.h"
@@ -132,7 +112,7 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk,
curnode->next = NULL;
return pool;
}
-
+#if 0
void *BLI_mempool_alloc(BLI_mempool *pool){
void *retval=NULL;
BLI_freenode *curnode=NULL;
@@ -177,6 +157,7 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
//memset(retval, 0, pool->esize);
return retval;
}
+#endif
void *BLI_mempool_calloc(BLI_mempool *pool){
void *retval=NULL;
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 68b1feea632..6756f42bf35 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -1568,7 +1568,7 @@ void interp_weights_poly_v3(float *w,float v[][3], int n, float *co)
t2= mean_value_half_tan(co, vmid, vnext);
len= len_v3v3(co, vmid);
- w[i]= (t1+t2)/len;
+ w[i]= (t1+t2)/(len+FLT_EPSILON*2);
totweight += w[i];
}
diff --git a/source/blender/bmesh/bmesh_iterators.h b/source/blender/bmesh/bmesh_iterators.h
index 16127f54e9d..c741ec5d967 100644
--- a/source/blender/bmesh/bmesh_iterators.h
+++ b/source/blender/bmesh/bmesh_iterators.h
@@ -45,6 +45,7 @@ a different face hole boundary*/
from the other faces in the radial cycle surrounding the
input loop's edge.*/
#define BM_LOOPS_OF_LOOP 12
+#define BM_LOOPS_OF_EDGE 13
#define BM_ITER(ele, iter, bm, type, data) \
ele = BMIter_New(iter, bm, type, data); \
diff --git a/source/blender/bmesh/bmesh_operator_api.h b/source/blender/bmesh/bmesh_operator_api.h
index 0b5075d4e66..0b1e356d01d 100644
--- a/source/blender/bmesh/bmesh_operator_api.h
+++ b/source/blender/bmesh/bmesh_operator_api.h
@@ -141,9 +141,9 @@ void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
if you need to store a value per element, use a
ghash or a mapping slot to do it.*/
/*flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use*/
-#define BMO_TestFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].f & (flag))
-#define BMO_SetFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].f |= (flag))
-#define BMO_ClearFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].f &= ~(flag))
+#define BMO_TestFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f & (flag))
+#define BMO_SetFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f |= (flag))
+#define BMO_ClearFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f &= ~(flag))
/*profiling showed a significant amount of time spent in BMO_TestFlag
void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
@@ -398,6 +398,11 @@ BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname,
BLI_ghash_insert(slot->data.ghash, element, mapping);
}
+BM_INLINE void BMO_Insert_MapInt(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, int val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(int));
+}
BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
void *element, float val)
@@ -448,6 +453,15 @@ BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
return 0.0f;
}
+BM_INLINE int BMO_Get_MapInt(BMesh *bm, BMOperator *op, char *slotname,
+ void *element)
+{
+ int *val = (int*) BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return 0;
+}
+
BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
void *element)
{
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index cdf05e1f780..7df30f61136 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -331,6 +331,8 @@ BMFace *BM_Make_Ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len,
for (i=0; i<len; i++) {
edges2[i] = BM_Edge_Exist(verts[i], verts[(i+1)%len]);
+ if (!edges2[i])
+ return NULL;
}
/*check if face already exists*/
@@ -534,11 +536,13 @@ BMesh *BM_Copy_Mesh(BMesh *bmold)
}
f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
+ if (!f2)
+ continue;
BMINDEX_SET(f, i);
BLI_array_growone(ftable);
ftable[i] = f2;
-
+
BM_Copy_Attributes(bmold, bm, f, f2);
VECCOPY(f2->no, f->no);
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index f53a9e4f47b..1f737ac9fe9 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -210,6 +210,35 @@ static void *loop_of_vert_step(BMIter *iter)
return NULL;
}
+
+static void loops_of_edge_begin(BMIter *iter)
+{
+ BMLoop *l;
+
+ l = iter->edata->l;
+ if (!l)
+ return;
+
+ /*note sure why this sets ldata. . .*/
+ init_iterator(iter);
+
+ iter->firstloop = iter->nextloop = l;
+}
+
+static void *loops_of_edge_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop)
+ iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop)
+ iter->nextloop = NULL;
+
+ if(current) return current;
+ return NULL;
+}
+
static void loops_of_loop_begin(BMIter *iter)
{
BMLoop *l;
@@ -420,6 +449,14 @@ void *BMIter_New(BMIter *iter, BMesh *bm, int type, void *data)
iter->step = loops_of_loop_step;
iter->ldata = data;
break;
+ case BM_LOOPS_OF_EDGE:
+ if (!data)
+ return NULL;
+
+ iter->begin = loops_of_edge_begin;
+ iter->step = loops_of_edge_step;
+ iter->edata = data;
+ break;
default:
break;
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 48cfdd1cdf6..d804e0f9193 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -129,7 +129,7 @@ BMesh *BM_Make_Mesh(int allocsize[4])
/*allocate one flag pool that we dont get rid of.*/
bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0, 0);
- bm->stackdepth = 0;
+ bm->stackdepth = 1;
bm->totflags = 1;
return bm;
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 718326b803d..fe5c49a921b 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -221,6 +221,12 @@ BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) {
}
l1 = jed->l;
+
+ if (!l1) {
+ bmesh_error();
+ return NULL;
+ }
+
l2 = l1->radial_next;
if (l1->v == l2->v) {
bmesh_loop_reverse(bm, f2);
diff --git a/source/blender/bmesh/intern/bmesh_newcore.c b/source/blender/bmesh/intern/bmesh_newcore.c
index c22946ed95f..64fcb310c93 100644
--- a/source/blender/bmesh/intern/bmesh_newcore.c
+++ b/source/blender/bmesh/intern/bmesh_newcore.c
@@ -1,3 +1,5 @@
+#include <limits.h>
+
#include "BLI_math_vector.h"
#include "BKE_utildefines.h"
@@ -658,8 +660,17 @@ static int count_flagged_radial(BMLoop *l, int flag)
int i = 0;
do {
+ if (!l2) {
+ bmesh_error();
+ return 0;
+ }
+
i += bmesh_api_getflag(l2->f, flag) ? 1 : 0;
l2 = bmesh_radial_nextloop(l2);
+ if (i >= 800000) {
+ bmesh_error();
+ return 0;
+ }
} while (l2 != l);
return i;
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 11403db2cc3..560c5b4aef0 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -383,8 +383,12 @@ BMOpDefine def_contextual_create= {
BMOpDefine def_edgenet_fill= {
"edgenet_fill",
- {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
- {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {BMOP_OPSLOT_MAPPING, "restrict"}, /*restricts edges to groups. maps edges to integers*/
+ {BMOP_OPSLOT_INT, "use_restrict"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "excludefaces"}, /*list of faces to ignore for manifold checks*/
+ {BMOP_OPSLOT_MAPPING, "faceout_groupmap"}, /*maps new faces to the group numbers they came from*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /*new faces*/
{0, /*null-terminating sentinel*/}},
bmesh_edgenet_fill_exec,
0,
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 9204052b81d..2f298902c3c 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -130,11 +130,11 @@ void BMO_Exec_Op(BMesh *bm, BMOperator *op)
BMO_push(bm, op);
- if(bm->stackdepth == 1)
+ if(bm->stackdepth == 2)
bmesh_begin_edit(bm);
op->exec(bm, op);
- if(bm->stackdepth == 1)
+ if(bm->stackdepth == 2)
bmesh_end_edit(bm,0);
BMO_pop(bm);
@@ -792,13 +792,13 @@ static void alloc_flag_layer(BMesh *bm)
bm->totflags++;
/*allocate new flag pool*/
- bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, 1, 0);
+ bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, 0, 0);
/*now go through and memcpy all the flags. Loops don't get a flag layer at this time...*/
for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
oldflags = v->head.flags;
v->head.flags = BLI_mempool_calloc(bm->toolflagpool);
- memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*(bm->totflags-1)); /*dont know if this memcpy usage is correct*/
+ memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*(bm->totflags-1));
}
for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
oldflags = e->head.flags;
diff --git a/source/blender/bmesh/operators/createops.c b/source/blender/bmesh/operators/createops.c
index 8b983f00087..57c5e13ba57 100644
--- a/source/blender/bmesh/operators/createops.c
+++ b/source/blender/bmesh/operators/createops.c
@@ -9,23 +9,34 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_smallhash.h"
+#include "BLI_rand.h"
#include "bmesh.h"
#include "bmesh_operators_private.h"
+#define EDGE_MARK 1
+#define EDGE_VIS 2
+
+#define FACE_NEW 1
+
#define ELE_NEW 1
#define ELE_OUT 2
#define ELE_ORIG 4
+#define FACE_IGNORE 16
+
typedef struct EPathNode {
struct EPathNode *next, *prev;
BMVert *v;
BMEdge *e;
+ BMEdge *cure;
} EPathNode;
typedef struct EPath {
ListBase nodes;
float weight;
+ int group;
} EPath;
typedef struct PathBase {
@@ -35,12 +46,534 @@ typedef struct PathBase {
typedef struct EdgeData {
int tag;
int ftag;
+
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink1;
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink2;
} EdgeData;
-#define EDGE_MARK 1
-#define EDGE_VIS 2
+typedef struct VertData {
+ BMEdge *e;
+ float no[3], offco[3], sco[3]; /*offco is vertex coordinate slightly offset randomly*/
+ int tag;
+} VertData;
-#define FACE_NEW 1
+static int count_edge_faces(BMesh *bm, BMEdge *e);
+
+/**** rotation system code ***/
+
+#define rs_get_edge_link(e, v, ed) (Link*)((v) == ((BMEdge*)(e))->v1 ? &(((EdgeData*)(ed))->dlink1) : &(((EdgeData*)(ed))->dlink2))
+
+int rotsys_append_edge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = &edata[BMINDEX_GET(e)];
+ VertData *vd = &vdata[BMINDEX_GET(v)];
+
+ if (!vd->e) {
+ Link *e1 = (Link*)rs_get_edge_link(e, v, ed);
+
+ vd->e = e;
+ e1->next = e1->prev = (Link*)e;
+ } else {
+ Link *e1, *e2, *e3;
+ EdgeData *ved = &edata[BMINDEX_GET(vd->e)];
+
+ e1 = rs_get_edge_link(e, v, ed);
+ e2 = rs_get_edge_link(vd->e, v, ved);
+ e3 = e2->prev ? rs_get_edge_link(e2->prev, v, &edata[BMINDEX_GET(e2->prev)]) : NULL;
+
+ e1->next = (Link*)vd->e;
+ e1->prev = e2->prev;
+
+ e2->prev = (Link*)e;
+ if (e3)
+ e3->next = (Link*)e;
+ }
+
+ return 1;
+}
+
+void rotsys_remove_edge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = edata + BMINDEX_GET(e);
+ VertData *vd = vdata + BMINDEX_GET(v);
+ Link *e1, *e2;
+
+ e1 = rs_get_edge_link(e, v, ed);
+ if (e1->prev) {
+ e2 = rs_get_edge_link(e1->prev, v, ed);
+ e2->next = e1->next;
+ }
+
+ if (e1->next) {
+ e2 = rs_get_edge_link(e1->next, v, ed);
+ e2->prev = e1->prev;
+ }
+
+ if (vd->e == e)
+ vd->e = e!=e1->next ? (BMEdge*)e1->next : NULL;
+
+ e1->next = e1->prev = NULL;
+}
+
+struct BMEdge *rotsys_nextedge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ if (v == e->v1)
+ return edata[BMINDEX_GET(e)].dlink1.next;
+ if (v == e->v2)
+ return edata[BMINDEX_GET(e)].dlink2.next;
+ return NULL;
+}
+
+BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ if (v == e->v1)
+ return edata[BMINDEX_GET(e)].dlink1.prev;
+ if (v == e->v2)
+ return edata[BMINDEX_GET(e)].dlink2.prev;
+ return NULL;
+}
+
+struct BMEdge *rotsys_reverse(struct BMEdge *e, struct BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge **edges = NULL;
+ BMEdge *e2;
+ BLI_array_staticdeclare(edges, 256);
+ int i, totedge;
+
+ e2 = vdata[BMINDEX_GET(v)].e;
+ do {
+ BLI_array_append(edges, e2);
+ e2 = rotsys_nextedge(e2, v, edata, vdata);
+ } while (e2 != vdata[BMINDEX_GET(v)].e);
+
+ totedge = BLI_array_count(edges);
+ for (i=0; i<totedge/2; i++) {
+ SWAP(BMEdge*, edges[i], edges[totedge-1-i]);
+ }
+
+ vdata[BMINDEX_GET(v)].e = NULL;
+ for (i=0; i<totedge; i++) {
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ BLI_array_free(edges);
+}
+
+int rotsys_count(struct BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge *e = vdata[BMINDEX_GET(v)].e;
+ int i=0;
+
+ if (!e)
+ return 0;
+
+ do {
+ if (!e)
+ return 0;
+ e = rotsys_nextedge(e, v, edata, vdata);
+
+ if (i >= (1<<20)) {
+ printf("bmesh error: infinite loop in disk cycle!\n");
+ return 0;
+ }
+
+ i += 1;
+ } while (e != vdata[BMINDEX_GET(v)].e);
+
+ return i;
+}
+
+int rotsys_fill_faces(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e, **edges = NULL;
+ BLI_array_declare(edges);
+ BMVert *v, **verts = NULL;
+ BMFace *f;
+ BLI_array_declare(verts);
+ SmallHash visithash, *hash=&visithash;
+ int i;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMEdge *e2, *starte;
+ BMVert *startv;
+ int rad, ok;
+
+ rad = count_edge_faces(bm, e);
+
+ if (rad < 2)
+ starte = e;
+ else
+ continue;
+
+ /*do two passes, going forward then backward*/
+ for (i=0; i<2; i++) {
+ BLI_smallhash_init(hash);
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ startv = v = starte->v1;
+ e2 = starte;
+ ok = 1;
+ if (!v || !e2)
+ continue;
+
+ do {
+ if (BLI_smallhash_haskey(hash, (intptr_t)e2)
+ || BLI_smallhash_haskey(hash, (intptr_t)v)) {
+ ok = 0;
+ break;
+ }
+
+ BLI_array_append(verts, v);
+ BLI_array_append(edges, e2);
+
+ BLI_smallhash_insert(hash, (intptr_t)e2, NULL);
+
+ v = BM_OtherEdgeVert(e2, v);
+ e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
+ } while (e2 != starte && v != startv);
+
+ BLI_smallhash_release(hash);
+
+ if (!ok || BLI_array_count(edges) < 3)
+ continue;
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), 1);
+ if (!f)
+ continue;
+ }
+ }
+}
+
+void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v, **stack=NULL;
+ BLI_array_declare(stack);
+ int i;
+
+ for (i=0; i<bm->totvert; i++) {
+ vdata[i].tag = 0;
+ }
+
+ while (1) {
+ VertData *vd;
+ BMVert *startv = NULL;
+ float dis;
+
+ v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; i<bm->totvert; i++, BMIter_Step(&iter)) {
+ vd = vdata + BMINDEX_GET(v);
+
+ if (vd->tag)
+ continue;
+
+ if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
+ dis = dot_v3v3(vd->offco, vd->offco);
+ startv = v;
+ }
+ }
+
+ if (!startv)
+ break;
+
+ vd = vdata + BMINDEX_GET(startv);
+
+ BLI_array_empty(stack);
+ BLI_array_append(stack, startv);
+
+ vd->tag = 1;
+
+ while (BLI_array_count(stack)) {
+ v = BLI_array_pop(stack);
+ vd = vdata + BMINDEX_GET(v);
+
+ if (!vd->e)
+ continue;
+
+ e = vd->e;
+ do {
+ BMVert *v2 = BM_OtherEdgeVert(e, v);
+ VertData *vd2 = vdata + BMINDEX_GET(v2);
+
+ if (dot_v3v3(vd->no, vd2->no) < 0.0f+FLT_EPSILON*2) {
+ rotsys_reverse(e, v2, edata, vdata);
+ mul_v3_fl(vd2->no, -1.0f);
+ }
+
+ if (!vd2->tag) {
+ BLI_array_append(stack, v2);
+ vd2->tag = 1;
+ }
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ } while (e != vd->e);
+ }
+ }
+
+}
+
+void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMEdge **edges = NULL;
+ BLI_array_staticdeclare(edges, 256);
+ BMVert *v, *lastv, **verts = NULL;
+ BLI_array_staticdeclare(verts, 256);
+ int i;
+
+ #define SIGN(n) ((n)<0.0f)
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMIter eiter;
+ float no[3], cent[3];
+ int j, k=0, totedge=0;
+
+ if (BMINDEX_GET(v) == -1)
+ continue;
+
+ BLI_array_empty(edges);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ BLI_array_append(edges, e);
+ totedge++;
+ }
+ }
+
+ copy_v3_v3(cent, v->co);
+
+ zero_v3(no);
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1, *e2;
+ float cno[3], vec1[3], vec2[3];
+
+ e1 = edges[i];
+ e2 = edges[(i+1)%totedge];
+
+ sub_v3_v3v3(vec1, (BM_OtherEdgeVert(e1, v))->co, v->co);
+ sub_v3_v3v3(vec2, (BM_OtherEdgeVert(e2, v))->co, v->co);
+
+ cross_v3_v3v3(cno, vec1, vec2);
+ normalize_v3(cno);
+
+ if (i && dot_v3v3(cno, no) < 0.0f+FLT_EPSILON*10)
+ mul_v3_fl(cno, -1.0f);
+
+ add_v3_v3(no, cno);
+ normalize_v3(no);
+ }
+
+ /*generate plane-flattened coordinates*/
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1;
+ BMVert *v2;
+ float cvec[3], vec1[3];
+
+ e1 = edges[i];
+ v2 = BM_OtherEdgeVert(e1, v);
+
+ sub_v3_v3v3(vec1, v2->co, v->co);
+
+ cross_v3_v3v3(cvec, vec1, no);
+ cross_v3_v3v3(vec1, cvec, no);
+ normalize_v3(vec1);
+
+ mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
+ add_v3_v3(vec1, v->co);
+
+ copy_v3_v3(vdata[BMINDEX_GET(v2)].sco, vec1);
+ }
+
+ /*first, ensure no 0 or 180 angles between adjacent
+ (and that adjacent's adjacent) edges*/
+ for (i=0, k=0; i<totedge; i++) {
+ BMEdge *e1, *e2, *e3=NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], size;
+ int s1, s2, s3;
+
+ if (totedge < 3)
+ continue;
+
+ e1 = edges[(i+totedge-1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i+1) % totedge];
+
+ v1 = BM_OtherEdgeVert(e1, v); v2 = BM_OtherEdgeVert(e2, v); v3 = BM_OtherEdgeVert(e3, v);
+ vd1 = vdata+BMINDEX_GET(v1); vd2 = vdata+BMINDEX_GET(v2); vd3 = vdata+BMINDEX_GET(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ size = (len_v3(vec1) + len_v3(vec3))*0.01;
+ normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
+
+ #ifdef STRAIGHT
+ #undef STRAIGHT
+ #endif
+ #define STRAIGHT(vec11, vec22) (fabs(dot_v3v3((vec11), (vec22))) > 1.0-FLT_EPSILON*1000)
+
+ s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
+
+ if (s1 || s2 || s3) {
+ copy_v3_v3(cent, v->co);
+
+ for (j=0; j<3; j++) {
+ float fac = (BLI_frand()-0.5f)*size;
+ cent[j] += fac;
+ }
+
+ if (k < 2000) {
+ i = 0;
+ k++;
+ continue;
+ } else {
+ k++;
+ continue;
+ }
+
+ }
+ }
+
+ copy_v3_v3(vdata[BMINDEX_GET(v)].offco, cent);
+ copy_v3_v3(v->co, cent);
+
+ /*now, sort edges so the triangle fan of all edges
+ has a consistent normal. this is the same as
+ sorting by polar coordinates along a group normal*/
+ for (j=0; j<totedge; j++) {
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1, *e2, *e3=NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
+ int s1, s2, s3;
+
+ e1 = edges[(i+totedge-1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i+1) % totedge];
+
+ v1 = BM_OtherEdgeVert(e1, v); v2 = BM_OtherEdgeVert(e2, v); v3 = BM_OtherEdgeVert(e3, v);
+ vd1 = vdata+BMINDEX_GET(v1); vd2 = vdata+BMINDEX_GET(v2); vd3 = vdata+BMINDEX_GET(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ cross_v3_v3v3(n1, vec1, vec2);
+ cross_v3_v3v3(n2, vec2, vec3);
+ cross_v3_v3v3(n3, vec1, vec3);
+
+ normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
+
+ s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
+
+ if (s1 || s2 || s3) {
+ printf("yeek! s1: %d, s2: %d, s3: %dx\n", s1, s2, s3);
+ }
+ if (dot_v3v3(n1, n2) < 0.0f) {
+ if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON*10) {
+ SWAP(BMEdge*, edges[i], edges[(i+1)%totedge]);
+ } else {
+ SWAP(BMEdge*, edges[(i+totedge-1)%totedge], edges[(i+1)%totedge])
+ SWAP(BMEdge*, edges[i], edges[(i+1)%totedge])
+ }
+ }
+ }
+ }
+
+ #undef STRAIGHT
+
+ zero_v3(no);
+
+ /*yay, edges is sorted*/
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1 = edges[i], *e2 = edges[(i+1)%totedge];
+ float eno[3];
+
+ normal_tri_v3(eno, BM_OtherEdgeVert(e1, v)->co, v->co, BM_OtherEdgeVert(e2, v)->co);
+ add_v3_v3(no, eno);
+
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ normalize_v3(no);
+ copy_v3_v3(vdata[BMINDEX_GET(v)].no, no);
+ }
+
+ /*now, make sure rotation system is topologically consistent
+ (e.g. vert normals consistently point either inside or outside)*/
+ rotsys_make_consistent(bm, edata, vdata);
+
+ //rotsys_fill_faces(bm, edata, vdata);
+
+#if 0
+ /*create visualizing geometry*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMVert *v2;
+ BMFace *f;
+ int totedge = BM_Vert_EdgeCount(v);
+
+ if (BMINDEX_GET(v) == -1)
+ continue;
+
+ //cv = BM_Make_Vert(bm, cent, v);
+ //BMINDEX_SET(cv, -1);
+ i = 0;
+ e = vdata[BMINDEX_GET(v)].e;
+ lastv = NULL;
+ do {
+ BMEdge *e2;
+ BMVert *v2;
+ float f = ((float)i / (float)totedge)*0.35 + 0.05;
+ float co[3];
+
+ if (!e)
+ break;
+
+ if (!BM_OtherEdgeVert(e, v))
+ continue;
+
+ sub_v3_v3v3(co, (BM_OtherEdgeVert(e, v))->co, vdata[BMINDEX_GET(v)].offco);
+ mul_v3_fl(co, f);
+ add_v3_v3(co, vdata[BMINDEX_GET(v)].offco);
+
+ v2 = BM_Make_Vert(bm, co, NULL);
+ BMINDEX_SET(v2, -1);
+ //BM_Make_Edge(bm, cv, v2, NULL, 0);
+
+ BM_Select(bm, v2, 1);
+ if (lastv) {
+ e2 =
+ BM_Make_Edge(bm, lastv, v2, NULL, 0);
+ BM_Select(bm, e2, 1);
+ }
+
+ lastv = v2;
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ i++;
+ } while (e != vdata[BMINDEX_GET(v)].e);
+ }
+#endif
+
+ BLI_array_free(edges);
+}
PathBase *edge_pathbase_new(void)
{
@@ -64,33 +597,40 @@ EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
EPath *path2;
EPathNode *node, *node2;
- path2 = BLI_mempool_calloc(pb->pathpool);
+ path2 = BLI_mempool_alloc(pb->pathpool);
+ path2->nodes.first = path2->nodes.last = NULL;
+ path2->weight = 0.0f;
+ path2->group = path->group;
for (node=path->nodes.first; node; node=node->next) {
- node2 = BLI_mempool_calloc(pb->nodepool);
+ node2 = BLI_mempool_alloc(pb->nodepool);
*node2 = *node;
BLI_addtail(&path2->nodes, node2);
}
- node2 = BLI_mempool_calloc(pb->nodepool);
+ node2 = BLI_mempool_alloc(pb->nodepool);
node2->v = appendv;
node2->e = e;
+ node2->cure = NULL;
BLI_addtail(&path2->nodes, node2);
return path2;
}
-EPath *edge_path_new(PathBase *pb, BMVert *start)
+EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
{
EPath *path;
EPathNode *node;
- path = BLI_mempool_calloc(pb->pathpool);
- node = BLI_mempool_calloc(pb->nodepool);
-
+ path = BLI_mempool_alloc(pb->pathpool);
+ node = BLI_mempool_alloc(pb->nodepool);
+
+ path->nodes.first = path->nodes.last = NULL;
+
node->v = start;
- node->e = NULL;
+ node->e = starte;
+ node->cure = NULL;
BLI_addtail(&path->nodes, node);
path->weight = 0.0f;
@@ -98,14 +638,18 @@ EPath *edge_path_new(PathBase *pb, BMVert *start)
return path;
}
-float edge_weight_path(EPath *path, EdgeData *edata)
+float edge_weight_path(EPath *path, EdgeData *edata, VertData *vdata)
{
- EPathNode *node;
+ EPathNode *node, *first=path->nodes.first;
float w = 0.0;
for (node=path->nodes.first; node; node=node->next) {
- if (node->e) {
+ if (node->e && node != path->nodes.first) {
w += edata[BMINDEX_GET(node->e)].ftag;
+ if (node->prev) {
+ //w += len_v3v3(node->v->co, first->e->v1->co)*0.0001f;
+ //w += len_v3v3(node->v->co, first->e->v2->co)*0.0001f;
+ }
}
w += 1.0f;
@@ -127,30 +671,39 @@ void edge_free_path(PathBase *pathbase, EPath *path)
BLI_mempool_free(pathbase->pathpool, path);
}
-EPath *edge_find_shortest_path(BMesh *bm, BMEdge *edge, EdgeData *edata, PathBase *pathbase)
+EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
+ VertData *vdata, PathBase *pathbase, int group)
{
- BMIter iter;
- BMEdge *e;
+ BMEdge *e, *starte;
GHash *gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createops find shortest path");
BMVert *v1, *v2;
BMVert **verts = NULL;
- BLI_array_declare(verts);
+ BLI_array_staticdeclare(verts, 1024);
Heap *heap = BLI_heap_new();
EPath *path = NULL, *path2;
+ BMVert *startv;
+ BMVert *endv;
EPathNode *node;
- int i;
+ int i, use_restrict = BMO_Get_Int(op, "use_restrict");
- path = edge_path_new(pathbase, edge->v1);
+ startv = edata[BMINDEX_GET(edge)].ftag ? edge->v2 : edge->v1;
+ endv = edata[BMINDEX_GET(edge)].ftag ? edge->v1 : edge->v2;
+
+ path = edge_path_new(pathbase, startv, edge);
+ BLI_ghash_insert(gh, startv, NULL);
BLI_heap_insert(heap, path->weight, path);
- path = NULL;
+ path->group = group;
while (BLI_heap_size(heap)) {
- if (path)
- edge_free_path(pathbase, path);
+ VertData *vd;
+ EPathNode *last;
+ BMFace *f = NULL;
+
path = BLI_heap_popmin(heap);
- v1 = ((EPathNode*)path->nodes.last)->v;
+ last = path->nodes.last;
+ v1 = last->v;
- if (v1 == edge->v2) {
+ if (v1 == endv) {
/*make sure this path loop doesn't already exist*/
i = 0;
BLI_array_empty(verts);
@@ -159,33 +712,79 @@ EPath *edge_find_shortest_path(BMesh *bm, BMEdge *edge, EdgeData *edata, PathBas
verts[i] = node->v;
}
- if (!BM_Face_Exists(bm, verts, i, NULL))
- break;
- else
- continue;
+ if (BM_Face_Exists(bm, verts, i, &f)) {
+ if (!BMO_TestFlag(bm, f, FACE_IGNORE)) {
+ BLI_ghash_remove(gh, endv, NULL, NULL);
+ continue;
+ }
+ }
+ break;
}
-
- BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v1) {
- if (e == edge || !BMO_TestFlag(bm, e, EDGE_MARK))
- continue;
+
+ vd = vdata + BMINDEX_GET(v1);
+ if (!vd->e)
+ continue;
+
+ v2 = NULL;
+ while (1) {
+ if (!last->cure) {
+ last->cure = e = vdata[BMINDEX_GET(last->v)].e;
+ } else {
+ last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
+ if (last->cure == vdata[BMINDEX_GET(last->v)].e) {
+ v2 = NULL;
+ break;
+ }
+ }
- v2 = BM_OtherEdgeVert(e, v1);
+ if (e == edge || !BMO_TestFlag(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ v2 = BM_OtherEdgeVert(e, last->v);
- if (BLI_ghash_haskey(gh, v2))
+ if (BLI_ghash_haskey(gh, v2)) {
+ v2 = NULL;
continue;
+ }
+
+ if (use_restrict && BMO_InMap(bm, op, "restrict", e)) {
+ int group = BMO_Get_MapInt(bm, op, "restrict", e);
+
+ if (!(group & path->group)) {
+ v2 = NULL;
+ continue;
+ }
+ }
- BLI_ghash_insert(gh, v2, NULL);
-
- path2 = edge_copy_add_path(pathbase, path, v2, e);
- path2->weight = edge_weight_path(path2, edata);
-
- BLI_heap_insert(heap, path2->weight, path2);
+ break;
+ }
+
+ if (!v2) {
+ if (path) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+ continue;
}
+
+ /*add path back into heap*/
+ BLI_heap_insert(heap, path->weight, path);
+
+ /*put v2 in gh map*/
+ BLI_ghash_insert(gh, v2, NULL);
- if (BLI_heap_size(heap) == 0)
- path = NULL;
- }
+ path2 = edge_copy_add_path(pathbase, path, v2, e);
+ path2->weight = edge_weight_path(path2, edata, vdata);
+ BLI_heap_insert(heap, path2->weight, path2);
+ }
+
+ if (path && ((EPathNode*)path->nodes.last)->v != endv) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+
BLI_array_free(verts);
BLI_heap_free(heap, NULL);
BLI_ghash_free(gh, NULL, NULL);
@@ -193,26 +792,56 @@ EPath *edge_find_shortest_path(BMesh *bm, BMEdge *edge, EdgeData *edata, PathBas
return path;
}
+static int count_edge_faces(BMesh *bm, BMEdge *e) {
+ int i=0;
+ BMLoop *l = e->l;
+
+ if (!l)
+ return 0;
+
+ do {
+ if (!BMO_TestFlag(bm, l->f, FACE_IGNORE))
+ i++;
+
+ l = l->radial_next;
+ } while (l != e->l);
+
+ return i;
+}
+
void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
{
BMIter iter;
BMOIter siter;
- BMEdge *e, *edge;
BMFace *f;
+ BMEdge *e, *edge;
+ BMVert *v, **verts = NULL;
+ BLI_array_declare(verts);
EPath *path;
EPathNode *node;
EdgeData *edata;
+ VertData *vdata;
BMEdge **edges = NULL;
PathBase *pathbase = edge_pathbase_new();
BLI_array_declare(edges);
- int i;
+ int use_restrict = BMO_Get_Int(op, "use_restrict");
+ int i, j, group = 0;
if (!bm->totvert || !bm->totedge)
return;
edata = MEM_callocN(sizeof(EdgeData)*bm->totedge, "EdgeData");
+ vdata = MEM_callocN(sizeof(VertData)*bm->totvert, "VertData");
+
BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMO_Flag_Buffer(bm, op, "excludefaces", FACE_IGNORE, BM_FACE);
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(v, i);
+ i++;
+ }
+
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
BMO_SetFlag(bm, f, ELE_ORIG);
}
@@ -228,12 +857,38 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
i += 1;
}
+ init_rotsys(bm, edata, vdata);
+
while (1) {
edge = NULL;
-
+ group = 0;
+
BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ /*if restrict is on, only start on faces in the restrict map*/
+ if (use_restrict && !BMO_InMap(bm, op, "restrict", e))
+ continue;
+
if (edata[BMINDEX_GET(e)].tag < 2) {
edge = e;
+
+ if (use_restrict) {
+ int i=0, j=0, gi=0;
+
+ group = BMO_Get_MapInt(bm, op, "restrict", e);
+
+ for (i=0; i<30; i++) {
+ if (group & (1<<i)) {
+ j++;
+ gi = i;
+
+ if (j-1 == edata[BMINDEX_GET(e)].tag)
+ break;
+ }
+ }
+
+ group = 1<<gi;
+ }
+
break;
}
}
@@ -243,11 +898,12 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
edata[BMINDEX_GET(edge)].tag += 1;
- path = edge_find_shortest_path(bm, edge, edata, pathbase);
+ path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
if (!path)
continue;
BLI_array_empty(edges);
+ BLI_array_empty(verts);
i = 0;
for (node=path->nodes.first; node; node=node->next) {
if (!node->next)
@@ -262,23 +918,44 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
edata[BMINDEX_GET(e)].ftag++;
BLI_array_growone(edges);
edges[i++] = e;
+
+ BLI_array_append(verts, node->v);
}
BLI_array_growone(edges);
edges[i++] = edge;
+ edata[BMINDEX_GET(edge)].ftag++;
+
+ for (j=0; j<i; j++) {
+ if (count_edge_faces(bm, edges[j]) >= 2) {
+ edge_free_path(pathbase, path);
+ break;
+ }
+ }
+
+ if (j != i)
+ continue;
+
+ if (i) {
+ f = BM_Make_Ngon(bm, edge->v1, edge->v2, edges, i, 1);
+ if (f && !BMO_TestFlag(bm, f, ELE_ORIG)) {
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
- f = BM_Make_Ngon(bm, edge->v1, edge->v2, edges, i, 1);
- if (f && !BMO_TestFlag(bm, f, ELE_ORIG))
- BMO_SetFlag(bm, f, FACE_NEW);
-
+ if (use_restrict)
+ BMO_Insert_MapInt(bm, op, "faceout_groupmap", f, path->group);
+ }
+
edge_free_path(pathbase, path);
}
BMO_Flag_To_Slot(bm, op, "faceout", FACE_NEW, BM_FACE);
BLI_array_free(edges);
+ BLI_array_free(verts);
edge_pathbase_free(pathbase);
MEM_freeN(edata);
+ MEM_freeN(vdata);
}
/* evaluate if entire quad is a proper convex quad */
diff --git a/source/blender/bmesh/operators/mesh_conv.c b/source/blender/bmesh/operators/mesh_conv.c
index a45142a3c0b..942951c11c1 100644
--- a/source/blender/bmesh/operators/mesh_conv.c
+++ b/source/blender/bmesh/operators/mesh_conv.c
@@ -45,7 +45,8 @@
void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
Object *ob = BMO_Get_Pnt(op, "object");
Mesh *me = BMO_Get_Pnt(op, "mesh");
- MVert *mvert;
+ MVert *mvert, **verts = NULL;
+ BLI_array_declare(verts);
MEdge *medge;
MLoop *ml;
MPoly *mpoly;
@@ -185,14 +186,17 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
BMLoop *l;
BLI_array_empty(fedges);
+ BLI_array_empty(verts);
for (j=0; j<mpoly->totloop; j++) {
ml = &me->mloop[mpoly->loopstart+j];
v = vt[ml->v];
e = et[ml->e];
BLI_array_growone(fedges);
+ BLI_array_growone(verts);
fedges[j] = e;
+ verts[j] = v;
}
v1 = vt[me->mloop[mpoly->loopstart].v];
@@ -203,8 +207,8 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
v1 = fedges[0]->v2;
v2 = fedges[0]->v1;
}
-
- f = BM_Make_Ngon(bm, v1, v2, fedges, mpoly->totloop, 0);
+
+ f = BM_Make_Face(bm, verts, fedges, mpoly->totloop);
if (!f) {
printf("Warning! Bad face in mesh"
@@ -222,9 +226,11 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
if (i == me->act_face) bm->act_face = f;
/*Copy over loop customdata*/
+ j = 0;
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
- CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data);
+ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart+j, &l->head.data);
li++;
+ j++;
}
/*Copy Custom Data*/
diff --git a/source/blender/editors/include/ED_toolmode.h b/source/blender/editors/include/ED_toolmode.h
new file mode 100755
index 00000000000..733ca6c74fc
--- /dev/null
+++ b/source/blender/editors/include/ED_toolmode.h
@@ -0,0 +1,80 @@
+#if 0
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_TOOLMODE_H
+#define ED_TOOLMODE_H
+
+struct ID;
+struct View3D;
+struct ARegion;
+struct bContext;
+struct wmWindowManager;
+struct wmKeyConfig;
+struct ReportList;
+struct ViewContext;
+struct bDeformGroup;
+struct MDeformWeight;
+struct MDeformVert;
+struct Scene;
+struct Mesh;
+struct MCol;
+struct UvVertMap;
+struct UvMapVert;
+struct CustomData;
+struct BMEditMesh;
+struct BMEditSelection;
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+struct UvVertMap;
+struct UvMapVert;
+struct Material;
+struct Object;
+struct rcti;
+struct wmOperator;
+
+typedef struct ToolModeDefine {
+ short idtype, icon;
+ char *name;
+ void (*create)(void *args);
+ void (*free)(void *self);
+
+ /*called when mode is set active*/
+ void (*enter)(void *self, struct bContext *C);
+ void (*exit)(void *self, struct bContext *C);
+
+ /*called on draw*/
+ void (*draw)(void *self, struct bContext *C);
+ /*modal is option, and should be used carefully*/
+ void (*modal)(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+
+ /*keymap stuff*/
+ void (*create_keymap)(struct wmKeyConfig *km);
+ void (*keymap_poll)(struct bContext *C);
+};
+#endif
diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c
index dd86b2da9ee..0f24764f51f 100644
--- a/source/blender/editors/mesh/bmesh_select.c
+++ b/source/blender/editors/mesh/bmesh_select.c
@@ -440,7 +440,7 @@ BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict
}
/* returns labda for closest distance v1 to line-piece v2-v3 */
-static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
+float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
{
float rc[2], len;
@@ -564,9 +564,14 @@ BMFace *EDBM_findnearestface(ViewContext *vc, int *dist)
{
if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
- BMFace *efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
+ unsigned int index;
+ BMFace *efa;
+
+ view3d_validate_backbuf(vc);
+ index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
+ efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
+
if (efa) {
struct { short mval[2]; int dist; BMFace *toFace; } data;
diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c
index a614521cdba..ae37c6f9337 100644
--- a/source/blender/editors/mesh/bmesh_tools.c
+++ b/source/blender/editors/mesh/bmesh_tools.c
@@ -1357,7 +1357,7 @@ static int flip_normals(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
- if (!EDBM_CallOpf(em, op, "reversefaces facaes=%hf", BM_SELECT))
+ if (!EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT))
return OPERATOR_CANCELLED;
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
diff --git a/source/blender/editors/mesh/editbmesh_bvh.c b/source/blender/editors/mesh/editbmesh_bvh.c
index c0f82a0fe23..daa80dfe6e3 100644
--- a/source/blender/editors/mesh/editbmesh_bvh.c
+++ b/source/blender/editors/mesh/editbmesh_bvh.c
@@ -185,7 +185,7 @@ static void raycallback(void *userdata, int index, const BVHTreeRay *ray, BVHTre
{
BMBVHTree *tree = userdata;
BMLoop **ls = tree->em->looptris[index];
- float dist, uv[2], co1[3], co2[3], co3[3];
+ float dist, uv[2];
dist = ray_tri_intersection(ray, hit->dist, ls[0]->v->co, ls[1]->v->co,
ls[2]->v->co, uv, tree->epsilon);
@@ -195,16 +195,10 @@ static void raycallback(void *userdata, int index, const BVHTreeRay *ray, BVHTre
VECCOPY(hit->no, ls[0]->v->no);
- VECCOPY(co1, ls[0]->v->co);
- VECCOPY(co2, ls[1]->v->co);
- VECCOPY(co3, ls[2]->v->co);
-
- mul_v3_fl(co1, uv[0]);
- mul_v3_fl(co2, uv[1]);
- mul_v3_fl(co3, 1.0f-uv[0]-uv[1]);
-
- add_v3_v3v3(hit->co, co1, co2);
- add_v3_v3v3(hit->co, hit->co, co3);
+ copy_v3_v3(hit->co, ray->direction);
+ normalize_v3(hit->co);
+ mul_v3_fl(hit->co, dist);
+ add_v3_v3(hit->co, ray->origin);
}
}
@@ -227,6 +221,10 @@ BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout)
return NULL;
}
+BVHTree *BMBVH_BVHTree(BMBVHTree *tree)
+{
+ return tree->tree;
+}
static void vertsearchcallback(void *userdata, int index, const float *co, BVHTreeNearest *hit)
{
diff --git a/source/blender/editors/mesh/editbmesh_bvh.h b/source/blender/editors/mesh/editbmesh_bvh.h
index c64700b729f..328bd6507c7 100644
--- a/source/blender/editors/mesh/editbmesh_bvh.h
+++ b/source/blender/editors/mesh/editbmesh_bvh.h
@@ -4,6 +4,7 @@ struct BMEdge;
struct BMVert;
struct RegionView3D;
struct BMBVHTree;
+struct BVHTree;
#ifndef IN_EDITMESHBVH
typedef struct BMBVHTree BMBVHTree;
@@ -11,6 +12,7 @@ typedef struct BMBVHTree BMBVHTree;
struct BMBVHTree *BMBVH_NewBVH(struct BMEditMesh *em);
void BMBVH_FreeBVH(struct BMBVHTree *tree);
+struct BVHTree *BMBVH_BVHTree(struct BMBVHTree *tree);
struct BMFace *BMBVH_RayCast(struct BMBVHTree *tree, float *co, float *dir, float *hitout);
diff --git a/source/blender/editors/mesh/knifetool.c b/source/blender/editors/mesh/knifetool.c
new file mode 100755
index 00000000000..bbe0adc9d27
--- /dev/null
+++ b/source/blender/editors/mesh/knifetool.c
@@ -0,0 +1,1623 @@
+#if 1
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joseph Eagar, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "DNA_ID.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_object_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_editVert.h"
+#include "BLI_array.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_math.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_smallhash.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_scene.h"
+#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_depsgraph.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h" /* for paint cursor */
+
+#include "IMB_imbuf_types.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_view3d.h"
+#include "ED_mesh.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "mesh_intern.h"
+#include "editbmesh_bvh.h"
+
+#define MAXGROUP 30
+
+/* knifetool operator */
+typedef struct KnifeVert {
+ BMVert *v; /*non-NULL if this is an original vert*/
+ ListBase edges;
+
+ float co[3], sco[3]; /*sco is screen coordinates*/
+ short flag, draw, isface;
+} KnifeVert;
+
+typedef struct Ref {
+ struct Ref *next, *prev;
+ void *ref;
+} Ref;
+
+typedef struct KnifeEdge {
+ KnifeVert *v1, *v2;
+ BMFace *basef; /*face to restrict face fill to*/
+ ListBase faces;
+ int draw;
+
+ BMEdge *e, *oe; /*non-NULL if this is an original edge*/
+} KnifeEdge;
+
+#define KMAXDIST 12 /*max mouse distance from edge before not detecting it*/
+#define MARK 4
+#define DEL 8
+
+typedef struct BMEdgeHit {
+ BMEdge *e;
+ float hit[3];
+ float shit[3];
+ float l; /*lambda along line*/
+ BMVert *v; //set if snapped to a vert
+} BMEdgeHit;
+
+/* struct for properties used while drawing */
+typedef struct knifetool_opdata {
+ ARegion *ar; /* region that knifetool was activated in */
+ void *draw_handle; /* for drawing preview loop */
+ ViewContext vc;
+
+ Object *ob;
+ BMEditMesh *em;
+
+ MemArena *arena;
+
+ GHash *origvertmap;
+ GHash *origedgemap;
+
+ GHash *kedgefacemap;
+
+ BMBVHTree *bmbvh;
+
+ BLI_mempool *kverts;
+ BLI_mempool *kedges;
+
+ float vthresh;
+ float ethresh;
+
+ float vertco[3];
+ float prevco[3];
+
+ /*used for drag-cutting*/
+ BMEdgeHit *linehits;
+ int totlinehit;
+
+ /*if curedge is NULL, attach to curvert;
+ if curvert is NULL, attach to curbmface,
+ otherwise create null vert*/
+ KnifeEdge *curedge, *prevedge;
+ KnifeVert *curvert, *prevvert;
+ BMFace *curbmface, *prevbmface;
+
+ int totkedge, totkvert, cutnr;
+
+ BLI_mempool *refs;
+
+ float projmat[4][4];
+
+ enum {
+ MODE_IDLE,
+ MODE_DRAGGING,
+ MODE_CONNECT,
+ } mode;
+} knifetool_opdata;
+
+static ListBase *knife_get_face_kedges(knifetool_opdata *kcd, BMFace *f);
+
+static KnifeEdge *new_knife_edge(knifetool_opdata *kcd)
+{
+ kcd->totkedge++;
+ return BLI_mempool_calloc(kcd->kedges);
+}
+
+static KnifeVert *new_knife_vert(knifetool_opdata *kcd, float *co)
+{
+ KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
+
+ kcd->totkvert++;
+
+ copy_v3_v3(kfv->co, co);
+ copy_v3_v3(kfv->sco, co);
+
+ view3d_project_float(kcd->ar, kfv->co, kfv->sco, kcd->projmat);
+
+ return kfv;
+}
+
+/*get a KnifeVert wrapper for an existing BMVert*/
+static KnifeVert *get_bm_knife_vert(knifetool_opdata *kcd, BMVert *v)
+{
+ KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
+
+ if (!kfv) {
+ kfv = new_knife_vert(kcd, v->co);
+ kfv->v = v;
+ BLI_ghash_insert(kcd->origvertmap, v, kfv);
+ }
+
+ return kfv;
+}
+
+/*get a KnifeEdge wrapper for an existing BMEdge*/
+static KnifeEdge *get_bm_knife_edge(knifetool_opdata *kcd, BMEdge *e)
+{
+ KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
+ if (!kfe) {
+ Ref *ref;
+ BMIter iter;
+ BMFace *f;
+
+ kfe = new_knife_edge(kcd);
+ kfe->e = e;
+ kfe->v1 = get_bm_knife_vert(kcd, e->v1);
+ kfe->v2 = get_bm_knife_vert(kcd, e->v2);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v2->edges, ref);
+
+ BLI_ghash_insert(kcd->origedgemap, e, kfe);
+
+ BM_ITER(f, &iter, kcd->em->bm, BM_FACES_OF_EDGE, e) {
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = f;
+ BLI_addtail(&kfe->faces, ref);
+
+ /*ensures the kedges lst for this f is initialized,
+ it automatically adds kfe by itself*/
+ knife_get_face_kedges(kcd, f);
+ }
+ }
+
+ return kfe;
+}
+
+static void knife_start_cut(knifetool_opdata *kcd)
+{
+ kcd->prevedge = kcd->curedge;
+ kcd->prevvert = kcd->curvert;
+ kcd->prevbmface = kcd->curbmface;
+ kcd->cutnr++;
+
+ copy_v3_v3(kcd->prevco, kcd->vertco);
+}
+
+static Ref *find_ref(ListBase *lb, void *ref)
+{
+ Ref *ref1;
+
+ for (ref1=lb->first; ref1; ref1=ref1->next) {
+ if (ref1->ref == ref)
+ return ref1;
+ }
+
+ return NULL;
+}
+
+static ListBase *knife_get_face_kedges(knifetool_opdata *kcd, BMFace *f)
+{
+ ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
+
+ if (!lst) {
+ BMIter iter;
+ BMEdge *e;
+
+ lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
+ lst->first = lst->last = NULL;
+
+ BM_ITER(e, &iter, kcd->em->bm, BM_EDGES_OF_FACE, f) {
+ Ref *ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = get_bm_knife_edge(kcd, e);
+ BLI_addtail(lst, ref);
+ }
+
+ BLI_ghash_insert(kcd->kedgefacemap, f, lst);
+ }
+
+ return lst;
+}
+
+/*finds the proper face to restrict face fill to*/
+void knife_find_basef(knifetool_opdata *kcd, KnifeEdge *kfe)
+{
+ if (!kfe->basef) {
+ Ref *r1, *r2, *r3, *r4;
+
+ if (kfe->v1->isface || kfe->v2->isface) {
+ if (kfe->v2->isface)
+ kfe->basef = kcd->curbmface;
+ else
+ kfe->basef = kcd->prevbmface;
+ } else {
+ for (r1=kfe->v1->edges.first; r1 && !kfe->basef; r1=r1->next) {
+ KnifeEdge *ke1 = r1->ref;
+ for (r2=ke1->faces.first; r2 && !kfe->basef; r2=r2->next) {
+ for (r3=kfe->v2->edges.first; r3 && !kfe->basef; r3=r3->next) {
+ KnifeEdge *ke2 = r3->ref;
+
+ for (r4=ke2->faces.first; r4 && !kfe->basef; r4=r4->next) {
+ if (r2->ref == r4->ref) {
+ kfe->basef = r2->ref;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*ok, at this point kfe->basef should be set if any valid possibility
+ exists*/
+ }
+}
+
+static KnifeVert *knife_split_edge(knifetool_opdata *kcd, KnifeEdge *kfe, float co[3], KnifeEdge **newkfe_out)
+{
+ KnifeEdge *newkfe = new_knife_edge(kcd);
+ ListBase *lst;
+ Ref *ref;
+
+ newkfe->v1 = kfe->v1;
+ newkfe->v2 = new_knife_vert(kcd, co);
+ newkfe->v2->draw = 1;
+ newkfe->basef = kfe->basef;
+
+ ref = find_ref(&kfe->v1->edges, kfe);
+ BLI_remlink(&kfe->v1->edges, ref);
+
+ kfe->v1 = newkfe->v2;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ for (ref=kfe->faces.first; ref; ref=ref->next) {
+ Ref *ref2 = BLI_mempool_calloc(kcd->refs);
+
+ /*add kedge ref to bm faces*/
+ lst = knife_get_face_kedges(kcd, ref->ref);
+ ref2->ref = newkfe;
+ BLI_addtail(lst, ref2);
+
+ ref2 = BLI_mempool_calloc(kcd->refs);
+ ref2->ref = ref->ref;
+ BLI_addtail(&newkfe->faces, ref2);
+ }
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = newkfe;
+ BLI_addtail(&newkfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = newkfe;
+ BLI_addtail(&newkfe->v2->edges, ref);
+
+ newkfe->draw = kfe->draw;
+ newkfe->e = kfe->e;
+
+ *newkfe_out = newkfe;
+
+ return newkfe->v2;
+}
+
+static void knife_edge_append_face(knifetool_opdata *kcd, KnifeEdge *kfe, BMFace *f)
+{
+ ListBase *lst = knife_get_face_kedges(kcd, f);
+ Ref *ref = BLI_mempool_calloc(kcd->refs);
+
+ ref->ref = kfe;
+ BLI_addtail(lst, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = f;
+ BLI_addtail(&kfe->faces, ref);
+}
+
+static void knife_copy_edge_facelist(knifetool_opdata *kcd, KnifeEdge *dest, KnifeEdge *source)
+{
+ Ref *ref, *ref2;
+
+ for (ref2 = source->faces.first; ref2; ref2=ref2->next) {
+ ListBase *lst = knife_get_face_kedges(kcd, ref2->ref);
+
+ /*add new edge to face knife edge list*/
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = dest;
+ BLI_addtail(lst, ref);
+
+ /*add face to new edge's face list*/
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = ref2->ref;
+ BLI_addtail(&dest->faces, ref);
+ }
+}
+
+static void knife_add_single_cut(knifetool_opdata *kcd)
+{
+ KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL;
+ Ref *ref;
+
+ if (kcd->prevvert && kcd->prevvert == kcd->curvert)
+ return;
+ if (kcd->prevedge && kcd->prevedge == kcd->curedge)
+ return;
+
+ if (kcd->prevvert) {
+ kfe->v1 = kcd->prevvert;
+ } else if (kcd->prevedge) {
+ kfe->v1 = knife_split_edge(kcd, kcd->prevedge, kcd->prevco, &kfe2);
+ } else {
+ kfe->v1 = new_knife_vert(kcd, kcd->prevco);
+ kfe->v1->draw = 1;
+ kfe->v1->isface = 1;
+ }
+
+ if (kcd->curvert) {
+ kfe->v2 = kcd->curvert;
+ } else if (kcd->curedge) {
+ kfe->v2 = knife_split_edge(kcd, kcd->curedge, kcd->vertco, &kfe3);
+
+ kcd->curvert = kfe->v2;
+ } else {
+ kfe->v2 = new_knife_vert(kcd, kcd->vertco);
+ kfe->v2->draw = 1;
+ kfe->v2->isface = 1;
+
+ kcd->curvert = kfe->v2;
+ }
+
+ knife_find_basef(kcd, kfe);
+
+ kfe->draw = 1;
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v2->edges, ref);
+
+ if (kfe->basef && !find_ref(&kfe->faces, kfe->basef))
+ knife_edge_append_face(kcd, kfe, kfe->basef);
+
+ /*sanity check to make sure we're in the right edge/face lists*/
+ if (kcd->curbmface) {
+ if (!find_ref(&kfe->faces, kcd->curbmface)) {
+ knife_edge_append_face(kcd, kfe, kcd->curbmface);
+ }
+
+ if (kcd->prevbmface && kcd->prevbmface != kcd->curbmface) {
+ if (!find_ref(&kfe->faces, kcd->prevbmface)) {
+ knife_edge_append_face(kcd, kfe, kcd->prevbmface);
+ }
+ }
+ }
+
+ /*set up for next cut*/
+ kcd->prevbmface = kcd->curbmface;
+ kcd->prevvert = kcd->curvert;
+ kcd->prevedge = kcd->curedge;
+ copy_v3_v3(kcd->prevco, kcd->vertco);
+}
+
+static int verge_linehit(const void *vlh1, const void *vlh2)
+{
+ const BMEdgeHit *lh1=vlh1, *lh2=vlh2;
+
+ if (lh1->l < lh2->l) return -1;
+ else if (lh1->l > lh2->l) return 1;
+ else return 0;
+}
+
+static void knife_add_cut(knifetool_opdata *kcd)
+{
+ BMEditMesh *em = kcd->em;
+ BMesh *bm = em->bm;
+ knifetool_opdata oldkcd = *kcd;
+
+ if (kcd->linehits) {
+ BMEdgeHit *lh, *lastlh, *firstlh;
+ int i;
+
+ qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
+
+ lh = kcd->linehits;
+ lastlh = firstlh = NULL;
+ for (i=0; i<kcd->totlinehit; i++, (lastlh=lh), lh++) {
+ if (lastlh && len_v3v3(lastlh->hit, lh->hit) == 0.0f) {
+ if (!firstlh)
+ firstlh = lastlh;
+ continue;
+ } else if (lastlh && firstlh) {
+ if (firstlh->v || lastlh->v) {
+ BMVert *bmv = firstlh->v ? firstlh->v : lastlh->v;
+
+ kcd->prevvert = get_bm_knife_vert(kcd, bmv);
+ copy_v3_v3(kcd->prevco, firstlh->hit);
+ kcd->prevedge = NULL;
+ kcd->prevbmface = firstlh->e->l ? firstlh->e->l->f : NULL;
+ }
+ lastlh = firstlh = NULL;
+ }
+
+ if (!lastlh && len_v3v3(kcd->prevco, lh->hit) < FLT_EPSILON*10)
+ continue;
+
+ kcd->curedge = get_bm_knife_edge(kcd, lh->e);
+ kcd->curbmface = kcd->curedge->e->l ? kcd->curedge->e->l->f : NULL;
+ kcd->curvert = lh->v ? get_bm_knife_vert(kcd, lh->v) : NULL;
+ copy_v3_v3(kcd->vertco, lh->hit);
+
+ knife_add_single_cut(kcd);
+ }
+
+ kcd->curbmface = oldkcd.curbmface;
+ kcd->curvert = oldkcd.curvert;
+ kcd->curedge = oldkcd.curedge;
+ copy_v3_v3(kcd->vertco, oldkcd.vertco);
+
+ knife_add_single_cut(kcd);
+
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ } else {
+ knife_add_single_cut(kcd);
+ }
+}
+
+static void knife_finish_cut(knifetool_opdata *kcd)
+{
+
+}
+
+/* modal loop selection drawing callback */
+static void knifetool_draw(const bContext *C, ARegion *ar, void *arg)
+{
+ knifetool_opdata *kcd = arg;
+
+ glDisable(GL_DEPTH_TEST);
+
+ glPushMatrix();
+ glMultMatrixf(kcd->ob->obmat);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ glColor3f(0.1, 0.1, 0.1);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINES);
+ glVertex3fv(kcd->prevco);
+ glVertex3fv(kcd->vertco);
+ glEnd();
+
+ glLineWidth(1.0);
+ }
+
+ if (kcd->curedge) {
+ glColor3f(0.5, 0.3, 0.15);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINES);
+ glVertex3fv(kcd->curedge->v1->co);
+ glVertex3fv(kcd->curedge->v2->co);
+ glEnd();
+
+ glLineWidth(1.0);
+ } else if (kcd->curvert) {
+ glColor3f(0.8, 0.2, 0.1);
+ glPointSize(9);
+
+ glBegin(GL_POINTS);
+ glVertex3fv(kcd->vertco);
+ glEnd();
+ }
+
+ if (kcd->curbmface) {
+ glColor3f(0.1, 0.8, 0.05);
+ glPointSize(7);
+
+ glBegin(GL_POINTS);
+ glVertex3fv(kcd->vertco);
+ glEnd();
+ }
+
+ if (kcd->totlinehit > 0) {
+ BMEdgeHit *lh;
+ int i;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /*draw any snapped verts first*/
+ glColor4f(0.8, 0.2, 0.1, 0.4);
+ glPointSize(9);
+ glBegin(GL_POINTS);
+ lh = kcd->linehits;
+ for (i=0; i<kcd->totlinehit; i++, lh++) {
+ float sv1[3], sv2[3];
+
+ view3d_project_float_v3(kcd->ar, lh->e->v1->co, sv1, kcd->projmat);
+ view3d_project_float_v3(kcd->ar, lh->e->v2->co, sv2, kcd->projmat);
+
+ if (len_v2v2(lh->shit, sv1) < kcd->vthresh/4) {
+ copy_v3_v3(lh->hit, lh->e->v1->co);
+ glVertex3fv(lh->hit);
+ lh->v = lh->e->v1;
+ } else if (len_v2v2(lh->shit, sv2) < kcd->vthresh/4) {
+ copy_v3_v3(lh->hit, lh->e->v2->co);
+ glVertex3fv(lh->hit);
+ lh->v = lh->e->v2;
+ }
+ }
+ glEnd();
+
+ /*now draw the rest*/
+ glColor4f(0.1, 0.8, 0.05, 0.4);
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ lh = kcd->linehits;
+ for (i=0; i<kcd->totlinehit; i++, lh++) {
+ glVertex3fv(lh->hit);
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+ }
+
+ if (kcd->totkedge > 0) {
+ BLI_mempool_iter iter;
+ KnifeEdge *kfe;
+
+ glLineWidth(1.0);
+ glBegin(GL_LINES);
+
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ if (!kfe->draw)
+ continue;
+
+ glColor3f(0.2, 0.2, 0.2);
+
+ glVertex3fv(kfe->v1->co);
+ glVertex3fv(kfe->v2->co);
+ }
+
+ glEnd();
+ glLineWidth(1.0);
+ }
+
+ if (kcd->totkvert > 0) {
+ BLI_mempool_iter iter;
+ KnifeVert *kfv;
+
+ glPointSize(4.0);
+
+ glBegin(GL_POINTS);
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv=BLI_mempool_iterstep(&iter); kfv; kfv=BLI_mempool_iterstep(&iter)) {
+ if (!kfv->draw)
+ continue;
+
+ glColor3f(0.6, 0.1, 0.2);
+
+ glVertex3fv(kfv->co);
+ }
+
+ glEnd();
+ }
+
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
+BMEdgeHit *knife_edge_tri_isect(knifetool_opdata *kcd, BMBVHTree *bmtree, float v1[3],
+ float v2[3], float v3[3], bglMats *mats, int *count)
+{
+ BVHTree *tree2 = BLI_bvhtree_new(3, FLT_EPSILON*4, 8, 8), *tree = BMBVH_BVHTree(bmtree);
+ BMEdgeHit *edges = NULL;
+ BLI_array_declare(edges);
+ SmallHash hash, *ehash = &hash;
+ BVHTreeOverlap *results, *result;
+ BMLoop *l, **ls;
+ float cos[9], uv[3], lambda;
+ int tot=0, i, j;
+
+ BLI_smallhash_init(ehash);
+
+ copy_v3_v3(cos, v1);
+ copy_v3_v3(cos+3, v2);
+ copy_v3_v3(cos+6, v3);
+
+ BLI_bvhtree_insert(tree2, 0, cos, 3);
+ BLI_bvhtree_balance(tree2);
+
+ result = results = BLI_bvhtree_overlap(tree, tree2, &tot);
+
+ for (i=0; i<tot; i++, result++) {
+ float p[3];
+
+ ls = (BMLoop**)kcd->em->looptris[result->indexA];
+
+ for (j=0; j<3; j++) {
+ if (isect_line_tri_v3(ls[j]->e->v1->co, ls[j]->e->v2->co, v1, v2, v3, &lambda, uv)) {
+ float no[3], view[3], sp[3];
+
+ sub_v3_v3v3(p, ls[j]->e->v2->co, ls[j]->e->v1->co);
+ mul_v3_fl(p, lambda);
+ add_v3_v3(p, ls[j]->e->v1->co);
+
+ view3d_project_float_v3(kcd->ar, p, sp, kcd->projmat);
+ view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
+ sub_v3_v3v3(view, p, view);
+ normalize_v3(view);
+
+ copy_v3_v3(no, view);
+ mul_v3_fl(no, -0.00001);
+
+ /*go backwards toward view a bit*/
+ add_v3_v3(p, no);
+
+ if (!BMBVH_RayCast(bmtree, p, no, NULL) && !BLI_smallhash_haskey(ehash, (intptr_t)ls[j]->e)) {
+ BMEdgeHit hit;
+
+ hit.e = ls[j]->e;
+ hit.v = NULL;
+ copy_v3_v3(hit.hit, p);
+ view3d_project_float_v3(kcd->ar, hit.hit, hit.shit, kcd->projmat);
+
+ BLI_array_append(edges, hit);
+ BLI_smallhash_insert(ehash, (intptr_t)ls[j]->e, NULL);
+ }
+ }
+ }
+ }
+
+ BLI_smallhash_release(ehash);
+
+ if (results)
+ MEM_freeN(results);
+
+ *count = BLI_array_count(edges);
+ return edges;
+}
+
+/*finds (visible) edges that intersects the current screen drag line*/
+static void knife_find_line_hits(knifetool_opdata *kcd)
+{
+ bglMats mats;
+ BMEdgeHit *e1, *e2;
+ float v1[3], v2[3], v3[3], v4[4], s1[3], s2[3], view[3];
+ int i, c1, c2;
+
+ bgl_get_mats(&mats);
+
+ if (kcd->linehits) {
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ }
+
+ /*project screen line's 3d coordinates back into 2d*/
+ view3d_project_float_v3(kcd->ar, kcd->prevco, s1, kcd->projmat);
+ view3d_project_float_v3(kcd->ar, kcd->vertco, s2, kcd->projmat);
+
+ if (len_v2v2(s1, s2) < 1)
+ return;
+
+ /*unproject screen line*/
+ view3d_unproject(&mats, v1, s1[0], s1[1], 0.0f);
+ view3d_unproject(&mats, v2, s2[0], s2[1], 0.0f);
+ view3d_unproject(&mats, v3, s1[0], s1[1], 1.0f-FLT_EPSILON);
+ view3d_unproject(&mats, v4, s2[0], s2[1], 1.0f-FLT_EPSILON);
+
+ mul_m4_v3(kcd->ob->imat, v1);
+ mul_m4_v3(kcd->ob->imat, v2);
+ mul_m4_v3(kcd->ob->imat, v3);
+ mul_m4_v3(kcd->ob->imat, v4);
+
+ sub_v3_v3v3(view, v4, v1);
+ normalize_v3(view);
+
+ /*test two triangles of sceen line's plane*/
+ e1 = knife_edge_tri_isect(kcd, kcd->bmbvh, v1, v2, v3, &mats, &c1);
+ e2 = knife_edge_tri_isect(kcd, kcd->bmbvh, v1, v3, v4, &mats, &c2);
+ if (c1 && c2) {
+ e1 = MEM_reallocN(e1, sizeof(BMEdgeHit)*(c1+c2));
+ memcpy(e1+c1, e2, sizeof(BMEdgeHit)*c2);
+ MEM_freeN(e2);
+ } else if (c2) {
+ e1 = e2;
+ }
+
+ kcd->linehits = e1;
+ kcd->totlinehit = c1+c2;
+
+ /*find position along screen line, used for sorting*/
+ for (i=0; i<kcd->totlinehit; i++) {
+ BMEdgeHit *lh = e1+i;
+
+ lh->l = len_v2v2(lh->shit, s1) / len_v2v2(s2, s1);
+ }
+}
+
+static BMFace *knife_find_closest_face(knifetool_opdata *kcd, float co[3])
+{
+ BMFace *f;
+ bglMats mats;
+ float origin[3], ray[3];
+ float mval[2];
+ int dist = KMAXDIST;
+
+ bgl_get_mats(&mats);
+
+ mval[0] = kcd->vc.mval[0]; mval[1] = kcd->vc.mval[1];
+
+ /*unproject to find view ray*/
+ view3d_unproject(&mats, origin, mval[0], mval[1], 0.0f);
+
+ sub_v3_v3v3(ray, origin, kcd->vc.rv3d->viewinv[3]);
+ normalize_v3(ray);
+
+ /*transform into object space*/
+ mul_m4_v3(kcd->ob->imat, origin);
+ mul_m4_v3(kcd->ob->imat, ray);
+
+ f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co);
+ if (!f) {
+ /*try to use backbuffer selection method if ray casting failed*/
+ f = EDBM_findnearestface(&kcd->vc, &dist);
+
+ /*cheat for now; just put in the origin instead
+ of a true coordinate on the face*/
+ copy_v3_v3(co, origin);
+ }
+
+ //copy_v3_v3(co, origin);
+
+ return f;
+}
+
+/*find the 2d screen space density of vertices within a radius. used to scale snapping
+ distance for picking edges/verts.*/
+static int knife_sample_screen_density(knifetool_opdata *kcd, float radius)
+{
+ BMFace *f;
+ float co[3], sco[3];
+
+ f = knife_find_closest_face(kcd, co);
+
+ if (f) {
+ ListBase *lst;
+ Ref *ref;
+ KnifeVert *curv = NULL;
+ float dis;
+ int c = 0;
+
+ view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
+
+ for (i=0; i<2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+
+ view3d_project_float_v3(kcd->ar, kfv->co, kfv->sco, kcd->projmat);
+
+ dis = len_v2v2(kfv->sco, sco);
+ if (dis < radius) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ copy_v3_v3(vec, kfv->co);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ }
+
+ return c;
+ }
+
+ return 0;
+}
+
+/*returns snapping distance for edges/verts, scaled by the density of the
+ surrounding mesh (in screen space)*/
+static float knife_snap_size(knifetool_opdata *kcd, float maxsize)
+{
+ float density = (float)knife_sample_screen_density(kcd, maxsize*2.0f);
+
+ density = MAX2(density, 1);
+
+ return MIN2(maxsize / (density*0.5f), maxsize);
+}
+
+/*p is closest point on edge to the mouse cursor*/
+static KnifeEdge *knife_find_closest_edge(knifetool_opdata *kcd, float p[3], BMFace **fptr)
+{
+ BMFace *f;
+ float co[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh);
+
+ f = knife_find_closest_face(kcd, co);
+ /*set p to co, in case we don't find anything, means a face cut*/
+ copy_v3_v3(p, co);
+
+ if (f) {
+ KnifeEdge *cure = NULL;
+ ListBase *lst;
+ Ref *ref;
+ float dis, curdis=FLT_MAX;
+
+ view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat);
+
+ /*look through all edges associated with this face*/
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+
+ /*project edge vertices into screen space*/
+ view3d_project_float_v3(kcd->ar, kfe->v1->co, kfe->v1->sco, kcd->projmat);
+ view3d_project_float_v3(kcd->ar, kfe->v2->co, kfe->v2->sco, kcd->projmat);
+
+ dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
+ if (dis < curdis && dis < maxdist) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float labda_PdistVL2Dfl(float *v1, float *v2, float *v3);
+ float labda= labda_PdistVL2Dfl(sco, kfe->v1->sco, kfe->v2->sco);
+ float vec[3];
+
+ vec[0]= kfe->v1->co[0] + labda*(kfe->v2->co[0] - kfe->v1->co[0]);
+ vec[1]= kfe->v1->co[1] + labda*(kfe->v2->co[1] - kfe->v1->co[1]);
+ vec[2]= kfe->v1->co[2] + labda*(kfe->v2->co[2] - kfe->v1->co[2]);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ cure = kfe;
+ curdis = dis;
+ }
+ } else {
+ cure = kfe;
+ curdis = dis;
+ }
+ }
+ }
+
+ if (fptr)
+ *fptr = f;
+
+ if (cure && p) {
+ closest_to_line_segment_v3(p, co, cure->v1->co, cure->v2->co);
+ }
+
+ return cure;
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
+}
+
+/*find a vertex near the mouse cursor, if it exists*/
+static KnifeVert *knife_find_closest_vert(knifetool_opdata *kcd, float p[3], BMFace **fptr)
+{
+ BMFace *f;
+ float co[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh);
+
+ f = knife_find_closest_face(kcd, co);
+ /*set p to co, in case we don't find anything, means a face cut*/
+ copy_v3_v3(p, co);
+
+ if (f) {
+ ListBase *lst;
+ Ref *ref;
+ KnifeVert *curv = NULL;
+ float dis, curdis=FLT_MAX;
+
+ view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
+
+ for (i=0; i<2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+
+ view3d_project_float_v3(kcd->ar, kfv->co, kfv->sco, kcd->projmat);
+
+ dis = len_v2v2(kfv->sco, sco);
+ if (dis < curdis && dis < maxdist) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ copy_v3_v3(vec, kfv->co);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ curv = kfv;
+ curdis = dis;
+ }
+ } else {
+ curv = kfv;
+ curdis = dis;
+ }
+ }
+ }
+ }
+
+ if (fptr)
+ *fptr = f;
+
+ if (curv && p) {
+ copy_v3_v3(p, curv->co);
+ }
+
+ return curv;
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
+}
+
+/*update active knife edge/vert pointers*/
+static int knife_update_active(knifetool_opdata *kcd)
+{
+ kcd->curvert = NULL; kcd->curedge = NULL; kcd->curbmface = NULL;
+
+ kcd->curvert = knife_find_closest_vert(kcd, kcd->vertco, &kcd->curbmface);
+ if (!kcd->curvert)
+ kcd->curedge = knife_find_closest_edge(kcd, kcd->vertco, &kcd->curbmface);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_find_line_hits(kcd);
+ }
+ return 1;
+}
+
+#define VERT_ON_EDGE 8
+#define VERT_ORIG 16
+#define FACE_FLIP 32
+
+/*use edgenet to fill faces. this is a bit annoying and convoluted.*/
+void knifenet_fill_faces(knifetool_opdata *kcd)
+{
+ BLI_mempool_iter iter;
+ BMOperator bmop;
+ BMesh *bm = kcd->em->bm;
+ BMOIter siter;
+ BMIter bmiter;
+ BMFace *f;
+ BMEdge *e;
+ KnifeVert *kfv;
+ KnifeEdge *kfe;
+ float (*vertcos)[3] = NULL;
+ void **blocks = NULL;
+ BLI_array_declare(blocks);
+ BLI_array_declare(vertcos);
+ float *w = NULL;
+ BLI_array_declare(w);
+
+ BMO_push(bm, NULL);
+
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_MESH, NULL) {
+ BMINDEX_SET(f, 0);
+ }
+
+ /*assign a bit flag to each face. adjacent
+ faces cannot share the same bit flag, nor can
+ diagonally adjacent faces*/
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_MESH, NULL) {
+ BMIter bmiter2;
+ BMLoop *l;
+ int group = 0, ok=0;
+
+ while (!ok) {
+ ok = 1;
+ BM_ITER(l, &bmiter2, bm, BM_LOOPS_OF_FACE, f) {
+ BMLoop *l2 = l->radial_next;
+ while (l2 != l) {
+ BMLoop *l3;
+ BMIter bmiter3;
+
+ if (l2->f == l->f) {
+ l2 = l2->radial_next;
+ continue;
+ }
+
+ if (BMINDEX_GET(l2->f) == (1<<group) && group <= MAXGROUP) {
+ group++;
+ ok = 0;
+ } else if (BMINDEX_GET(l2->f) == (1<<group)) {
+ printf("yeek! ran out of groups! 1\n");
+ }
+
+ BM_ITER(l3, &bmiter3, bm, BM_LOOPS_OF_FACE, l2->f) {
+ BMLoop *l4 = l3->radial_next;
+
+ do {
+ if (l4->f == l->f) {
+ l4 = l4->radial_next;
+ continue;
+ }
+
+ if (BMINDEX_GET(l4->f) == (1<<group) && group <= MAXGROUP) {
+ group++;
+ ok = 0;
+ } else if (BMINDEX_GET(l4->f) == (1<<group)) {
+ printf("yeek! ran out of groups! 2`\n");
+ }
+
+ l4 = l4->radial_next;
+ } while (l4 != l3);
+ }
+
+ l2 = l2->radial_next;
+ }
+ }
+ }
+
+ BMINDEX_SET(f, (1<<group));
+ }
+
+ /*turn knife verts into real verts, as necassary*/
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv=BLI_mempool_iterstep(&iter); kfv; kfv=BLI_mempool_iterstep(&iter)) {
+ if (!kfv->v) {
+ kfv->v = BM_Make_Vert(bm, kfv->co, NULL);
+ kfv->flag = 1;
+ } else {
+ kfv->flag = 0;
+ BMO_SetFlag(bm, kfv->v, VERT_ORIG);
+ }
+
+ BMO_SetFlag(bm, kfv->v, MARK);
+ }
+
+ BMO_InitOpf(bm, &bmop, "edgenet_fill use_restrict=%i", 1);
+
+ /*turn knife edges into real edges, and assigns bit masks representing
+ the faces they are adjacent too*/
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ int group = 0;
+
+ if (!kfe->v1 || !kfe->v2)
+ continue;
+
+ if (kfe->e) {
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_EDGE, kfe->e) {
+ group |= BMINDEX_GET(f);
+
+ if (kfe->v1->v != kfe->e->v1 || kfe->v2->v != kfe->e->v2) {
+ BMO_SetFlag(bm, f, DEL);
+ }
+ }
+
+ kfe->oe = kfe->e;
+
+ if (kfe->v1->v != kfe->e->v1 || kfe->v2->v != kfe->e->v2) {
+ BMO_SetFlag(bm, kfe->e, DEL);
+ BMO_ClearFlag(bm, kfe->e, MARK);
+
+ if (kfe->v1->v != kfe->e->v1)
+ BMO_SetFlag(bm, kfe->v1->v, VERT_ON_EDGE);
+ if (kfe->v2->v != kfe->e->v2)
+ BMO_SetFlag(bm, kfe->v2->v, VERT_ON_EDGE);
+
+ kfe->e = NULL;
+ }
+ }
+
+ if (!kfe->e) {
+ kfe->e = BM_Make_Edge(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
+ }
+
+ BMO_SetFlag(bm, kfe->e, MARK);
+
+ if (kfe->basef) {
+ BMEdge *e;
+ BM_ITER(e, &bmiter, bm, BM_EDGES_OF_FACE, kfe->basef) {
+ BMO_SetFlag(bm, e, MARK);
+ }
+
+ BMO_SetFlag(bm, kfe->basef, DEL);
+ group |= BMINDEX_GET(kfe->basef);
+ }
+
+ if (!group) {
+ Ref *ref;
+
+ for (ref=kfe->faces.first; ref; ref=ref->next) {
+ kfe->basef = ref->ref;
+ group |= BMINDEX_GET(ref->ref);
+ }
+ }
+
+ if (group)
+ BMO_Insert_MapInt(bm, &bmop, "restrict", kfe->e, group);
+ else
+ printf("yeek!\n");
+ }
+
+ /*not sure why this is needed, sanity check to make sure del'd edges are not
+ marked as well*/
+ BM_ITER(e, &bmiter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e, DEL))
+ BMO_ClearFlag(bm, e, MARK);
+ }
+
+ BMO_Flag_To_Slot(bm, &bmop, "edges", MARK, BM_EDGE);
+ BMO_Flag_To_Slot(bm, &bmop, "excludefaces", DEL, BM_FACE);
+
+ /*execute the edgenet fill operator. it will restrict filled faces to edges
+ belonging to the same group (note edges can belong to multiple groups, using
+ bitmasks)*/
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Flag_Buffer(bm, &bmop, "faceout", MARK, BM_FACE);
+
+ BM_Compute_Normals(bm);
+
+ //void interp_weights_poly_v3(float *w,float v[][3], int n, float *co)
+
+ /* interpolate customdata */
+
+ /*first deal with interpolating vertices that lie on original edges*/
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ BMLoop *l1, *l2;
+ float fac, w[2];
+ void *blocks[2];
+
+ if (!kfe->oe)
+ continue;
+
+ BM_ITER(l1, &bmiter, bm, BM_LOOPS_OF_EDGE, kfe->oe) {
+ BMLoop *l2 = NULL;
+ BMIter liter;
+ int i, j;
+
+ BM_ITER(l2, &liter, bm, BM_LOOPS_OF_EDGE, kfe->e) {
+ if (!BM_Vert_In_Edge(kfe->e, l2->next->v)) {
+ l2 = l2->prev;
+ }
+
+ if (!BMO_InMap(bm, &bmop, "faceout_groupmap", l2->f))
+ continue;
+
+ if (BMINDEX_GET(l1->f) == BMO_Get_MapInt(bm, &bmop, "faceout_groupmap", l2->f))
+ break;
+ }
+
+ if (!l2)
+ continue;
+
+ if (dot_v3v3(l1->f->no, l2->f->no) < 0.0f) {
+ BMO_SetFlag(bm, l2->f, FACE_FLIP);
+ }
+
+ for (i=0; i<2; i++) {
+ if (i)
+ l2 = l2->next;
+
+ fac = len_v3v3(kfe->oe->v1->co, l2->v->co) / (len_v3v3(kfe->oe->v1->co, kfe->oe->v2->co)+FLT_EPSILON);
+
+ if (kfe->oe->v1 == l1->v) {
+ w[0] = 1.0-fac;
+ w[1] = fac;
+ } else {
+ w[0] = fac;
+ w[1] = 1.0-fac;
+ }
+
+ if (l1->e == kfe->oe) {
+ blocks[0] = l1->head.data;
+ blocks[1] = l1->next->head.data;
+ } else {
+ blocks[0] = l1->prev->head.data;
+ blocks[1] = l1->head.data;
+ }
+
+ BM_Copy_Attributes(bm, bm, l1->f, l2->f);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, 2, l2->head.data);
+ }
+ }
+ }
+
+ /*ensure normals are correct*/
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, f, FACE_FLIP)) {
+ BM_flip_normal(bm, f);
+ }
+ }
+
+ /*now deal with interior vertex interpolation
+ still kindof buggy*/
+ BMO_ITER(f, &siter, bm, &bmop, "faceout_groupmap", BM_FACE) {
+ BMLoop *l1, *l2;
+ BMFace *f2;
+ BMIter liter1, liter2;
+ int group = *(int*)BMO_IterMapVal(&siter);
+
+ BM_ITER(l1, &liter1, bm, BM_LOOPS_OF_FACE, f) {
+ float co[3], hit[3];
+ float dir[3];
+ int i;
+
+ if (BMO_TestFlag(bm, l1->v, VERT_ORIG) || BMO_TestFlag(bm, l1->v, VERT_ON_EDGE))
+ continue;
+
+ copy_v3_v3(co, l1->v->co);
+ copy_v3_v3(dir, l1->v->no);
+ mul_v3_fl(dir, 0.001f);
+
+ add_v3_v3(co, dir);
+ copy_v3_v3(dir, l1->v->no);
+ mul_v3_fl(dir, -1.0);
+
+ f2 = BMBVH_RayCast(kcd->bmbvh, co, dir, hit);
+ if (!f2) {
+ printf("eek!!\n");
+ continue;
+ }
+
+ BLI_array_empty(vertcos);
+ BLI_array_empty(blocks);
+ BLI_array_empty(w);
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, f2) {
+ BLI_array_growone(vertcos);
+ BLI_array_append(blocks, l2->head.data);
+
+ copy_v3_v3(vertcos[BLI_array_count(vertcos)-1], l2->v->co);
+ BLI_array_append(w, 0.0f);
+ }
+
+ BM_Copy_Attributes(bm, bm, f2, f);
+
+ interp_weights_poly_v3(w, vertcos, f2->len, l1->v->co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, BLI_array_count(blocks), l1->head.data);
+ }
+ }
+
+ BMO_Finish_Op(bm, &bmop);
+
+ /*delete left over faces*/
+ BMO_CallOpf(bm, "del geom=%ff context=%i", DEL, DEL_ONLYFACES);
+ BMO_CallOpf(bm, "del geom=%fe context=%i", DEL, DEL_EDGES);
+
+ BMO_pop(bm);
+}
+
+/*called on tool confirmation*/
+static void knifetool_finish(bContext *C, wmOperator *op)
+{
+ knifetool_opdata *kcd= op->customdata;
+
+ knifenet_fill_faces(kcd);
+}
+
+void knife_recalc_projmat(knifetool_opdata *kcd)
+{
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ view3d_get_object_project_mat(kcd->ar->regiondata, kcd->ob, kcd->projmat);
+}
+
+/* called when modal loop selection is done... */
+static void knifetool_exit (bContext *C, wmOperator *op)
+{
+ knifetool_opdata *kcd= op->customdata;
+
+ if (!kcd)
+ return;
+
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+
+ /* free the custom data */
+ BLI_mempool_destroy(kcd->refs);
+ BLI_mempool_destroy(kcd->kverts);
+ BLI_mempool_destroy(kcd->kedges);
+
+ BLI_ghash_free(kcd->origedgemap, NULL, NULL);
+ BLI_ghash_free(kcd->origvertmap, NULL, NULL);
+ BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
+
+ BMBVH_FreeBVH(kcd->bmbvh);
+ BLI_memarena_free(kcd->arena);
+
+ /* tag for redraw */
+ ED_region_tag_redraw(kcd->ar);
+
+ /* destroy kcd itself */
+ MEM_freeN(kcd);
+ op->customdata= NULL;
+}
+
+/* called when modal loop selection gets set up... */
+static int knifetool_init (bContext *C, wmOperator *op, int do_cut)
+{
+ knifetool_opdata *kcd;
+
+ /* alloc new customdata */
+ kcd= op->customdata= MEM_callocN(sizeof(knifetool_opdata), "knifetool Modal Op Data");
+
+ /* assign the drawing handle for drawing preview line... */
+ kcd->ar= CTX_wm_region(C);
+ kcd->draw_handle= ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
+ em_setup_viewcontext(C, &kcd->vc);
+
+ kcd->ob = CTX_data_edit_object(C);
+ kcd->em= ((Mesh *)kcd->ob->data)->edit_btmesh;
+ kcd->bmbvh = BMBVH_NewBVH(kcd->em);
+ kcd->arena = BLI_memarena_new(1<<15, "knife");
+ kcd->vthresh = KMAXDIST-1;
+ kcd->ethresh = KMAXDIST;
+
+ knife_recalc_projmat(kcd);
+
+ ED_region_tag_redraw(kcd->ar);
+
+ kcd->refs = BLI_mempool_create(sizeof(Ref), 1, 2048, 0, 0);
+ kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 1, 512, 0, 1);
+ kcd->kedges = BLI_mempool_create(sizeof(KnifeEdge), 1, 512, 0, 1);
+
+ kcd->origedgemap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origedgemap");
+ kcd->origvertmap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origvertmap");
+ kcd->kedgefacemap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origvertmap");
+
+ return 1;
+}
+
+static int knifetool_cancel (bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ knifetool_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+static int knifetool_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ knifetool_opdata *kcd;
+
+ view3d_operator_needs_opengl(C);
+
+ if (!knifetool_init(C, op, 0))
+ return OPERATOR_CANCELLED;
+
+ /* add a modal handler for this operator - handles loop selection */
+ WM_event_add_modal_handler(C, op);
+
+ kcd = op->customdata;
+ kcd->vc.mval[0] = evt->mval[0];
+ kcd->vc.mval[1] = evt->mval[1];
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
+{
+ knifetool_opdata *kcd= op->customdata;
+
+ view3d_operator_needs_opengl(C);
+
+ switch (event->type) {
+ case ESCKEY:
+ case RETKEY: /* confirm */ // XXX hardcoded
+ if (event->val == KM_RELEASE) {
+ /* finish */
+ ED_region_tag_redraw(kcd->ar);
+
+ knifetool_finish(C, op);
+ knifetool_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ return OPERATOR_RUNNING_MODAL;
+ case LEFTMOUSE:
+ knife_recalc_projmat(kcd);
+ if (event->val != KM_RELEASE)
+ break;
+
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_add_cut(kcd);
+ if (!event->ctrl) {
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ }
+ } else {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ return OPERATOR_RUNNING_MODAL;
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ knife_recalc_projmat(kcd);
+
+ if (event->val == KM_RELEASE) {
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ return OPERATOR_RUNNING_MODAL;
+ case MOUSEMOVE: { /* mouse moved somewhere to select another loop */
+ knife_recalc_projmat(kcd);
+ kcd->vc.mval[0] = event->mval[0];
+ kcd->vc.mval[1] = event->mval[1];
+
+ if (knife_update_active(kcd))
+ ED_region_tag_redraw(kcd->ar);
+
+ break;
+ /*block undo*/
+ case ZKEY:
+ if (event->ctrl)
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ /* keep going until the user confirms */
+ return OPERATOR_PASS_THROUGH;
+}
+
+void MESH_OT_knifetool (wmOperatorType *ot)
+{
+ /* description */
+ ot->name= "Knife Topology Tool";
+ ot->idname= "MESH_OT_knifetool";
+ ot->description= "Cut new topology";
+
+ /* callbacks */
+ ot->invoke= knifetool_invoke;
+ ot->modal= knifetool_modal;
+ ot->cancel= knifetool_cancel;
+ ot->poll= ED_operator_editmesh_view3d;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
+}
+#endif
+
+/*
+ if (0) {
+ ListBase fgroups[30];
+ BMEdge *e;
+
+ memset(fgroups, 0, sizeof(fgroups));
+ BM_ITER(f, &bmiter, kcd->em->bm, BM_FACES_OF_MESH, NULL) {
+ Ref *ref = BLI_mempool_alloc(kcd->refs);
+ int i;
+
+ ref->ref = f;
+ for (i=0; i<30; i++) {
+ if ((1<<i) == BMINDEX_GET(f))
+ break;
+ }
+
+ BLI_addtail(&fgroups[i], ref);
+ }
+
+ BM_ITER(e, &bmiter, kcd->em->bm, BM_EDGES_OF_MESH, NULL) {
+ Ref *ref;
+ int group = 0;
+
+ if (!BMO_InMap(kcd->em->bm, &bmop, "restrict", e))
+ continue;
+
+ group = BMO_Get_MapInt(kcd->em->bm, &bmop, "restrict", e);
+
+ for (i=0; i<30; i++) {
+ if ((1<<i) & group) {
+ float co[3];
+ BMVert *v1, *v2;
+
+ add_v3_v3v3(co, e->v1->co, e->v2->co);
+ mul_v3_fl(co, 0.5f);
+
+ v1 = BM_Make_Vert(kcd->em->bm, co, NULL);
+
+ for (ref=fgroups[i].first; ref; ref=ref->next) {
+ BMFace *f = ref->ref;
+ BMLoop *l;
+ BMIter liter;
+ BMEdge *e2;
+
+ zero_v3(co);
+ BM_ITER(l, &liter, kcd->em->bm, BM_LOOPS_OF_FACE, f) {
+ add_v3_v3(co, l->v->co);
+ }
+ mul_v3_fl(co, 1.0f/(float)f->len);
+
+ v2 = BM_Make_Vert(kcd->em->bm, co, NULL);
+ e2 = BM_Make_Edge(kcd->em->bm, v1, v2, NULL, 0);
+ }
+ }
+ }
+ }
+ }
+
+ */
diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c
index 282ed48a476..a699561e4bb 100644
--- a/source/blender/editors/mesh/loopcut.c
+++ b/source/blender/editors/mesh/loopcut.c
@@ -265,7 +265,8 @@ static void ringsel_find_edge(tringselOpData *lcd, const bContext *C, ARegion *a
if (lcd->eed) {
edgering_sel(lcd, cuts, 0);
} else {
- MEM_freeN(lcd->edges);
+ if (lcd->edges)
+ MEM_freeN(lcd->edges);
lcd->edges = NULL;
lcd->totedge = 0;
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 28c72121d2f..327d0e95487 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -305,5 +305,7 @@ void MESH_OT_bm_test(struct wmOperatorType *ot);
void MESH_OT_edgering_select(struct wmOperatorType *ot);
void MESH_OT_loopcut(struct wmOperatorType *ot);
+void MESH_OT_knifetool(struct wmOperatorType *ot);
+
#endif // MESH_INTERN_H
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 621f20144b5..f966852672f 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -143,6 +143,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_solidify);
WM_operatortype_append(MESH_OT_select_nth);
WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_knifetool);
}
int ED_operator_editmesh_face_select(bContext *C)
@@ -294,8 +295,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
- RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
+ WM_keymap_add_item(keymap, "MESH_OT_knifetool", KKEY, KM_PRESS, 0, 0);
+ //RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index dd5a7d60fbd..35924ad9afb 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -2883,11 +2883,13 @@ static void project_paint_begin(ProjPaintState *ps)
ps->dm_mvert= MEM_dupallocN(ps->dm_mvert);
ps->dm_mface= MEM_dupallocN(ps->dm_mface);
/* looks like these are ok for now.*/
- /*
+
ps->dm_mtface= MEM_dupallocN(ps->dm_mtface);
- ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
- ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
- */
+ if (ps->dm_mtface_clone)
+ ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
+ if (ps->dm_mtface_stencil)
+ ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
+
}
ps->viewDir[0] = 0.0f;
@@ -4660,6 +4662,9 @@ static int texture_paint_init(bContext *C, wmOperator *op)
Mesh *me;
pop->s.ob = OBACT;
+ if (!pop->ps.ob)
+ pop->ps.ob = pop->s.ob;
+
pop->s.me = get_mesh(pop->s.ob);
if (!pop->s.me) return 0;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 4361f4f2fb4..12b9e982d02 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1609,7 +1609,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
for (i=0; i<mpoly->totloop; i++, ml++) {
if ((me->dvert+ml->v)->flag) {
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*ml->v, mval, pressure);
- if(alpha) {
+ if(alpha != 0.0f) {
do_weight_paint_vertex(wp, ob, ml->v,
alpha, paintweight, flip, wpd->vgroup_mirror,
wpd->vgroup_validmap);
@@ -1882,7 +1882,7 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
make_vertexcol(ob);
if(me->mloopcol==NULL)
return OPERATOR_CANCELLED;
-
+
/* make mode data storage */
vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
paint_stroke_set_mode_data(stroke, vpd);
@@ -2019,7 +2019,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
MLoopCol *mlc;
unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
- int i, j, alpha;
+ float alpha;
+ int i, j;
if(brush->vertexpaint_tool==VP_BLUR) {
unsigned int blend[5] = {0};
@@ -2050,7 +2051,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
for (i=0; i<mpoly->totloop; i++, ml++) {
alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat,
vpd->vertexcosnos+6*ml->v, mval, pressure);
- if(alpha) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, alpha);
+ if(alpha > 0.0f) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
}
#ifdef CPYCOL
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 64289f9bd0a..532c13314fd 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -688,7 +688,7 @@ void view3d_unproject(bglMats *mats, float out[3], const short x, const short y,
out[2] = uz;
}
-/* use above call to get projecting mat */
+/* use view3d_get_object_project_mat to get projecting mat */
void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
{
float vec4[4];
@@ -708,7 +708,7 @@ void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
}
}
-/* use above call to get projecting mat */
+/* use view3d_get_object_project_mat to get projecting mat */
void view3d_project_float_v3(ARegion *ar, float *vec, float *adr, float mat[4][4])
{
float vec4[4];
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index aa377f063e1..3fdbe0bcc13 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -44,7 +44,7 @@
#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-
+
EnumPropertyItem fmodifier_type_items[] = {
{FMODIFIER_TYPE_NULL, "NULL", 0, "Invalid", ""},
{FMODIFIER_TYPE_GENERATOR, "GENERATOR", 0, "Generator", ""},