2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
2005-03-29 16:43:39 +00:00
|
|
|
*
|
|
|
|
|
* 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
|
2008-01-07 19:13:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2005-03-29 16:43:39 +00:00
|
|
|
*
|
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2005-03-29 16:43:39 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
|
*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2005-03-29 16:43:39 +00:00
|
|
|
*/
|
|
|
|
|
|
2011-02-27 20:40:57 +00:00
|
|
|
/** \file blender/blenkernel/intern/subsurf_ccg.c
|
|
|
|
|
* \ingroup bke
|
|
|
|
|
*/
|
|
|
|
|
|
2013-06-14 14:57:35 +00:00
|
|
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
2015-11-22 17:12:54 +01:00
|
|
|
# ifdef __GNUC__
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wvla"
|
|
|
|
|
# endif
|
2013-06-04 07:41:21 +00:00
|
|
|
# define USE_DYNSIZE
|
|
|
|
|
#endif
|
2011-02-27 20:40:57 +00:00
|
|
|
|
2005-03-21 01:37:14 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
2005-08-03 04:04:05 +00:00
|
|
|
#include <float.h>
|
|
|
|
|
|
2017-09-25 09:56:02 +02:00
|
|
|
#include "atomic_ops.h"
|
|
|
|
|
|
2005-03-21 01:37:14 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_meshdata_types.h"
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
#include "DNA_modifier_types.h"
|
2005-03-21 01:37:14 +00:00
|
|
|
#include "DNA_object_types.h"
|
2008-02-13 11:18:08 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2005-03-21 01:37:14 +00:00
|
|
|
|
2011-05-09 04:06:48 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2012-03-14 06:31:49 +00:00
|
|
|
#include "BLI_bitmap.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
|
#include "BLI_edgehash.h"
|
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
#include "BLI_memarena.h"
|
2018-01-11 14:49:32 +01:00
|
|
|
#include "BLI_task.h"
|
2014-05-03 15:58:37 +02:00
|
|
|
#include "BLI_threads.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
|
2012-12-15 15:59:25 +00:00
|
|
|
#include "BKE_pbvh.h"
|
2012-05-10 20:33:09 +00:00
|
|
|
#include "BKE_ccg.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "BKE_cdderivedmesh.h"
|
2005-03-21 01:37:14 +00:00
|
|
|
#include "BKE_global.h"
|
2015-07-17 04:22:24 +10:00
|
|
|
#include "BKE_mesh.h"
|
2013-12-12 16:26:11 +11:00
|
|
|
#include "BKE_mesh_mapping.h"
|
2018-01-24 11:13:49 +01:00
|
|
|
#include "BKE_modifier.h"
|
2012-03-12 22:52:20 +00:00
|
|
|
#include "BKE_multires.h"
|
2010-03-22 11:59:36 +00:00
|
|
|
#include "BKE_paint.h"
|
2008-02-13 11:18:08 +00:00
|
|
|
#include "BKE_scene.h"
|
2005-03-21 01:37:14 +00:00
|
|
|
#include "BKE_subsurf.h"
|
|
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
|
|
|
|
# include "BLI_array.h"
|
|
|
|
|
#endif
|
2005-03-21 01:37:14 +00:00
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
#include "GPU_draw.h"
|
2014-10-07 15:46:19 -05:00
|
|
|
#include "GPU_glew.h"
|
2015-07-14 16:48:23 +02:00
|
|
|
#include "GPU_buffers.h"
|
2015-12-06 21:20:19 +01:00
|
|
|
#include "GPU_shader.h"
|
2015-12-25 22:57:50 +01:00
|
|
|
#include "GPU_basic_shader.h"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2005-03-21 01:37:14 +00:00
|
|
|
#include "CCGSubSurf.h"
|
|
|
|
|
|
2018-02-08 21:14:26 +11:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
# include "opensubdiv_capi.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-07-18 23:45:51 +10:00
|
|
|
/* assumes MLoop's are layed out 4 for each poly, in order */
|
|
|
|
|
#define USE_LOOP_LAYOUT_FAST
|
|
|
|
|
|
2010-01-05 22:33:41 +00:00
|
|
|
static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
2009-08-18 20:05:08 +00:00
|
|
|
int drawInteriorEdges,
|
|
|
|
|
int useSubsurfUv,
|
2015-07-20 16:08:06 +02:00
|
|
|
DerivedMesh *dm,
|
|
|
|
|
bool use_gpu_backend);
|
2011-05-04 13:15:42 +00:00
|
|
|
static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2005-03-21 01:37:14 +00:00
|
|
|
///
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static void *arena_alloc(CCGAllocatorHDL a, int numBytes)
|
|
|
|
|
{
|
2005-03-21 01:37:14 +00:00
|
|
|
return BLI_memarena_alloc(a, numBytes);
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize)
|
|
|
|
|
{
|
2005-03-21 01:37:14 +00:00
|
|
|
void *p2 = BLI_memarena_alloc(a, newSize);
|
|
|
|
|
if (ptr) {
|
|
|
|
|
memcpy(p2, ptr, oldSize);
|
|
|
|
|
}
|
|
|
|
|
return p2;
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static void arena_free(CCGAllocatorHDL UNUSED(a), void *UNUSED(ptr))
|
|
|
|
|
{
|
|
|
|
|
/* do nothing */
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static void arena_release(CCGAllocatorHDL a)
|
|
|
|
|
{
|
2005-03-21 01:37:14 +00:00
|
|
|
BLI_memarena_free(a);
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-20 01:43:49 +00:00
|
|
|
typedef enum {
|
|
|
|
|
CCG_USE_AGING = 1,
|
|
|
|
|
CCG_USE_ARENA = 2,
|
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
have a mask layer and what that layer's offset is. Unlike normals
however, it doesn't change any behavior during CCG calculation; it's
there only to give CCGKey information on the mask.
* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
an extra layer is allocated, but the number of CCG layers is not set
to include it. This is done because GridPaintMasks are absolute,
rather than being relative to the subdivided output (as MDisp
displacements are), so we skip subdividing paint masks here.
* Add a new flag to subsurf_make_derived_from_derived(),
SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
set for _getSubSurf(). Related, masks are never loaded in during
ss_sync_from_derivedmesh(). After subdivision is finished, if the
alloc mask flag is set, the number of CCG layers is increase to 4
with ccgSubSurf_setNumLayers().
* Add a new flag to multires_make_from_derived(),
MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
mask data (e.g. multiresModifier_base_apply.) This flag is always
set in MOD_multires.c so that subdividing a mesh with a mask updates
properly even when not in sculpt mode.
* Update multiresModifier_disp_run() to apply, calculate, and add mask
elements. It's almost the same as the existing operations with xyz
coordinates, but treats masks as absolute rather than displacements
relative to subdivided values.
* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
addition to CD_MDISPS.
* Update multires_del_higher() to call the new function
multires_grid_paint_mask_downsample(), which allocates a
lower-resolution paint mask grid and copies values over from the
high-resolution grid.
2012-05-10 20:34:08 +00:00
|
|
|
CCG_CALC_NORMALS = 4,
|
|
|
|
|
/* add an extra four bytes for a mask layer */
|
2012-08-18 19:54:21 +00:00
|
|
|
CCG_ALLOC_MASK = 8,
|
|
|
|
|
CCG_SIMPLE_SUBDIV = 16
|
2012-01-20 01:43:49 +00:00
|
|
|
} CCGFlags;
|
|
|
|
|
|
2012-05-10 20:32:41 +00:00
|
|
|
static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
|
2012-05-11 08:05:47 +00:00
|
|
|
int numLayers, CCGFlags flags)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2005-03-21 01:37:14 +00:00
|
|
|
CCGMeshIFC ifc;
|
2005-03-31 15:44:05 +00:00
|
|
|
CCGSubSurf *ccgSS;
|
2012-01-20 01:43:49 +00:00
|
|
|
int useAging = !!(flags & CCG_USE_AGING);
|
|
|
|
|
int useArena = flags & CCG_USE_ARENA;
|
2012-05-10 20:32:41 +00:00
|
|
|
int normalOffset = 0;
|
2005-03-21 01:37:14 +00:00
|
|
|
|
2012-05-27 19:40:36 +00:00
|
|
|
/* (subdivLevels == 0) is not allowed */
|
2005-07-22 15:09:54 +00:00
|
|
|
subdivLevels = MAX2(subdivLevels, 1);
|
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
if (prevSS) {
|
|
|
|
|
int oldUseAging;
|
|
|
|
|
|
|
|
|
|
ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
|
|
|
|
|
|
2012-08-18 19:54:21 +00:00
|
|
|
if ((oldUseAging != useAging) ||
|
2014-01-12 22:05:24 +11:00
|
|
|
(ccgSubSurf_getSimpleSubdiv(prevSS) != !!(flags & CCG_SIMPLE_SUBDIV)))
|
2012-08-18 19:54:21 +00:00
|
|
|
{
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_free(prevSS);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
|
|
|
|
|
|
|
|
|
|
return prevSS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (useAging) {
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
|
2005-03-31 15:44:05 +00:00
|
|
|
}
|
2012-05-10 20:32:41 +00:00
|
|
|
ifc.numLayers = numLayers;
|
|
|
|
|
ifc.vertDataSize = sizeof(float) * numLayers;
|
|
|
|
|
normalOffset += sizeof(float) * numLayers;
|
2012-05-11 08:05:47 +00:00
|
|
|
if (flags & CCG_CALC_NORMALS)
|
2012-05-10 20:32:41 +00:00
|
|
|
ifc.vertDataSize += sizeof(float) * 3;
|
2012-05-11 08:05:47 +00:00
|
|
|
if (flags & CCG_ALLOC_MASK)
|
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
have a mask layer and what that layer's offset is. Unlike normals
however, it doesn't change any behavior during CCG calculation; it's
there only to give CCGKey information on the mask.
* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
an extra layer is allocated, but the number of CCG layers is not set
to include it. This is done because GridPaintMasks are absolute,
rather than being relative to the subdivided output (as MDisp
displacements are), so we skip subdividing paint masks here.
* Add a new flag to subsurf_make_derived_from_derived(),
SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
set for _getSubSurf(). Related, masks are never loaded in during
ss_sync_from_derivedmesh(). After subdivision is finished, if the
alloc mask flag is set, the number of CCG layers is increase to 4
with ccgSubSurf_setNumLayers().
* Add a new flag to multires_make_from_derived(),
MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
mask data (e.g. multiresModifier_base_apply.) This flag is always
set in MOD_multires.c so that subdividing a mesh with a mask updates
properly even when not in sculpt mode.
* Update multiresModifier_disp_run() to apply, calculate, and add mask
elements. It's almost the same as the existing operations with xyz
coordinates, but treats masks as absolute rather than displacements
relative to subdivided values.
* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
addition to CD_MDISPS.
* Update multires_del_higher() to call the new function
multires_grid_paint_mask_downsample(), which allocates a
lower-resolution paint mask grid and copies values over from the
high-resolution grid.
2012-05-10 20:34:08 +00:00
|
|
|
ifc.vertDataSize += sizeof(float);
|
2012-08-18 19:54:21 +00:00
|
|
|
ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
|
2005-03-21 01:37:14 +00:00
|
|
|
|
2005-03-31 16:54:47 +00:00
|
|
|
if (useArena) {
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
CCGAllocatorIFC allocatorIFC;
|
2013-10-10 18:18:13 +00:00
|
|
|
CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena");
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
2005-03-31 16:54:47 +00:00
|
|
|
allocatorIFC.alloc = arena_alloc;
|
|
|
|
|
allocatorIFC.realloc = arena_realloc;
|
|
|
|
|
allocatorIFC.free = arena_free;
|
|
|
|
|
allocatorIFC.release = arena_release;
|
2005-03-21 01:37:14 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
|
2005-03-31 16:54:47 +00:00
|
|
|
}
|
2005-03-31 15:44:05 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
if (useAging) {
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
|
2005-03-31 15:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
have a mask layer and what that layer's offset is. Unlike normals
however, it doesn't change any behavior during CCG calculation; it's
there only to give CCGKey information on the mask.
* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
an extra layer is allocated, but the number of CCG layers is not set
to include it. This is done because GridPaintMasks are absolute,
rather than being relative to the subdivided output (as MDisp
displacements are), so we skip subdividing paint masks here.
* Add a new flag to subsurf_make_derived_from_derived(),
SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
set for _getSubSurf(). Related, masks are never loaded in during
ss_sync_from_derivedmesh(). After subdivision is finished, if the
alloc mask flag is set, the number of CCG layers is increase to 4
with ccgSubSurf_setNumLayers().
* Add a new flag to multires_make_from_derived(),
MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
mask data (e.g. multiresModifier_base_apply.) This flag is always
set in MOD_multires.c so that subdividing a mesh with a mask updates
properly even when not in sculpt mode.
* Update multiresModifier_disp_run() to apply, calculate, and add mask
elements. It's almost the same as the existing operations with xyz
coordinates, but treats masks as absolute rather than displacements
relative to subdivided values.
* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
addition to CD_MDISPS.
* Update multires_del_higher() to call the new function
multires_grid_paint_mask_downsample(), which allocates a
lower-resolution paint mask grid and copies values over from the
high-resolution grid.
2012-05-10 20:34:08 +00:00
|
|
|
if (flags & CCG_ALLOC_MASK) {
|
|
|
|
|
normalOffset += sizeof(float);
|
|
|
|
|
/* mask is allocated after regular layers */
|
|
|
|
|
ccgSubSurf_setAllocMask(ccgSS, 1, sizeof(float) * numLayers);
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-20 19:27:04 +00:00
|
|
|
if (flags & CCG_CALC_NORMALS)
|
2012-05-10 20:32:41 +00:00
|
|
|
ccgSubSurf_setCalcVertexNormals(ccgSS, 1, normalOffset);
|
2012-01-20 19:27:04 +00:00
|
|
|
else
|
|
|
|
|
ccgSubSurf_setCalcVertexNormals(ccgSS, 0, 0);
|
2005-04-03 21:52:10 +00:00
|
|
|
|
2005-03-31 15:44:05 +00:00
|
|
|
return ccgSS;
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize)
|
|
|
|
|
{
|
2008-09-29 17:08:11 +00:00
|
|
|
CCGVert *v0 = ccgSubSurf_getEdgeVert0(e);
|
|
|
|
|
CCGVert *v1 = ccgSubSurf_getEdgeVert1(e);
|
2012-04-22 00:20:58 +00:00
|
|
|
int v0idx = *((int *) ccgSubSurf_getVertUserData(ss, v0));
|
|
|
|
|
int v1idx = *((int *) ccgSubSurf_getVertUserData(ss, v1));
|
|
|
|
|
int edgeBase = *((int *) ccgSubSurf_getEdgeUserData(ss, e));
|
2005-03-21 01:37:14 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (x == 0) {
|
2005-03-21 01:37:14 +00:00
|
|
|
return v0idx;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (x == edgeSize - 1) {
|
2005-03-21 01:37:14 +00:00
|
|
|
return v1idx;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-04-22 00:20:58 +00:00
|
|
|
return edgeBase + x - 1;
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
int faceBase = *((int *) ccgSubSurf_getFaceUserData(ss, f));
|
2008-09-29 17:08:11 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2005-03-21 01:37:14 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (x == gridSize - 1 && y == gridSize - 1) {
|
2012-03-06 01:01:42 +00:00
|
|
|
CCGVert *v = ccgSubSurf_getFaceVert(f, S);
|
2012-04-22 00:20:58 +00:00
|
|
|
return *((int *) ccgSubSurf_getVertUserData(ss, v));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (x == gridSize - 1) {
|
2012-03-06 01:01:42 +00:00
|
|
|
CCGVert *v = ccgSubSurf_getFaceVert(f, S);
|
|
|
|
|
CCGEdge *e = ccgSubSurf_getFaceEdge(f, S);
|
2012-04-22 00:20:58 +00:00
|
|
|
int edgeBase = *((int *) ccgSubSurf_getEdgeUserData(ss, e));
|
|
|
|
|
if (v == ccgSubSurf_getEdgeVert0(e)) {
|
|
|
|
|
return edgeBase + (gridSize - 1 - y) - 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-04-22 00:20:58 +00:00
|
|
|
return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - y) - 1);
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (y == gridSize - 1) {
|
2012-03-06 01:01:42 +00:00
|
|
|
CCGVert *v = ccgSubSurf_getFaceVert(f, S);
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGEdge *e = ccgSubSurf_getFaceEdge(f, (S + numVerts - 1) % numVerts);
|
|
|
|
|
int edgeBase = *((int *) ccgSubSurf_getEdgeUserData(ss, e));
|
|
|
|
|
if (v == ccgSubSurf_getEdgeVert0(e)) {
|
|
|
|
|
return edgeBase + (gridSize - 1 - x) - 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-04-22 00:20:58 +00:00
|
|
|
return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - x) - 1);
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (x == 0 && y == 0) {
|
2005-03-21 01:37:14 +00:00
|
|
|
return faceBase;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (x == 0) {
|
|
|
|
|
S = (S + numVerts - 1) % numVerts;
|
|
|
|
|
return faceBase + 1 + (gridSize - 2) * S + (y - 1);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
else if (y == 0) {
|
|
|
|
|
return faceBase + 1 + (gridSize - 2) * S + (x - 1);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-04-22 00:20:58 +00:00
|
|
|
return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) + (y - 1) * (gridSize - 2) + (x - 1);
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-08-18 11:31:20 +00:00
|
|
|
|
2012-04-12 12:23:25 +00:00
|
|
|
static void get_face_uv_map_vert(UvVertMap *vmap, struct MPoly *mpoly, struct MLoop *ml, int fi, CCGVertHDL *fverts)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2006-02-19 11:37:50 +00:00
|
|
|
UvMapVert *v, *nv;
|
2012-04-22 00:20:58 +00:00
|
|
|
int j, nverts = mpoly[fi].totloop;
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (j = 0; j < nverts; j++) {
|
2012-05-05 21:28:12 +00:00
|
|
|
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) {
|
2006-01-10 11:36:57 +00:00
|
|
|
if (v->separate)
|
2012-04-22 00:20:58 +00:00
|
|
|
nv = v;
|
2006-01-10 11:36:57 +00:00
|
|
|
if (v->f == fi)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 06:40:35 +00:00
|
|
|
fverts[j] = SET_UINT_IN_POINTER(mpoly[nv->f].loopstart + nv->tfindex);
|
2006-01-10 11:36:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MLoopUV *mloopuv)
|
|
|
|
|
{
|
2011-10-30 09:48:59 +00:00
|
|
|
MPoly *mpoly = dm->getPolyArray(dm);
|
|
|
|
|
MLoop *mloop = dm->getLoopArray(dm);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MVert *mvert = dm->getVertArray(dm);
|
|
|
|
|
int totvert = dm->getNumVerts(dm);
|
2011-11-29 13:01:51 +00:00
|
|
|
int totface = dm->getNumPolys(dm);
|
2013-07-02 21:47:42 +00:00
|
|
|
int i, seam;
|
2006-02-19 11:37:50 +00:00
|
|
|
UvMapVert *v;
|
2006-01-10 11:36:57 +00:00
|
|
|
UvVertMap *vmap;
|
|
|
|
|
float limit[2];
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGVertHDL *fverts = NULL;
|
2011-10-30 09:48:59 +00:00
|
|
|
BLI_array_declare(fverts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2013-08-25 20:03:45 +00:00
|
|
|
EdgeSet *eset;
|
2006-02-19 11:37:50 +00:00
|
|
|
float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
|
2012-04-22 00:20:58 +00:00
|
|
|
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
|
2015-05-15 23:38:53 +10:00
|
|
|
/* previous behavior here is without accounting for winding, however this causes stretching in
|
2015-05-06 23:29:59 +02:00
|
|
|
* UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially
|
|
|
|
|
* intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED
|
|
|
|
|
* This fixes a very old regression (2.49 was correct here) */
|
2015-05-17 23:04:34 +10:00
|
|
|
vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
|
2006-01-10 11:36:57 +00:00
|
|
|
if (!vmap)
|
|
|
|
|
return 0;
|
2006-01-13 06:56:32 +00:00
|
|
|
|
2006-01-10 11:36:57 +00:00
|
|
|
ccgSubSurf_initFullSync(ss);
|
|
|
|
|
|
|
|
|
|
/* create vertices */
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < totvert; i++) {
|
2012-05-05 21:28:12 +00:00
|
|
|
if (!BKE_mesh_uv_vert_map_get_vert(vmap, i))
|
2006-01-13 06:56:32 +00:00
|
|
|
continue;
|
|
|
|
|
|
2012-05-05 21:28:12 +00:00
|
|
|
for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i)->next; v; v = v->next)
|
2006-01-10 11:36:57 +00:00
|
|
|
if (v->separate)
|
|
|
|
|
break;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
seam = (v != NULL) || ((mvert + i)->flag & ME_VERT_MERGED);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-05-05 21:28:12 +00:00
|
|
|
for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
|
2006-01-10 11:36:57 +00:00
|
|
|
if (v->separate) {
|
|
|
|
|
CCGVert *ssv;
|
2012-04-12 12:23:25 +00:00
|
|
|
int loopid = mpoly[v->f].loopstart + v->tfindex;
|
|
|
|
|
CCGVertHDL vhdl = SET_INT_IN_POINTER(loopid);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-04-12 12:23:25 +00:00
|
|
|
copy_v2_v2(uv, mloopuv[loopid].uv);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
|
|
|
|
ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create edges */
|
2013-08-25 20:03:45 +00:00
|
|
|
eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2015-07-12 02:53:37 +10:00
|
|
|
MPoly *mp = &mpoly[i];
|
2012-04-22 00:20:58 +00:00
|
|
|
int nverts = mp->totloop;
|
2013-07-02 21:47:42 +00:00
|
|
|
int j, j_next;
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGFace *origf = ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
|
2011-10-30 09:48:59 +00:00
|
|
|
/* unsigned int *fv = &mp->v1; */
|
2012-04-22 00:20:58 +00:00
|
|
|
MLoop *ml = mloop + mp->loopstart;
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifdef USE_DYNSIZE
|
|
|
|
|
CCGVertHDL fverts[nverts];
|
|
|
|
|
#else
|
2018-02-01 12:06:57 +11:00
|
|
|
BLI_array_clear(fverts);
|
2012-04-28 15:14:16 +00:00
|
|
|
BLI_array_grow_items(fverts, nverts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2011-10-30 09:48:59 +00:00
|
|
|
|
2012-04-12 12:23:25 +00:00
|
|
|
get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2013-06-04 06:40:35 +00:00
|
|
|
for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
|
2013-07-02 21:47:42 +00:00
|
|
|
unsigned int v0 = GET_UINT_FROM_POINTER(fverts[j_next]);
|
|
|
|
|
unsigned int v1 = GET_UINT_FROM_POINTER(fverts[j]);
|
|
|
|
|
MVert *mv0 = mvert + (ml[j_next].v);
|
|
|
|
|
MVert *mv1 = mvert + (ml[j].v);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2014-05-29 14:00:11 +10:00
|
|
|
if (BLI_edgeset_add(eset, v0, v1)) {
|
2013-07-02 21:47:42 +00:00
|
|
|
CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
|
|
|
|
|
CCGEdgeHDL ehdl = SET_INT_IN_POINTER(mp->loopstart + j_next);
|
2006-02-19 11:37:50 +00:00
|
|
|
float crease;
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if ((mv0->flag & mv1->flag) & ME_VERT_MERGED)
|
2006-02-19 11:37:50 +00:00
|
|
|
crease = creaseFactor;
|
|
|
|
|
else
|
2008-09-29 17:08:11 +00:00
|
|
|
crease = ccgSubSurf_getEdgeCrease(orige);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2013-07-02 21:47:42 +00:00
|
|
|
ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
|
2006-01-10 11:36:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-25 20:03:45 +00:00
|
|
|
BLI_edgeset_free(eset);
|
2006-01-10 11:36:57 +00:00
|
|
|
|
|
|
|
|
/* create faces */
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2011-12-28 04:43:29 +00:00
|
|
|
MPoly *mp = &mpoly[i];
|
2012-04-22 00:20:58 +00:00
|
|
|
MLoop *ml = &mloop[mp->loopstart];
|
|
|
|
|
int nverts = mp->totloop;
|
2006-01-10 11:36:57 +00:00
|
|
|
CCGFace *f;
|
|
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifdef USE_DYNSIZE
|
|
|
|
|
CCGVertHDL fverts[nverts];
|
|
|
|
|
#else
|
2018-02-01 12:06:57 +11:00
|
|
|
BLI_array_clear(fverts);
|
2012-04-28 15:14:16 +00:00
|
|
|
BLI_array_grow_items(fverts, nverts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2011-10-30 09:48:59 +00:00
|
|
|
|
2012-04-12 12:23:25 +00:00
|
|
|
get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
|
2008-02-18 10:49:46 +00:00
|
|
|
ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
|
2006-01-10 11:36:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2011-10-30 09:48:59 +00:00
|
|
|
BLI_array_free(fverts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2011-10-30 09:48:59 +00:00
|
|
|
|
2012-05-05 21:28:12 +00:00
|
|
|
BKE_mesh_uv_vert_map_free(vmap);
|
2006-01-10 11:36:57 +00:00
|
|
|
ccgSubSurf_processSync(ss);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
2015-08-03 17:30:44 +02:00
|
|
|
static void UNUSED_FUNCTION(set_subsurf_osd_ccg_uv)(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
DerivedMesh *result,
|
|
|
|
|
int layer_index)
|
2015-07-20 16:08:06 +02:00
|
|
|
{
|
|
|
|
|
CCGFace **faceMap;
|
|
|
|
|
MTFace *tf;
|
|
|
|
|
MLoopUV *mluv;
|
|
|
|
|
CCGFaceIterator fi;
|
|
|
|
|
int index, gridSize, gridFaces, totface, x, y, S;
|
|
|
|
|
MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
|
|
|
|
|
/* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
|
|
|
|
|
* just tface except applying the modifier then looses subsurf UV */
|
|
|
|
|
MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, layer_index);
|
|
|
|
|
MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, layer_index);
|
|
|
|
|
|
|
|
|
|
if (dmloopuv == NULL || (tface == NULL && mloopuv == NULL)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ccgSubSurf_evaluatorSetFVarUV(ss, dm, layer_index);
|
|
|
|
|
|
|
|
|
|
/* get some info from CCGSubSurf */
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
gridFaces = gridSize - 1;
|
|
|
|
|
|
|
|
|
|
/* make a map from original faces to CCGFaces */
|
|
|
|
|
faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
|
|
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
|
|
|
|
faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* load coordinates from uvss into tface */
|
|
|
|
|
tf = tface;
|
|
|
|
|
mluv = mloopuv;
|
|
|
|
|
for (index = 0; index < totface; index++) {
|
|
|
|
|
CCGFace *f = faceMap[index];
|
|
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2015-08-03 14:50:31 +02:00
|
|
|
const int delta[4][2] = {{0, 0},
|
|
|
|
|
{0, 1},
|
|
|
|
|
{1, 1},
|
|
|
|
|
{1, 0}};
|
|
|
|
|
float uv[4][2];
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
const int dx = delta[i][0],
|
|
|
|
|
dy = delta[i][1];
|
|
|
|
|
const float grid_u = ((float)(x + dx)) / (gridSize - 1),
|
|
|
|
|
grid_v = ((float)(y + dy)) / (gridSize - 1);
|
|
|
|
|
ccgSubSurf_evaluatorFVarUV(ss,
|
|
|
|
|
index,
|
|
|
|
|
S,
|
|
|
|
|
grid_u, grid_v,
|
|
|
|
|
uv[i]);
|
|
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
if (tf) {
|
2015-08-03 14:50:31 +02:00
|
|
|
copy_v2_v2(tf->uv[0], uv[0]);
|
|
|
|
|
copy_v2_v2(tf->uv[1], uv[1]);
|
|
|
|
|
copy_v2_v2(tf->uv[2], uv[2]);
|
|
|
|
|
copy_v2_v2(tf->uv[3], uv[3]);
|
2015-07-20 16:08:06 +02:00
|
|
|
tf++;
|
|
|
|
|
}
|
|
|
|
|
if (mluv) {
|
2015-08-03 14:50:31 +02:00
|
|
|
copy_v2_v2(mluv[0].uv, uv[0]);
|
|
|
|
|
copy_v2_v2(mluv[1].uv, uv[1]);
|
|
|
|
|
copy_v2_v2(mluv[2].uv, uv[2]);
|
|
|
|
|
copy_v2_v2(mluv[3].uv, uv[3]);
|
2015-07-20 16:08:06 +02:00
|
|
|
mluv += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(faceMap);
|
|
|
|
|
}
|
2015-08-03 17:30:44 +02:00
|
|
|
#endif /* WITH_OPENSUBDIV */
|
2006-01-10 11:36:57 +00:00
|
|
|
|
2015-08-03 17:30:44 +02:00
|
|
|
static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
|
|
|
|
CCGSubSurf *uvss;
|
|
|
|
|
CCGFace **faceMap;
|
|
|
|
|
MTFace *tf;
|
2011-10-30 09:48:59 +00:00
|
|
|
MLoopUV *mluv;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGFaceIterator fi;
|
2011-01-10 03:55:47 +00:00
|
|
|
int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
|
2011-10-30 09:48:59 +00:00
|
|
|
MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
|
|
|
|
|
/* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
|
|
|
|
|
* just tface except applying the modifier then looses subsurf UV */
|
2006-12-12 21:29:09 +00:00
|
|
|
MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
|
2011-10-30 09:48:59 +00:00
|
|
|
MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n);
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!dmloopuv || (!tface && !mloopuv))
|
2006-12-12 21:29:09 +00:00
|
|
|
return;
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
/* create a CCGSubSurf from uv's */
|
2012-05-10 20:32:41 +00:00
|
|
|
uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 2, CCG_USE_ARENA);
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) {
|
2006-12-12 21:29:09 +00:00
|
|
|
ccgSubSurf_free(uvss);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
/* get some info from CCGSubSurf */
|
2006-12-12 21:29:09 +00:00
|
|
|
totface = ccgSubSurf_getNumFaces(uvss);
|
2011-01-10 03:55:47 +00:00
|
|
|
/* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/
|
2006-12-12 21:29:09 +00:00
|
|
|
gridSize = ccgSubSurf_getGridSize(uvss);
|
|
|
|
|
gridFaces = gridSize - 1;
|
|
|
|
|
|
|
|
|
|
/* make a map from original faces to CCGFaces */
|
2012-04-22 00:20:58 +00:00
|
|
|
faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2012-03-06 01:01:42 +00:00
|
|
|
faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* load coordinates from uvss into tface */
|
2012-04-22 00:20:58 +00:00
|
|
|
tf = tface;
|
|
|
|
|
mluv = mloopuv;
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2006-12-12 21:29:09 +00:00
|
|
|
CCGFace *f = faceMap[index];
|
2008-09-29 17:08:11 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2012-05-10 20:32:41 +00:00
|
|
|
float (*faceGridData)[2] = ccgSubSurf_getFaceGridDataArray(uvss, f, S);
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2012-04-22 00:20:58 +00:00
|
|
|
float *a = faceGridData[(y + 0) * gridSize + x + 0];
|
|
|
|
|
float *b = faceGridData[(y + 0) * gridSize + x + 1];
|
|
|
|
|
float *c = faceGridData[(y + 1) * gridSize + x + 1];
|
|
|
|
|
float *d = faceGridData[(y + 1) * gridSize + x + 0];
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2012-03-18 06:01:33 +00:00
|
|
|
if (tf) {
|
|
|
|
|
copy_v2_v2(tf->uv[0], a);
|
|
|
|
|
copy_v2_v2(tf->uv[1], d);
|
|
|
|
|
copy_v2_v2(tf->uv[2], c);
|
|
|
|
|
copy_v2_v2(tf->uv[3], b);
|
|
|
|
|
tf++;
|
2011-10-30 09:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-18 06:01:33 +00:00
|
|
|
if (mluv) {
|
|
|
|
|
copy_v2_v2(mluv[0].uv, a);
|
|
|
|
|
copy_v2_v2(mluv[1].uv, d);
|
|
|
|
|
copy_v2_v2(mluv[2].uv, c);
|
|
|
|
|
copy_v2_v2(mluv[3].uv, b);
|
|
|
|
|
mluv += 4;
|
2011-10-30 09:48:59 +00:00
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ccgSubSurf_free(uvss);
|
|
|
|
|
MEM_freeN(faceMap);
|
|
|
|
|
}
|
2015-08-03 17:30:44 +02:00
|
|
|
|
|
|
|
|
static void set_subsurf_uv(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
DerivedMesh *result,
|
|
|
|
|
int layer_index)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (!ccgSubSurf_needGrids(ss)) {
|
|
|
|
|
/* GPU backend is used, no need to evaluate UVs on CPU. */
|
|
|
|
|
/* TODO(sergey): Think of how to support edit mode of UVs. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
set_subsurf_legacy_uv(ss, dm, result, layer_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2009-06-16 20:08:40 +00:00
|
|
|
/* face weighting */
|
|
|
|
|
typedef struct FaceVertWeightEntry {
|
|
|
|
|
FaceVertWeight *weight;
|
2009-08-16 19:55:05 +00:00
|
|
|
float *w;
|
2009-06-16 20:08:40 +00:00
|
|
|
int valid;
|
|
|
|
|
} FaceVertWeightEntry;
|
|
|
|
|
|
|
|
|
|
typedef struct WeightTable {
|
|
|
|
|
FaceVertWeightEntry *weight_table;
|
|
|
|
|
int len;
|
|
|
|
|
} WeightTable;
|
|
|
|
|
|
2009-08-16 19:55:05 +00:00
|
|
|
static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
|
2009-06-16 20:08:40 +00:00
|
|
|
{
|
2009-08-16 19:55:05 +00:00
|
|
|
int x, y, i, j;
|
|
|
|
|
float *w, w1, w2, w4, fac, fac2, fx, fy;
|
|
|
|
|
|
|
|
|
|
if (wtable->len <= faceLen) {
|
2012-04-22 00:20:58 +00:00
|
|
|
void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry) * (faceLen + 1), "weight table alloc 2");
|
2009-08-16 19:55:05 +00:00
|
|
|
|
|
|
|
|
if (wtable->len) {
|
2012-04-22 00:20:58 +00:00
|
|
|
memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry) * wtable->len);
|
2009-08-16 19:55:05 +00:00
|
|
|
MEM_freeN(wtable->weight_table);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wtable->weight_table = tmp;
|
2012-04-22 00:20:58 +00:00
|
|
|
wtable->len = faceLen + 1;
|
2009-08-16 19:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!wtable->weight_table[faceLen].valid) {
|
|
|
|
|
wtable->weight_table[faceLen].valid = 1;
|
2012-04-22 00:20:58 +00:00
|
|
|
wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float) * faceLen * faceLen * (gridCuts + 2) * (gridCuts + 2), "weight table alloc");
|
2011-08-24 02:44:26 +00:00
|
|
|
fac = 1.0f / (float)faceLen;
|
2009-08-16 19:55:05 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < faceLen; i++) {
|
|
|
|
|
for (x = 0; x < gridCuts + 2; x++) {
|
|
|
|
|
for (y = 0; y < gridCuts + 2; y++) {
|
|
|
|
|
fx = 0.5f - (float)x / (float)(gridCuts + 1) / 2.0f;
|
|
|
|
|
fy = 0.5f - (float)y / (float)(gridCuts + 1) / 2.0f;
|
2009-08-16 19:55:05 +00:00
|
|
|
|
|
|
|
|
fac2 = faceLen - 4;
|
2012-04-22 00:20:58 +00:00
|
|
|
w1 = (1.0f - fx) * (1.0f - fy) + (-fac2 * fx * fy * fac);
|
|
|
|
|
w2 = (1.0f - fx + fac2 * fx * -fac) * (fy);
|
|
|
|
|
w4 = (fx) * (1.0f - fy + -fac2 * fy * fac);
|
|
|
|
|
|
2012-09-18 12:53:41 +00:00
|
|
|
/* these values aren't used for tri's and cause divide by zero */
|
|
|
|
|
if (faceLen > 3) {
|
|
|
|
|
fac2 = 1.0f - (w1 + w2 + w4);
|
|
|
|
|
fac2 = fac2 / (float)(faceLen - 3);
|
|
|
|
|
for (j = 0; j < faceLen; j++) {
|
|
|
|
|
w[j] = fac2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-16 19:55:05 +00:00
|
|
|
|
|
|
|
|
w[i] = w1;
|
2012-04-22 00:20:58 +00:00
|
|
|
w[(i - 1 + faceLen) % faceLen] = w2;
|
|
|
|
|
w[(i + 1) % faceLen] = w4;
|
2009-08-16 19:55:05 +00:00
|
|
|
|
|
|
|
|
w += faceLen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-16 20:08:40 +00:00
|
|
|
|
2009-08-16 19:55:05 +00:00
|
|
|
return wtable->weight_table[faceLen].w;
|
2009-06-16 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
|
2011-05-11 02:14:43 +00:00
|
|
|
static void free_ss_weights(WeightTable *wtable)
|
2009-06-16 20:08:40 +00:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < wtable->len; i++) {
|
2009-06-16 20:08:40 +00:00
|
|
|
if (wtable->weight_table[i].valid)
|
2009-08-16 19:55:05 +00:00
|
|
|
MEM_freeN(wtable->weight_table[i].w);
|
2009-06-16 20:08:40 +00:00
|
|
|
}
|
2011-03-27 02:56:41 +00:00
|
|
|
|
2011-03-29 05:48:18 +00:00
|
|
|
if (wtable->weight_table)
|
|
|
|
|
MEM_freeN(wtable->weight_table);
|
2009-06-16 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
float (*vertexCos)[3],
|
|
|
|
|
int useFlatSubdiv)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
|
|
|
|
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2010-01-05 22:33:41 +00:00
|
|
|
CCGVertHDL *fVerts = NULL;
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_declare(fVerts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MVert *mvert = dm->getVertArray(dm);
|
|
|
|
|
MEdge *medge = dm->getEdgeArray(dm);
|
2011-08-28 21:20:10 +00:00
|
|
|
/* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
|
2006-08-28 01:12:36 +00:00
|
|
|
MVert *mv;
|
|
|
|
|
MEdge *me;
|
2011-06-14 03:16:08 +00:00
|
|
|
MLoop *mloop = dm->getLoopArray(dm), *ml;
|
|
|
|
|
MPoly *mpoly = dm->getPolyArray(dm), *mp;
|
2011-05-13 13:17:30 +00:00
|
|
|
/*MFace *mf;*/ /*UNUSED*/
|
2011-06-14 03:16:08 +00:00
|
|
|
int totvert = dm->getNumVerts(dm);
|
|
|
|
|
int totedge = dm->getNumEdges(dm);
|
|
|
|
|
/*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/
|
|
|
|
|
/*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/
|
|
|
|
|
int i, j;
|
|
|
|
|
int *index;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
ccgSubSurf_initFullSync(ss);
|
|
|
|
|
|
|
|
|
|
mv = mvert;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < totvert; i++, mv++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGVert *v;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (vertexCos) {
|
2008-02-18 10:49:46 +00:00
|
|
|
ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2008-02-18 10:49:46 +00:00
|
|
|
ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
((int *)ccgSubSurf_getVertUserData(ss, v))[1] = (index) ? *index++ : i;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
me = medge;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < totedge; i++, me++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGEdge *e;
|
|
|
|
|
float crease;
|
2011-05-11 09:31:00 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
crease = useFlatSubdiv ? creaseFactor :
|
2012-04-22 00:20:58 +00:00
|
|
|
me->crease * creaseFactor / 255.0f;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2013-06-04 06:40:35 +00:00
|
|
|
ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_UINT_IN_POINTER(me->v1),
|
|
|
|
|
SET_UINT_IN_POINTER(me->v2), crease, &e);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
((int *)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index) ? *index++ : i;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
mp = mpoly;
|
2012-10-31 03:21:13 +00:00
|
|
|
index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < dm->numPolyData; i++, mp++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f;
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifdef USE_DYNSIZE
|
|
|
|
|
CCGVertHDL fVerts[mp->totloop];
|
|
|
|
|
#else
|
2018-02-01 12:06:57 +11:00
|
|
|
BLI_array_clear(fVerts);
|
2012-04-28 15:14:16 +00:00
|
|
|
BLI_array_grow_items(fVerts, mp->totloop);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
ml = mloop + mp->loopstart;
|
2012-04-22 00:20:58 +00:00
|
|
|
for (j = 0; j < mp->totloop; j++, ml++) {
|
2013-06-04 06:40:35 +00:00
|
|
|
fVerts[j] = SET_UINT_IN_POINTER(ml->v);
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this is very bad, means mesh is internally inconsistent.
|
|
|
|
|
* it is not really possible to continue without modifying
|
|
|
|
|
* other parts of code significantly to handle missing faces.
|
|
|
|
|
* since this really shouldn't even be possible we just bail.*/
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), mp->totloop,
|
2012-05-20 19:49:27 +00:00
|
|
|
fVerts, &f) == eCCGError_InvalidValue)
|
|
|
|
|
{
|
2006-08-28 01:12:36 +00:00
|
|
|
static int hasGivenError = 0;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!hasGivenError) {
|
2012-02-05 07:44:40 +00:00
|
|
|
//XXX error("Unrecoverable error in SubSurf calculation,"
|
|
|
|
|
// " mesh is inconsistent.");
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
hasGivenError = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-05 07:44:40 +00:00
|
|
|
return;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
((int *)ccgSubSurf_getFaceUserData(ss, f))[1] = (index) ? *index++ : i;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ccgSubSurf_processSync(ss);
|
2009-08-29 23:55:35 +00:00
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_free(fVerts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2005-03-21 01:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
ccgSubSurf_initFullSync(ss);
|
|
|
|
|
ccgSubSurf_prepareTopologyRefiner(ss, dm);
|
|
|
|
|
ccgSubSurf_processSync(ss);
|
|
|
|
|
}
|
|
|
|
|
#endif /* WITH_OPENSUBDIV */
|
|
|
|
|
|
|
|
|
|
static void ss_sync_from_derivedmesh(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
float (*vertexCos)[3],
|
2016-07-22 17:52:30 +02:00
|
|
|
int use_flat_subdiv,
|
|
|
|
|
bool use_subdiv_uvs)
|
2015-07-20 16:08:06 +02:00
|
|
|
{
|
2016-07-23 03:59:18 +10:00
|
|
|
#ifndef WITH_OPENSUBDIV
|
|
|
|
|
UNUSED_VARS(use_subdiv_uvs);
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
/* Reset all related descriptors if actual mesh topology changed or if
|
2015-09-14 02:21:15 +10:00
|
|
|
* other evaluation-related settings changed.
|
2015-07-20 16:08:06 +02:00
|
|
|
*/
|
|
|
|
|
if (!ccgSubSurf_needGrids(ss)) {
|
|
|
|
|
/* TODO(sergey): Use vertex coordinates and flat subdiv flag. */
|
2016-07-22 17:52:30 +02:00
|
|
|
ccgSubSurf__sync_subdivUvs(ss, use_subdiv_uvs);
|
2015-08-03 17:30:44 +02:00
|
|
|
ccgSubSurf_checkTopologyChanged(ss, dm);
|
2015-07-20 16:08:06 +02:00
|
|
|
ss_sync_osd_from_derivedmesh(ss, dm);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-30 08:12:27 +00:00
|
|
|
/***/
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
return ((int *) ccgSubSurf_getVertUserData(ss, v))[1];
|
2005-08-07 05:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
return ((int *) ccgSubSurf_getEdgeUserData(ss, e))[1];
|
2005-08-07 05:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
return ((int *) ccgSubSurf_getFaceUserData(ss, f))[1];
|
2005-08-07 05:42:03 +00:00
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
static void minmax_v3_v3v3(const float vec[3], float min[3], float max[3])
|
|
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
if (min[0] > vec[0]) min[0] = vec[0];
|
|
|
|
|
if (min[1] > vec[1]) min[1] = vec[1];
|
|
|
|
|
if (min[2] > vec[2]) min[2] = vec[2];
|
|
|
|
|
if (max[0] < vec[0]) max[0] = vec[0];
|
|
|
|
|
if (max[1] < vec[1]) max[1] = vec[1];
|
|
|
|
|
if (max[2] < vec[2]) max[2] = vec[2];
|
2012-05-10 20:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-16 03:24:05 +11:00
|
|
|
static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVertIterator vi;
|
|
|
|
|
CCGEdgeIterator ei;
|
|
|
|
|
CCGFaceIterator fi;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2005-07-17 04:17:33 +00:00
|
|
|
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
|
2015-08-05 14:43:51 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
ccgSubSurf_getMinMax(ccgdm->ss, r_min, r_max);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2015-09-30 20:57:02 +05:00
|
|
|
if (!ccgSubSurf_getNumVerts(ss))
|
|
|
|
|
r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0;
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
|
|
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
2005-07-17 04:17:33 +00:00
|
|
|
float *co = ccgSubSurf_getVertData(ss, v);
|
|
|
|
|
|
2014-03-16 03:24:05 +11:00
|
|
|
minmax_v3_v3v3(co, r_min, r_max);
|
2005-07-17 04:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
|
2005-07-17 04:17:33 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (i = 0; i < edgeSize; i++)
|
2014-03-16 03:24:05 +11:00
|
|
|
minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max);
|
2005-07-17 04:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2008-09-29 17:08:11 +00:00
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2005-07-17 04:17:33 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
2005-07-17 04:17:33 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (y = 0; y < gridSize; y++)
|
|
|
|
|
for (x = 0; x < gridSize; x++)
|
2014-03-16 03:24:05 +11:00
|
|
|
minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max);
|
2005-07-17 04:17:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static int ccgDM_getNumVerts(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static int ccgDM_getNumEdges(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2015-08-17 17:24:34 +10:00
|
|
|
static int ccgDM_getNumPolys(DerivedMesh *dm)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2015-08-17 17:24:34 +10:00
|
|
|
static int ccgDM_getNumTessFaces(DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
return dm->numTessFaceData;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static int ccgDM_getNumLoops(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2011-11-30 18:03:56 +00:00
|
|
|
|
|
|
|
|
/* All subsurf faces are quads */
|
2012-02-05 08:18:34 +00:00
|
|
|
return 4 * ccgSubSurf_getNumFinalFaces(ccgdm->ss);
|
2011-11-30 18:03:56 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *vd;
|
|
|
|
|
CCGKey key;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
int i;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
2006-08-28 01:12:36 +00:00
|
|
|
memset(mv, 0, sizeof(*mv));
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* this vert comes from face data */
|
|
|
|
|
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
|
|
|
|
|
CCGFace *f;
|
|
|
|
|
int x, y, grid, numVerts;
|
|
|
|
|
int offset;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridSideVerts;
|
|
|
|
|
int gridInternalVerts;
|
|
|
|
|
int gridSideEnd;
|
|
|
|
|
int gridInternalEnd;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
2012-05-09 09:24:15 +00:00
|
|
|
while (i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert) {
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
f = ccgdm->faceMap[i].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
gridSideVerts = gridSize - 2;
|
|
|
|
|
gridInternalVerts = gridSideVerts * gridSideVerts;
|
|
|
|
|
|
|
|
|
|
gridSideEnd = 1 + numVerts * gridSideVerts;
|
|
|
|
|
gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
|
|
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
offset = vertNum - ccgdm->faceMap[i].startVert;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (offset < 1) {
|
2010-04-05 11:11:15 +00:00
|
|
|
vd = ccgSubSurf_getFaceCenterData(f);
|
2012-05-10 20:33:09 +00:00
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if (offset < gridSideEnd) {
|
2006-08-28 01:12:36 +00:00
|
|
|
offset -= 1;
|
|
|
|
|
grid = offset / gridSideVerts;
|
|
|
|
|
x = offset % gridSideVerts + 1;
|
2010-04-05 11:11:15 +00:00
|
|
|
vd = ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
|
2012-05-10 20:33:09 +00:00
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if (offset < gridInternalEnd) {
|
2006-08-28 01:12:36 +00:00
|
|
|
offset -= gridSideEnd;
|
|
|
|
|
grid = offset / gridInternalVerts;
|
|
|
|
|
offset %= gridInternalVerts;
|
|
|
|
|
y = offset / gridSideVerts + 1;
|
|
|
|
|
x = offset % gridSideVerts + 1;
|
2010-04-05 11:11:15 +00:00
|
|
|
vd = ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
|
2012-05-10 20:33:09 +00:00
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if ((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* this vert comes from edge data */
|
|
|
|
|
CCGEdge *e;
|
|
|
|
|
int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
|
|
|
|
|
int x;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
2012-05-09 09:24:15 +00:00
|
|
|
while (i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert) {
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
e = ccgdm->edgeMap[i].edge;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
x = vertNum - ccgdm->edgeMap[i].startVert + 1;
|
2010-04-05 11:11:15 +00:00
|
|
|
vd = ccgSubSurf_getEdgeData(ss, e, x);
|
2012-05-10 20:33:09 +00:00
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* this vert comes from vert data */
|
|
|
|
|
CCGVert *v;
|
2012-02-05 08:18:34 +00:00
|
|
|
i = vertNum - ccgdm->vertMap[0].startVert;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
v = ccgdm->vertMap[i].vert;
|
2010-04-05 11:11:15 +00:00
|
|
|
vd = ccgSubSurf_getVertData(ss, v);
|
2012-05-10 20:33:09 +00:00
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-16 03:24:05 +11:00
|
|
|
static void ccgDM_getFinalVertCo(DerivedMesh *dm, int vertNum, float r_co[3])
|
2010-04-05 11:11:15 +00:00
|
|
|
{
|
|
|
|
|
MVert mvert;
|
|
|
|
|
|
|
|
|
|
ccgDM_getFinalVert(dm, vertNum, &mvert);
|
2014-03-16 03:24:05 +11:00
|
|
|
copy_v3_v3(r_co, mvert.co);
|
2010-04-05 11:11:15 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-16 03:24:05 +11:00
|
|
|
static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3])
|
2010-04-05 11:11:15 +00:00
|
|
|
{
|
|
|
|
|
MVert mvert;
|
|
|
|
|
|
|
|
|
|
ccgDM_getFinalVert(dm, vertNum, &mvert);
|
2014-03-16 03:24:05 +11:00
|
|
|
normal_short_to_float_v3(r_no, mvert.no);
|
2010-04-05 11:11:15 +00:00
|
|
|
}
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2006-08-28 01:12:36 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
memset(med, 0, sizeof(*med));
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (edgeNum < ccgdm->edgeMap[0].startEdge) {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* this edge comes from face data */
|
|
|
|
|
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
|
|
|
|
|
CCGFace *f;
|
2011-01-10 03:55:47 +00:00
|
|
|
int x, y, grid /*, numVerts*/;
|
2006-08-28 01:12:36 +00:00
|
|
|
int offset;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int gridSideEdges;
|
|
|
|
|
int gridInternalEdges;
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2011-12-05 05:28:31 +00:00
|
|
|
/* code added in bmesh but works correctly without, commenting - campbell */
|
|
|
|
|
#if 0
|
2012-04-22 00:20:58 +00:00
|
|
|
int lasti, previ;
|
|
|
|
|
i = lastface;
|
|
|
|
|
lasti = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
previ = i;
|
|
|
|
|
if (ccgdm->faceMap[i].startEdge >= edgeNum) {
|
|
|
|
|
i -= fabsf(i - lasti) / 2.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (ccgdm->faceMap[i].startEdge < edgeNum) {
|
|
|
|
|
i += fabsf(i - lasti) / 2.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (i < 0) {
|
|
|
|
|
i = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (i > lastface) {
|
|
|
|
|
i = lastface;
|
|
|
|
|
break;
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
}
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (i == lasti)
|
|
|
|
|
break;
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
lasti = previ;
|
|
|
|
|
}
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
i = i > 0 ? i - 1 : i;
|
2011-12-05 05:28:31 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
i = 0;
|
2012-05-09 09:24:15 +00:00
|
|
|
while (i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge) {
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
f = ccgdm->faceMap[i].face;
|
2011-01-10 03:55:47 +00:00
|
|
|
/* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
gridSideEdges = gridSize - 1;
|
|
|
|
|
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
|
|
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
offset = edgeNum - ccgdm->faceMap[i].startEdge;
|
2006-08-28 01:12:36 +00:00
|
|
|
grid = offset / (gridSideEdges + gridInternalEdges);
|
|
|
|
|
offset %= (gridSideEdges + gridInternalEdges);
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (offset < gridSideEdges) {
|
2006-08-28 01:12:36 +00:00
|
|
|
x = offset;
|
|
|
|
|
med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
|
2012-04-22 00:20:58 +00:00
|
|
|
med->v2 = getFaceIndex(ss, f, grid, x + 1, 0, edgeSize, gridSize);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2006-08-28 01:12:36 +00:00
|
|
|
offset -= gridSideEdges;
|
|
|
|
|
x = (offset / 2) / gridSideEdges + 1;
|
|
|
|
|
y = (offset / 2) % gridSideEdges;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (offset % 2 == 0) {
|
2006-08-28 01:12:36 +00:00
|
|
|
med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
|
2012-04-22 00:20:58 +00:00
|
|
|
med->v2 = getFaceIndex(ss, f, grid, x, y + 1, edgeSize, gridSize);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2006-08-28 01:12:36 +00:00
|
|
|
med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
|
2012-04-22 00:20:58 +00:00
|
|
|
med->v2 = getFaceIndex(ss, f, grid, y + 1, x, edgeSize, gridSize);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* this vert comes from edge data */
|
|
|
|
|
CCGEdge *e;
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2009-11-25 13:11:44 +00:00
|
|
|
int x;
|
|
|
|
|
short *edgeFlag;
|
2006-08-28 01:12:36 +00:00
|
|
|
unsigned int flags = 0;
|
|
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
e = ccgdm->edgeMap[i].edge;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
x = edgeNum - ccgdm->edgeMap[i].startEdge;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
med->v1 = getEdgeIndex(ss, e, x, edgeSize);
|
2012-04-22 00:20:58 +00:00
|
|
|
med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeFlag = (ccgdm->edgeFlags) ? &ccgdm->edgeFlags[i] : NULL;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (edgeFlag)
|
2012-04-22 00:20:58 +00:00
|
|
|
flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER;
|
2007-08-28 08:53:36 +00:00
|
|
|
else
|
|
|
|
|
flags |= ME_EDGEDRAW | ME_EDGERENDER;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
med->flag = flags;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2006-08-28 01:12:36 +00:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int gridSideEdges = gridSize - 1;
|
|
|
|
|
int gridFaces = gridSideEdges * gridSideEdges;
|
|
|
|
|
int i;
|
|
|
|
|
CCGFace *f;
|
2011-01-10 03:55:47 +00:00
|
|
|
/*int numVerts;*/
|
2006-08-28 01:12:36 +00:00
|
|
|
int offset;
|
|
|
|
|
int grid;
|
|
|
|
|
int x, y;
|
2011-05-13 13:17:30 +00:00
|
|
|
/*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
memset(mf, 0, sizeof(*mf));
|
2012-02-05 08:18:34 +00:00
|
|
|
if (faceNum >= ccgdm->dm.numTessFaceData)
|
2009-09-15 15:32:09 +00:00
|
|
|
return;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
i = ccgdm->reverseFaceMap[faceNum];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
f = ccgdm->faceMap[i].face;
|
2011-01-10 03:55:47 +00:00
|
|
|
/*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
offset = faceNum - ccgdm->faceMap[i].startFace;
|
2006-08-28 01:12:36 +00:00
|
|
|
grid = offset / gridFaces;
|
|
|
|
|
offset %= gridFaces;
|
|
|
|
|
y = offset / gridSideEdges;
|
|
|
|
|
x = offset % gridSideEdges;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
mf->v1 = getFaceIndex(ss, f, grid, x + 0, y + 0, edgeSize, gridSize);
|
|
|
|
|
mf->v2 = getFaceIndex(ss, f, grid, x + 0, y + 1, edgeSize, gridSize);
|
|
|
|
|
mf->v3 = getFaceIndex(ss, f, grid, x + 1, y + 1, edgeSize, gridSize);
|
|
|
|
|
mf->v4 = getFaceIndex(ss, f, grid, x + 1, y + 0, edgeSize, gridSize);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (faceFlags) {
|
2012-03-06 00:17:03 +00:00
|
|
|
mf->flag = faceFlags[i].flag;
|
|
|
|
|
mf->mat_nr = faceFlags[i].mat_nr;
|
2010-02-16 10:36:17 +00:00
|
|
|
}
|
2013-01-21 09:54:33 +00:00
|
|
|
else {
|
|
|
|
|
mf->flag = ME_SMOOTH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mf->edcode = 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-14 06:32:13 +00:00
|
|
|
/* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes
|
2012-04-22 11:54:53 +00:00
|
|
|
* vertices are in the order output by ccgDM_copyFinalVertArray. */
|
2012-03-14 06:32:13 +00:00
|
|
|
void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
|
2012-04-22 00:20:58 +00:00
|
|
|
MVert *mvert, const MDisps *mdisps)
|
2012-03-14 06:32:13 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-03-14 06:32:13 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
int level = ccgSubSurf_getSubdivisionLevels(ss);
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int i, j, x, y;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2012-03-14 06:32:13 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (j = 0; j < mpoly[i].totloop; j++) {
|
2012-03-14 06:32:13 +00:00
|
|
|
const MDisps *md = &mdisps[mpoly[i].loopstart + j];
|
2013-10-01 09:17:35 +00:00
|
|
|
int hidden_gridsize = BKE_ccg_gridsize(md->level);
|
|
|
|
|
int factor = BKE_ccg_factor(level, md->level);
|
2015-01-14 05:10:18 +11:00
|
|
|
BLI_bitmap *hidden = md->hidden;
|
2012-03-14 06:32:13 +00:00
|
|
|
|
2015-01-14 05:10:18 +11:00
|
|
|
if (!hidden)
|
2012-03-14 06:32:13 +00:00
|
|
|
continue;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (y = 0; y < gridSize; y++) {
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
2012-03-14 06:32:13 +00:00
|
|
|
int vndx, offset;
|
|
|
|
|
|
|
|
|
|
vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
|
2012-04-22 00:20:58 +00:00
|
|
|
offset = (y * factor) * hidden_gridsize + (x * factor);
|
2015-01-14 05:10:18 +11:00
|
|
|
if (BLI_BITMAP_TEST(hidden, offset))
|
2012-03-14 06:32:13 +00:00
|
|
|
mvert[vndx].flag |= ME_HIDE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:34:23 +00:00
|
|
|
/* Translate GridPaintMask into vertex paint masks. Assumes vertices
|
2012-05-16 23:37:23 +00:00
|
|
|
* are in the order output by ccgDM_copyFinalVertArray. */
|
2012-05-10 20:34:23 +00:00
|
|
|
void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly,
|
2012-05-11 08:05:47 +00:00
|
|
|
float *paint_mask,
|
|
|
|
|
const GridPaintMask *grid_paint_mask)
|
2012-05-10 20:34:23 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-05-10 20:34:23 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
int level = ccgSubSurf_getSubdivisionLevels(ss);
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int i, j, x, y, factor, gpm_gridsize;
|
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2012-05-10 20:34:23 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
const MPoly *p = &mpoly[i];
|
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (j = 0; j < p->totloop; j++) {
|
2012-05-10 20:34:23 +00:00
|
|
|
const GridPaintMask *gpm = &grid_paint_mask[p->loopstart + j];
|
2012-05-11 08:05:47 +00:00
|
|
|
if (!gpm->data)
|
2012-05-10 20:34:23 +00:00
|
|
|
continue;
|
|
|
|
|
|
2013-10-01 09:17:35 +00:00
|
|
|
factor = BKE_ccg_factor(level, gpm->level);
|
|
|
|
|
gpm_gridsize = BKE_ccg_gridsize(gpm->level);
|
2012-05-10 20:34:23 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (y = 0; y < gridSize; y++) {
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
2012-05-10 20:34:23 +00:00
|
|
|
int vndx, offset;
|
|
|
|
|
|
|
|
|
|
vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
|
2012-05-11 08:05:47 +00:00
|
|
|
offset = y * factor * gpm_gridsize + x * factor;
|
2012-05-10 20:34:23 +00:00
|
|
|
paint_mask[vndx] = gpm->data[offset];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-24 11:28:26 +00:00
|
|
|
/* utility functon */
|
|
|
|
|
BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem)
|
|
|
|
|
{
|
|
|
|
|
copy_v3_v3(mv->co, CCG_elem_co(key, elem));
|
|
|
|
|
normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem));
|
|
|
|
|
mv->flag = mv->bweight = 0;
|
|
|
|
|
}
|
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *vd;
|
|
|
|
|
CCGKey key;
|
2006-08-28 01:12:36 +00:00
|
|
|
int index;
|
|
|
|
|
int totvert, totedge, totface;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2013-01-24 11:28:26 +00:00
|
|
|
unsigned int i = 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
vd = ccgSubSurf_getFaceCenterData(f);
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MVert(&mvert[i++], &key, vd);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2013-01-24 11:28:26 +00:00
|
|
|
for (x = 1; x < gridSize - 1; x++) {
|
2012-04-22 00:20:58 +00:00
|
|
|
vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MVert(&mvert[i++], &key, vd);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 1; y < gridSize - 1; y++) {
|
2013-01-24 11:28:26 +00:00
|
|
|
for (x = 1; x < gridSize - 1; x++) {
|
2012-04-22 00:20:58 +00:00
|
|
|
vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MVert(&mvert[i++], &key, vd);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totedge = ccgSubSurf_getNumEdges(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totedge; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGEdge *e = ccgdm->edgeMap[index].edge;
|
2006-08-28 01:12:36 +00:00
|
|
|
int x;
|
|
|
|
|
|
2013-01-24 11:28:26 +00:00
|
|
|
for (x = 1; x < edgeSize - 1; x++) {
|
2011-03-30 02:05:10 +00:00
|
|
|
/* This gives errors with -debug-fpe
|
2012-03-18 07:38:51 +00:00
|
|
|
* the normals don't seem to be unit length.
|
2011-03-30 02:05:10 +00:00
|
|
|
* this is most likely caused by edges with no
|
|
|
|
|
* faces which are now zerod out, see comment in:
|
|
|
|
|
* ccgSubSurf__calcVertNormals(), - campbell */
|
2013-01-24 11:28:26 +00:00
|
|
|
vd = ccgSubSurf_getEdgeData(ss, e, x);
|
|
|
|
|
ccgDM_to_MVert(&mvert[i++], &key, vd);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totvert = ccgSubSurf_getNumVerts(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totvert; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGVert *v = ccgdm->vertMap[index].vert;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
vd = ccgSubSurf_getVertData(ss, v);
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MVert(&mvert[i++], &key, vd);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-24 11:28:26 +00:00
|
|
|
|
|
|
|
|
/* utility functon */
|
|
|
|
|
BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag)
|
|
|
|
|
{
|
|
|
|
|
med->v1 = v1;
|
|
|
|
|
med->v2 = v2;
|
|
|
|
|
med->crease = med->bweight = 0;
|
|
|
|
|
med->flag = flag;
|
|
|
|
|
}
|
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2006-08-28 01:12:36 +00:00
|
|
|
int index;
|
|
|
|
|
int totedge, totface;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2013-01-24 11:28:26 +00:00
|
|
|
unsigned int i = 0;
|
2012-02-05 08:18:34 +00:00
|
|
|
short *edgeFlags = ccgdm->edgeFlags;
|
2013-01-21 09:54:33 +00:00
|
|
|
const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (x = 0; x < gridSize - 1; x++) {
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MEdge(&medge[i++],
|
|
|
|
|
getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
|
|
|
|
|
getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
|
|
|
|
|
ed_interior_flag);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (x = 1; x < gridSize - 1; x++) {
|
|
|
|
|
for (y = 0; y < gridSize - 1; y++) {
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MEdge(&medge[i++],
|
|
|
|
|
getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
|
|
|
|
|
getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
|
|
|
|
|
ed_interior_flag);
|
|
|
|
|
ccgDM_to_MEdge(&medge[i++],
|
|
|
|
|
getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
|
|
|
|
|
getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
|
|
|
|
|
ed_interior_flag);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totedge = ccgSubSurf_getNumEdges(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totedge; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGEdge *e = ccgdm->edgeMap[index].edge;
|
2013-01-24 11:28:26 +00:00
|
|
|
short ed_flag = 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
int x;
|
2008-09-29 17:08:11 +00:00
|
|
|
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2013-01-24 11:28:26 +00:00
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e)) {
|
|
|
|
|
ed_flag |= ME_LOOSEEDGE;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (edgeFlags) {
|
|
|
|
|
if (edgeIdx != -1) {
|
2013-01-24 11:28:26 +00:00
|
|
|
ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
|
2006-12-07 18:30:00 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2013-01-24 11:28:26 +00:00
|
|
|
ed_flag |= ME_EDGEDRAW | ME_EDGERENDER;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (x = 0; x < edgeSize - 1; x++) {
|
2013-01-24 11:28:26 +00:00
|
|
|
ccgDM_to_MEdge(&medge[i++],
|
|
|
|
|
getEdgeIndex(ss, e, x, edgeSize),
|
|
|
|
|
getEdgeIndex(ss, e, x + 1, edgeSize),
|
|
|
|
|
ed_flag);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2011-06-14 03:16:08 +00:00
|
|
|
int index;
|
|
|
|
|
int totface;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int i = 0;
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2015-08-17 17:24:34 +10:00
|
|
|
totface = dm->getNumTessFaces(dm);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2011-06-14 03:16:08 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2011-09-20 06:25:15 +00:00
|
|
|
/* keep types in sync with MFace, avoid many conversions */
|
2012-04-22 00:20:58 +00:00
|
|
|
char flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
|
|
|
|
|
short mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
|
2009-06-12 14:02:37 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridSize - 1; y++) {
|
|
|
|
|
for (x = 0; x < gridSize - 1; x++) {
|
2011-06-14 03:16:08 +00:00
|
|
|
MFace *mf = &mface[i];
|
|
|
|
|
mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeSize, gridSize);
|
2011-06-14 03:16:08 +00:00
|
|
|
mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeSize, gridSize);
|
2011-06-14 03:16:08 +00:00
|
|
|
mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeSize, gridSize);
|
2011-06-14 03:16:08 +00:00
|
|
|
mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeSize, gridSize);
|
2011-06-14 03:16:08 +00:00
|
|
|
mf->mat_nr = mat_nr;
|
|
|
|
|
mf->flag = flag;
|
2013-01-21 09:54:33 +00:00
|
|
|
mf->edcode = 0;
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
}
|
|
|
|
|
|
2018-01-11 14:49:32 +01:00
|
|
|
typedef struct CopyFinalLoopArrayData {
|
|
|
|
|
CCGDerivedMesh *ccgdm;
|
|
|
|
|
MLoop *mloop;
|
|
|
|
|
int grid_size;
|
|
|
|
|
int *grid_offset;
|
|
|
|
|
int edge_size;
|
|
|
|
|
size_t mloop_index;
|
|
|
|
|
} CopyFinalLoopArrayData;
|
|
|
|
|
|
|
|
|
|
static void copyFinalLoopArray_task_cb(
|
|
|
|
|
void *__restrict userdata,
|
|
|
|
|
const int iter,
|
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
|
|
|
|
{
|
|
|
|
|
CopyFinalLoopArrayData *data = userdata;
|
|
|
|
|
CCGDerivedMesh *ccgdm = data->ccgdm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
const int grid_size = data->grid_size;
|
|
|
|
|
const int edge_size = data->edge_size;
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[iter].face;
|
|
|
|
|
const int num_verts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
const int grid_index = data->grid_offset[iter];
|
|
|
|
|
const size_t loop_index = 4 * (size_t)grid_index * (grid_size - 1) * (grid_size - 1);
|
|
|
|
|
MLoop *ml = &data->mloop[loop_index];
|
|
|
|
|
for (int S = 0; S < num_verts; S++) {
|
|
|
|
|
for (int y = 0; y < grid_size - 1; y++) {
|
|
|
|
|
for (int x = 0; x < grid_size - 1; x++) {
|
|
|
|
|
|
|
|
|
|
uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
|
|
|
|
|
edge_size, grid_size);
|
|
|
|
|
uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
|
|
|
|
|
edge_size, grid_size);
|
|
|
|
|
uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
|
|
|
|
|
edge_size, grid_size);
|
|
|
|
|
uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
|
|
|
|
|
edge_size, grid_size);
|
|
|
|
|
|
|
|
|
|
ml->v = v1;
|
|
|
|
|
ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(ccgdm->ehash, v1, v2));
|
|
|
|
|
ml++;
|
|
|
|
|
|
|
|
|
|
ml->v = v2;
|
|
|
|
|
ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(ccgdm->ehash, v2, v3));
|
|
|
|
|
ml++;
|
|
|
|
|
|
|
|
|
|
ml->v = v3;
|
|
|
|
|
ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(ccgdm->ehash, v3, v4));
|
|
|
|
|
ml++;
|
|
|
|
|
|
|
|
|
|
ml->v = v4;
|
|
|
|
|
ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(ccgdm->ehash, v4, v1));
|
|
|
|
|
ml++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
if (!ccgdm->ehash) {
|
2018-01-11 14:32:56 +01:00
|
|
|
BLI_mutex_lock(&ccgdm->loops_cache_lock);
|
2014-05-03 15:58:37 +02:00
|
|
|
if (!ccgdm->ehash) {
|
|
|
|
|
MEdge *medge;
|
2017-12-22 12:50:06 +01:00
|
|
|
EdgeHash *ehash;
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2017-12-22 12:50:06 +01:00
|
|
|
ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData);
|
2014-05-03 15:58:37 +02:00
|
|
|
medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm);
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2018-01-10 14:58:09 +01:00
|
|
|
for (int i = 0; i < ccgdm->dm.numEdgeData; i++) {
|
2017-12-22 12:50:06 +01:00
|
|
|
BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i));
|
2014-05-03 15:58:37 +02:00
|
|
|
}
|
2017-12-22 12:50:06 +01:00
|
|
|
|
2018-01-21 11:41:28 +11:00
|
|
|
atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
|
2011-06-14 03:16:08 +00:00
|
|
|
}
|
2018-01-11 14:32:56 +01:00
|
|
|
BLI_mutex_unlock(&ccgdm->loops_cache_lock);
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
}
|
|
|
|
|
|
2018-01-11 14:49:32 +01:00
|
|
|
CopyFinalLoopArrayData data;
|
|
|
|
|
data.ccgdm = ccgdm;
|
|
|
|
|
data.mloop = mloop;
|
|
|
|
|
data.grid_size = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
data.grid_offset = dm->getGridOffset(dm);
|
|
|
|
|
data.edge_size = ccgSubSurf_getEdgeSize(ss);
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2018-01-11 14:49:32 +01:00
|
|
|
/* NOTE: For a dense subdivision we've got enough work for each face and
|
|
|
|
|
* hence can dedicate whole thread to single face. For less dense
|
|
|
|
|
* subdivision we handle multiple faces per thread.
|
|
|
|
|
*/
|
|
|
|
|
data.mloop_index = data.grid_size >= 5 ? 1 : 8;
|
(NOTE: DO NOT TEST)
Start of planned DerivedMesh refactoring. The mface
interfaces in DerivedMesh have been renamed to reflect
their new status as tesselated face interfaces (rather
then the primary ones, which are now stored in mpolys).
short review: mpolys store "primary" face data, while
mfaces store the tesselated form of the mesh (generally
as triangles). mpolys are defined by mloops, and each
mpoly defines a range of loops it "owns" in the main
mloop array.
I've also added basic read-only face iterators, which
are implemented for CDDM, ccgsubsurf, and the bmeditmesh
derivedmesh. Since faces are now variable-length things,
trying to implement the same interface as mfaces would not
have worked well (especially since faces are stored as
an mpoly + a range of mloops).
I figure first we can evaluate these simple read-only
face iterators, then decide if a) we like using iterators
in DerivedMesh, b) how much of it should use them, and c)
if we want write-capable iterators.
I plan to write official docs on this design after I get
it more stable; I'm committing now because there's a rather
lot of changes, and I might do a merge soon.
2009-06-10 10:06:25 +00:00
|
|
|
|
2018-01-11 14:49:32 +01:00
|
|
|
ParallelRangeSettings settings;
|
|
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
|
settings.min_iter_per_thread = 1;
|
2009-09-15 15:32:09 +00:00
|
|
|
|
2018-01-11 14:49:32 +01:00
|
|
|
BLI_task_parallel_range(0, ccgSubSurf_getNumFaces(ss),
|
|
|
|
|
&data,
|
|
|
|
|
copyFinalLoopArray_task_cb,
|
|
|
|
|
&settings);
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-03 23:40:24 +00:00
|
|
|
static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2006-08-28 01:12:36 +00:00
|
|
|
int index;
|
|
|
|
|
int totface;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
2011-08-28 21:20:10 +00:00
|
|
|
/* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
|
2011-06-14 03:16:08 +00:00
|
|
|
int i = 0, k = 0;
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2012-04-22 00:20:58 +00:00
|
|
|
int flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
|
|
|
|
|
int mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridSize - 1; y++) {
|
|
|
|
|
for (x = 0; x < gridSize - 1; x++) {
|
2012-04-03 23:40:24 +00:00
|
|
|
MPoly *mp = &mpoly[i];
|
2011-06-14 03:16:08 +00:00
|
|
|
|
2012-04-03 23:40:24 +00:00
|
|
|
mp->mat_nr = mat_nr;
|
|
|
|
|
mp->flag = flag;
|
|
|
|
|
mp->loopstart = k;
|
|
|
|
|
mp->totloop = 4;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2011-06-14 03:16:08 +00:00
|
|
|
k += 4;
|
2006-08-28 01:12:36 +00:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2006-08-28 01:12:36 +00:00
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int i;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVertIterator vi;
|
|
|
|
|
CCGEdgeIterator ei;
|
|
|
|
|
CCGFaceIterator fi;
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGFace **faceMap2;
|
2005-08-23 02:05:45 +00:00
|
|
|
CCGEdge **edgeMap2;
|
|
|
|
|
CCGVert **vertMap2;
|
|
|
|
|
int index, totvert, totedge, totface;
|
|
|
|
|
|
|
|
|
|
totvert = ccgSubSurf_getNumVerts(ss);
|
2012-04-22 00:20:58 +00:00
|
|
|
vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
|
|
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
2005-08-23 02:05:45 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-23 02:05:45 +00:00
|
|
|
totedge = ccgSubSurf_getNumEdges(ss);
|
2012-04-22 00:20:58 +00:00
|
|
|
edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); i++, ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-23 02:05:45 +00:00
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-04-22 00:20:58 +00:00
|
|
|
faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2005-08-23 02:05:45 +00:00
|
|
|
|
2012-03-06 01:01:42 +00:00
|
|
|
faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
|
2005-08-23 02:05:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2005-08-23 02:05:45 +00:00
|
|
|
CCGFace *f = faceMap2[index];
|
2008-09-29 17:08:11 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
|
2005-08-23 02:05:45 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (x = 1; x < gridSize - 1; x++) {
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
|
2005-08-23 02:05:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 1; y < gridSize - 1; y++) {
|
|
|
|
|
for (x = 1; x < gridSize - 1; x++) {
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
|
2005-08-23 02:05:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
2005-08-23 02:05:45 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < totedge; index++) {
|
|
|
|
|
CCGEdge *e = edgeMap2[index];
|
2005-08-23 02:05:45 +00:00
|
|
|
int x;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (x = 1; x < edgeSize - 1; x++) {
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
|
2005-08-23 02:05:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < totvert; index++) {
|
2005-08-23 02:05:45 +00:00
|
|
|
CCGVert *v = vertMap2[index];
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
|
2005-08-23 02:05:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(vertMap2);
|
|
|
|
|
MEM_freeN(edgeMap2);
|
|
|
|
|
MEM_freeN(faceMap2);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2012-04-09 07:06:06 +00:00
|
|
|
static void ccgDM_foreachMappedVert(
|
2012-08-23 16:17:47 +00:00
|
|
|
DerivedMesh *dm,
|
|
|
|
|
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
|
2013-07-22 22:59:47 +00:00
|
|
|
void *userData,
|
|
|
|
|
DMForeachFlag flag)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVertIterator vi;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
|
|
|
|
CCG_key_top_level(&key, ccgdm->ss);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
|
|
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
2013-07-22 22:59:47 +00:00
|
|
|
const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2013-07-22 22:59:47 +00:00
|
|
|
if (index != -1) {
|
|
|
|
|
CCGElem *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
|
|
|
|
|
const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
|
|
|
|
|
func(userData, index, CCG_elem_co(&key, vd), no, NULL);
|
|
|
|
|
}
|
Big commit, had to rework lots of selection stuff so that things
worked properly with modifiers. Needs more testing I am sure.
No, honestly, I wasn't just cleaning for the hell of it, it
was *necessary* (I would never do such a thing). Selection should
work completely with cage options of modifiers now.
- added DerivedMesh foreach functions to iterate over mapped
verts/edges/face centers. These replaced some of the drawing
functions and are more general anyway. Special edge drawing
functions remain for performance reasons.
- removed EditFace xs, ys fields
- added general functions to iterate over screen coordinates of
mesh/curve/lattice objects
- removed all calc_*verts* functions that were used for storing
screen coordinates in objects. they were recalc'd on the fly
for most situations anyway, so now we just always do that.
calc_*verts_ext was one of those calls that did dirty things
deep down in the callstack (changing curarea and poking at
matrices)
- rewrote all vertex level selection routines (circle, lasso, bbox)
and closest vertex routines (rightmouse select) to use the new
system. This cleaned up the selection code a lot and the structure
of selection is much easier to see now. This is good for future
work on allowing modifiers to completely override the selection
system. It also points out some discrepancies in the way selection
is handled that might be nice to resolve (mesh vertex selection has
fancy stuff to try to help with selecting overlapping, but it only
works w/o bbuf select, and curves/lattices don't have at all).
- had to remove ton's code to move Manipulator to cage location, this
is not reliable (can come up with a different method if requested)
- as it happens BezTriple.s and BPoint.s are basically available to
be removed, just need to rewrite editipo code that still does
background calc of screen coordinates
- MVert.{xs,ys} are still around because they are abused in some places
for other info (not sure if this is safe actually, since they are
short's and the mvert limit went up).
And did I mention this commit is comes out to -305 lines? Well it does.
2005-08-09 08:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2012-04-09 07:06:06 +00:00
|
|
|
static void ccgDM_foreachMappedEdge(
|
2012-08-23 16:17:47 +00:00
|
|
|
DerivedMesh *dm,
|
|
|
|
|
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
|
|
|
|
|
void *userData)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGEdgeIterator ei;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
Big commit, had to rework lots of selection stuff so that things
worked properly with modifiers. Needs more testing I am sure.
No, honestly, I wasn't just cleaning for the hell of it, it
was *necessary* (I would never do such a thing). Selection should
work completely with cage options of modifiers now.
- added DerivedMesh foreach functions to iterate over mapped
verts/edges/face centers. These replaced some of the drawing
functions and are more general anyway. Special edge drawing
functions remain for performance reasons.
- removed EditFace xs, ys fields
- added general functions to iterate over screen coordinates of
mesh/curve/lattice objects
- removed all calc_*verts* functions that were used for storing
screen coordinates in objects. they were recalc'd on the fly
for most situations anyway, so now we just always do that.
calc_*verts_ext was one of those calls that did dirty things
deep down in the callstack (changing curarea and poking at
matrices)
- rewrote all vertex level selection routines (circle, lasso, bbox)
and closest vertex routines (rightmouse select) to use the new
system. This cleaned up the selection code a lot and the structure
of selection is much easier to see now. This is good for future
work on allowing modifiers to completely override the selection
system. It also points out some discrepancies in the way selection
is handled that might be nice to resolve (mesh vertex selection has
fancy stuff to try to help with selecting overlapping, but it only
works w/o bbuf select, and curves/lattices don't have at all).
- had to remove ton's code to move Manipulator to cage location, this
is not reliable (can come up with a different method if requested)
- as it happens BezTriple.s and BPoint.s are basically available to
be removed, just need to rewrite editipo code that still does
background calc of screen coordinates
- MVert.{xs,ys} are still around because they are abused in some places
for other info (not sure if this is safe actually, since they are
short's and the mvert limit went up).
And did I mention this commit is comes out to -305 lines? Well it does.
2005-08-09 08:12:36 +00:00
|
|
|
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
2013-07-22 22:59:47 +00:00
|
|
|
const int index = ccgDM_getEdgeMapIndex(ss, e);
|
2005-08-07 05:42:03 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (index != -1) {
|
2013-07-22 22:59:47 +00:00
|
|
|
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
|
|
|
|
|
for (i = 0; i < edgeSize - 1; i++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
func(userData, index, CCG_elem_offset_co(&key, edgeData, i), CCG_elem_offset_co(&key, edgeData, i + 1));
|
2013-07-22 22:59:47 +00:00
|
|
|
}
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
}
|
2005-08-07 05:42:03 +00:00
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-23 15:18:11 +02:00
|
|
|
static void ccgDM_foreachMappedLoop(
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
|
|
|
|
|
void *userData,
|
|
|
|
|
DMForeachFlag flag)
|
|
|
|
|
{
|
|
|
|
|
/* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
|
|
|
|
|
* return loop data from bmesh itself. */
|
|
|
|
|
const float (*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : NULL;
|
|
|
|
|
|
|
|
|
|
MVert *mv = dm->getVertArray(dm);
|
|
|
|
|
MLoop *ml = dm->getLoopArray(dm);
|
|
|
|
|
MPoly *mp = dm->getPolyArray(dm);
|
|
|
|
|
const int *v_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
|
|
|
|
|
const int *f_index = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
|
|
|
|
int p_idx, i;
|
|
|
|
|
|
|
|
|
|
for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) {
|
|
|
|
|
for (i = 0; i < mp->totloop; ++i, ++ml) {
|
|
|
|
|
const int v_idx = v_index ? v_index[ml->v] : ml->v;
|
|
|
|
|
const int f_idx = f_index ? f_index[p_idx] : p_idx;
|
|
|
|
|
const float *no = lnors ? *lnors++ : NULL;
|
|
|
|
|
if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
|
|
|
|
|
func(userData, v_idx, f_idx, mv[ml->v].co, no);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static void ccgDM_drawVerts(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVertIterator vi;
|
|
|
|
|
CCGEdgeIterator ei;
|
|
|
|
|
CCGFaceIterator fi;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
|
|
|
|
glBegin(GL_POINTS);
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
|
|
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
glVertex3fv(ccgSubSurf_getVertData(ss, v));
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
int x;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (x = 1; x < edgeSize - 1; x++)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2008-09-29 17:08:11 +00:00
|
|
|
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
glVertex3fv(ccgSubSurf_getFaceCenterData(f));
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++)
|
|
|
|
|
for (x = 1; x < gridSize - 1; x++)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++)
|
|
|
|
|
for (y = 1; y < gridSize - 1; y++)
|
|
|
|
|
for (x = 1; x < gridSize - 1; x++)
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2010-12-16 03:39:51 +00:00
|
|
|
|
|
|
|
|
static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
|
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
|
2010-12-16 03:39:51 +00:00
|
|
|
CCGFace **faces;
|
|
|
|
|
int totface;
|
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (totface) {
|
2010-12-16 03:39:51 +00:00
|
|
|
ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
|
|
|
|
|
ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
|
|
|
|
|
MEM_freeN(faces);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 19:33:54 +10:00
|
|
|
static void ccgDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2015-07-23 16:05:00 +02:00
|
|
|
GPUDrawObject *gdo;
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
/* TODO(sergey): We currently only support all edges drawing. */
|
2016-07-22 14:46:13 +02:00
|
|
|
if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) {
|
2015-07-24 17:11:50 +10:00
|
|
|
ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-12-16 03:39:51 +00:00
|
|
|
ccgdm_pbvh_update(ccgdm);
|
|
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
/* old debug feature for edges, unsupported for now */
|
|
|
|
|
#if 0
|
|
|
|
|
int useAging = 0;
|
2005-04-02 18:37:18 +00:00
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
if (!(G.f & G_BACKBUFSEL)) {
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
|
2011-07-11 09:05:10 +00:00
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
/* it needs some way to upload this to VBO now */
|
|
|
|
|
if (useAging) {
|
2012-04-22 00:20:58 +00:00
|
|
|
int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
|
|
|
|
|
glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
|
2005-03-31 16:54:47 +00:00
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2015-07-23 16:05:00 +02:00
|
|
|
#endif
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
GPU_edge_setup(dm);
|
|
|
|
|
gdo = dm->drawObject;
|
|
|
|
|
if (gdo->edges && gdo->points) {
|
|
|
|
|
if (drawAllEdges && drawLooseEdges) {
|
|
|
|
|
GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, (gdo->totedge - gdo->totinterior) * 2);
|
|
|
|
|
}
|
|
|
|
|
else if (drawAllEdges) {
|
|
|
|
|
GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
|
2015-07-25 12:46:08 +02:00
|
|
|
GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, gdo->tot_loose_edge_drawn * 2);
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
2005-03-31 16:54:47 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-12 11:42:35 +02:00
|
|
|
if (gdo->edges && ccgdm->drawInteriorEdges) {
|
2015-07-23 16:05:00 +02:00
|
|
|
GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->interior_offset * 2, gdo->totinterior * 2);
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2015-07-23 16:05:00 +02:00
|
|
|
GPU_buffers_unbind();
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
|
|
|
|
static void ccgDM_drawLooseEdges(DerivedMesh *dm)
|
|
|
|
|
{
|
2015-07-23 16:05:00 +02:00
|
|
|
int start;
|
|
|
|
|
int count;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
2015-07-23 16:05:00 +02:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2015-07-20 16:08:06 +02:00
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
/* TODO(sergey): Needs implementation. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
GPU_edge_setup(dm);
|
2012-05-10 20:33:09 +00:00
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
start = (dm->drawObject->loose_edge_offset * 2);
|
|
|
|
|
count = (dm->drawObject->interior_offset - dm->drawObject->loose_edge_offset) * 2;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
if (count) {
|
|
|
|
|
GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count);
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2015-07-23 16:05:00 +02:00
|
|
|
|
|
|
|
|
GPU_buffers_unbind();
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
|
|
|
|
|
{
|
|
|
|
|
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
|
|
|
|
|
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
|
|
|
|
|
|
|
|
|
|
no[0] = b_dY * a_cZ - b_dZ * a_cY;
|
|
|
|
|
no[1] = b_dZ * a_cX - b_dX * a_cZ;
|
|
|
|
|
no[2] = b_dX * a_cY - b_dY * a_cX;
|
|
|
|
|
|
|
|
|
|
normalize_v3(no);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-05-11 02:14:43 +00:00
|
|
|
static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
|
2007-08-28 08:53:36 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
|
|
|
|
|
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
|
2007-08-28 08:53:36 +00:00
|
|
|
float no[3];
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
no[0] = b_dY * a_cZ - b_dZ * a_cY;
|
|
|
|
|
no[1] = b_dZ * a_cX - b_dX * a_cZ;
|
|
|
|
|
no[2] = b_dX * a_cY - b_dY * a_cX;
|
2007-08-28 08:53:36 +00:00
|
|
|
|
2017-04-27 10:35:12 -04:00
|
|
|
normalize_v3(no); /* we no longer rely on GL_NORMALIZE */
|
|
|
|
|
|
2007-08-28 08:53:36 +00:00
|
|
|
glNormal3fv(no);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
/* Only used by non-editmesh types */
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_normal(
|
|
|
|
|
DerivedMesh *dm, short *varray)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2015-07-17 03:36:03 +10:00
|
|
|
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
|
2005-03-30 08:12:27 +00:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
2014-04-13 12:29:21 +02:00
|
|
|
int gridFaces = gridSize - 1;
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2011-11-21 14:59:26 +00:00
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
2015-07-14 16:48:23 +02:00
|
|
|
int shademodel;
|
|
|
|
|
int start = 0;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2015-11-13 21:57:00 +01:00
|
|
|
/* we are in sculpt mode, disable loop normals (since they won't get updated) */
|
|
|
|
|
if (ccgdm->pbvh)
|
|
|
|
|
lnors = NULL;
|
|
|
|
|
|
2015-09-02 15:39:17 +10:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2011-11-21 14:59:26 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2012-03-06 01:01:42 +00:00
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2015-07-17 03:36:03 +10:00
|
|
|
const float (*ln)[3] = NULL;
|
2007-08-28 08:53:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (faceFlags) {
|
2015-07-14 16:48:23 +02:00
|
|
|
shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
|
2007-08-28 08:53:36 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2015-07-14 16:48:23 +02:00
|
|
|
shademodel = GL_SMOOTH;
|
2007-08-28 08:53:36 +00:00
|
|
|
}
|
2014-03-29 11:40:26 +02:00
|
|
|
|
2014-04-13 12:29:21 +02:00
|
|
|
if (lnors) {
|
2015-07-17 03:36:03 +10:00
|
|
|
ln = lnors;
|
|
|
|
|
lnors += gridFaces * gridFaces * numVerts * 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2014-04-13 12:29:21 +02:00
|
|
|
if (ln) {
|
|
|
|
|
/* Can't use quad strips here... */
|
2015-07-14 16:48:23 +02:00
|
|
|
for (y = 0; y < gridFaces; y ++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x ++) {
|
2015-07-17 03:36:03 +10:00
|
|
|
normal_float_to_short_v3(&varray[start + 0], ln[0]);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 4], ln[3]);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 8], ln[2]);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 12], ln[1]);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
start += 16;
|
2015-07-15 14:32:11 +10:00
|
|
|
ln += 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (shademodel == GL_SMOOTH) {
|
2015-07-14 16:48:23 +02:00
|
|
|
for (y = 0; y < gridFaces; y ++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x ++) {
|
|
|
|
|
float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
|
|
|
|
|
float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
|
|
|
|
|
float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
normal_float_to_short_v3(&varray[start], a);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 4], b);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 8], c);
|
|
|
|
|
normal_float_to_short_v3(&varray[start + 12], d);
|
|
|
|
|
|
|
|
|
|
start += 16;
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
2005-04-03 21:52:10 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2015-07-14 16:48:23 +02:00
|
|
|
for (y = 0; y < gridFaces; y ++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x ++) {
|
2015-07-15 14:32:11 +10:00
|
|
|
float f_no[3];
|
|
|
|
|
short f_no_s[3];
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
|
|
|
|
|
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
|
|
|
|
|
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
2015-07-15 14:32:11 +10:00
|
|
|
ccgDM_NormalFast(a, b, c, d, f_no);
|
|
|
|
|
normal_float_to_short_v3(f_no_s, f_no);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-07-15 14:32:11 +10:00
|
|
|
copy_v3_v3_short(&varray[start], f_no_s);
|
|
|
|
|
copy_v3_v3_short(&varray[start + 4], f_no_s);
|
|
|
|
|
copy_v3_v3_short(&varray[start + 8], f_no_s);
|
|
|
|
|
copy_v3_v3_short(&varray[start + 12], f_no_s);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
start += 16;
|
2005-04-03 21:52:10 +00:00
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-07-25 22:02:15 +02:00
|
|
|
typedef struct FaceCount {
|
|
|
|
|
unsigned int i_visible;
|
|
|
|
|
unsigned int i_hidden;
|
|
|
|
|
unsigned int i_tri_visible;
|
|
|
|
|
unsigned int i_tri_hidden;
|
|
|
|
|
} FaceCount;
|
|
|
|
|
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
/* Only used by non-editmesh types */
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_triangles(
|
|
|
|
|
DerivedMesh *dm, unsigned int *varray,
|
|
|
|
|
const int *mat_orig_to_new)
|
2015-07-14 16:48:23 +02:00
|
|
|
{
|
2015-07-25 22:02:15 +02:00
|
|
|
GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
|
2015-09-17 20:40:51 +10:00
|
|
|
const int gpu_totmat = dm->drawObject->totmaterial;
|
|
|
|
|
const short dm_totmat = dm->totmat;
|
2015-07-14 16:48:23 +02:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
CCGKey key;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
|
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
2015-09-16 07:39:23 +10:00
|
|
|
short mat_nr = -1;
|
|
|
|
|
int start;
|
2015-07-14 16:48:23 +02:00
|
|
|
int totloops = 0;
|
2015-09-17 20:40:51 +10:00
|
|
|
FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2015-09-17 20:40:51 +10:00
|
|
|
for (i = 0; i < gpu_totmat; i++) {
|
2015-07-25 22:02:15 +02:00
|
|
|
fc[i].i_visible = 0;
|
|
|
|
|
fc[i].i_tri_visible = 0;
|
|
|
|
|
fc[i].i_hidden = gpumaterials[i].totpolys - 1;
|
|
|
|
|
fc[i].i_tri_hidden = gpumaterials[i].totelements - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2015-07-25 22:02:15 +02:00
|
|
|
bool is_hidden;
|
|
|
|
|
int mati;
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
if (faceFlags) {
|
2015-09-17 20:40:51 +10:00
|
|
|
mat_nr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
|
2015-07-25 22:02:15 +02:00
|
|
|
is_hidden = (faceFlags[index].flag & ME_HIDE) != 0;
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2015-09-16 07:39:23 +10:00
|
|
|
mat_nr = 0;
|
2015-07-25 22:02:15 +02:00
|
|
|
is_hidden = false;
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
2015-09-16 07:39:23 +10:00
|
|
|
mati = mat_orig_to_new[mat_nr];
|
2015-07-25 22:02:15 +02:00
|
|
|
gpumat = dm->drawObject->materials + mati;
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-07-25 22:02:15 +02:00
|
|
|
if (is_hidden) {
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
start = gpumat->start + fc[mati].i_tri_hidden;
|
|
|
|
|
|
2016-02-14 03:50:41 +01:00
|
|
|
varray[start--] = totloops;
|
2015-07-25 22:02:15 +02:00
|
|
|
varray[start--] = totloops + 2;
|
|
|
|
|
varray[start--] = totloops + 3;
|
|
|
|
|
|
|
|
|
|
varray[start--] = totloops;
|
|
|
|
|
varray[start--] = totloops + 1;
|
2016-02-14 03:50:41 +01:00
|
|
|
varray[start--] = totloops + 2;
|
2015-07-25 22:02:15 +02:00
|
|
|
|
|
|
|
|
fc[mati].i_tri_hidden -= 6;
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-07-25 22:02:15 +02:00
|
|
|
totloops += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
gpumat->polys[fc[mati].i_hidden--] = i;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
start = gpumat->start + fc[mati].i_tri_visible;
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-07-25 22:02:15 +02:00
|
|
|
varray[start++] = totloops + 3;
|
2016-02-14 20:24:36 +01:00
|
|
|
varray[start++] = totloops + 2;
|
2015-07-25 22:02:15 +02:00
|
|
|
varray[start++] = totloops;
|
2016-02-14 20:24:36 +01:00
|
|
|
|
2016-02-14 03:50:41 +01:00
|
|
|
varray[start++] = totloops + 2;
|
2016-02-14 20:24:36 +01:00
|
|
|
varray[start++] = totloops + 1;
|
|
|
|
|
varray[start++] = totloops;
|
2015-07-25 22:02:15 +02:00
|
|
|
|
|
|
|
|
fc[mati].i_tri_visible += 6;
|
|
|
|
|
|
|
|
|
|
totloops += 4;
|
|
|
|
|
}
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-07-25 22:02:15 +02:00
|
|
|
gpumat->polys[fc[mati].i_visible++] = i;
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-07-25 22:02:15 +02:00
|
|
|
|
|
|
|
|
/* set the visible polygons */
|
2015-09-17 20:40:51 +10:00
|
|
|
for (i = 0; i < gpu_totmat; i++) {
|
2015-07-25 22:02:15 +02:00
|
|
|
gpumaterials[i].totvisiblepolys = fc[i].i_visible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(fc);
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Only used by non-editmesh types */
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_vertex(
|
|
|
|
|
DerivedMesh *dm, void *varray_p)
|
2015-07-14 16:48:23 +02:00
|
|
|
{
|
2015-07-15 12:42:41 +10:00
|
|
|
float *varray = varray_p;
|
2015-07-14 16:48:23 +02:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
CCGKey key;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
2015-07-23 16:05:00 +02:00
|
|
|
int totedge = ccgSubSurf_getNumEdges(ss);
|
2015-07-14 16:48:23 +02:00
|
|
|
int start = 0;
|
2015-07-23 16:05:00 +02:00
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2015-09-01 19:56:23 +03:00
|
|
|
|
2015-09-02 15:39:17 +10:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
|
|
|
|
|
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
|
|
|
|
|
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
copy_v3_v3(&varray[start], a);
|
|
|
|
|
copy_v3_v3(&varray[start + 3], b);
|
|
|
|
|
copy_v3_v3(&varray[start + 6], c);
|
|
|
|
|
copy_v3_v3(&varray[start + 9], d);
|
|
|
|
|
|
|
|
|
|
start += 12;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-23 16:05:00 +02:00
|
|
|
|
|
|
|
|
/* upload loose points */
|
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
|
CCGEdge *e = ccgdm->edgeMap[i].edge;
|
|
|
|
|
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
|
|
|
|
|
|
|
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e)) {
|
|
|
|
|
int j = 0;
|
|
|
|
|
for (j = 0; j < edgeSize; j++) {
|
|
|
|
|
copy_v3_v3(&varray[start], CCG_elem_offset_co(&key, edgeData, j));
|
|
|
|
|
start += 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Only used by non-editmesh types */
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_color(
|
|
|
|
|
DerivedMesh *dm, unsigned char *varray,
|
|
|
|
|
const void *user_data)
|
2015-07-14 16:48:23 +02:00
|
|
|
{
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
CCGKey key;
|
2015-10-11 01:44:47 +02:00
|
|
|
const unsigned char *mloopcol = user_data;
|
2015-07-14 16:48:23 +02:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int start = 0;
|
|
|
|
|
int iface = 0;
|
|
|
|
|
|
|
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2017-09-30 19:20:04 +10:00
|
|
|
copy_v4_v4_uchar(&varray[start + 0], &mloopcol[iface * 16 + 0]);
|
|
|
|
|
copy_v4_v4_uchar(&varray[start + 4], &mloopcol[iface * 16 + 12]);
|
|
|
|
|
copy_v4_v4_uchar(&varray[start + 8], &mloopcol[iface * 16 + 8]);
|
|
|
|
|
copy_v4_v4_uchar(&varray[start + 12], &mloopcol[iface * 16 + 4]);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2017-09-30 19:20:04 +10:00
|
|
|
start += 16;
|
2015-07-14 16:48:23 +02:00
|
|
|
iface++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_uv(
|
|
|
|
|
DerivedMesh *dm, void *varray_p)
|
2015-07-14 16:48:23 +02:00
|
|
|
{
|
2015-07-15 12:42:41 +10:00
|
|
|
float *varray = varray_p;
|
2015-07-14 16:48:23 +02:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
CCGKey key;
|
2015-07-17 03:36:03 +10:00
|
|
|
MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
|
2015-07-14 16:48:23 +02:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int start = 0;
|
|
|
|
|
|
|
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2015-07-17 03:36:03 +10:00
|
|
|
copy_v2_v2(&varray[start + 0], mloopuv[0].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 2], mloopuv[3].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 4], mloopuv[2].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 6], mloopuv[1].uv);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
mloopuv += 4;
|
2015-07-14 16:48:23 +02:00
|
|
|
start += 8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 12:42:41 +10:00
|
|
|
static void ccgDM_buffer_copy_uv_texpaint(
|
|
|
|
|
DerivedMesh *dm, float *varray)
|
2015-07-14 16:48:23 +02:00
|
|
|
{
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
CCGKey key;
|
|
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int i, totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int start = 0;
|
|
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2015-09-17 20:40:51 +10:00
|
|
|
int dm_totmat = dm->totmat;
|
2015-07-17 03:36:03 +10:00
|
|
|
MLoopUV **mloopuv_base;
|
|
|
|
|
MLoopUV *stencil_base;
|
2015-07-14 16:48:23 +02:00
|
|
|
int stencil;
|
|
|
|
|
|
|
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
|
|
|
|
/* should have been checked for before, reassert */
|
2015-07-17 03:36:03 +10:00
|
|
|
BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
|
2015-09-17 20:40:51 +10:00
|
|
|
mloopuv_base = MEM_mallocN(dm_totmat * sizeof(*mloopuv_base), "texslots");
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-09-17 20:40:51 +10:00
|
|
|
for (i = 0; i < dm_totmat; i++) {
|
2015-07-17 04:26:17 +10:00
|
|
|
mloopuv_base[i] = DM_paint_uvlayer_active_get(dm, i);
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
|
|
|
|
|
stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
start = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
|
|
|
|
int matnr;
|
|
|
|
|
|
|
|
|
|
if (faceFlags) {
|
|
|
|
|
matnr = faceFlags[index].mat_nr;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
matnr = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2015-07-17 03:36:03 +10:00
|
|
|
/* divide by 4, gives us current loop-index */
|
|
|
|
|
unsigned int i_ml = start / 4;
|
|
|
|
|
copy_v2_v2(&varray[start + 0], mloopuv_base[matnr][i_ml + 0].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 2], stencil_base[i_ml + 0].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 4], mloopuv_base[matnr][i_ml + 3].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 6], stencil_base[i_ml + 3].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 8], mloopuv_base[matnr][i_ml + 2].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 10], stencil_base[i_ml + 2].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 14], stencil_base[i_ml + 1].uv);
|
2015-07-14 16:48:23 +02:00
|
|
|
start += 16;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
MEM_freeN(mloopuv_base);
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-18 23:45:51 +10:00
|
|
|
static void ccgDM_buffer_copy_uvedge(
|
|
|
|
|
DerivedMesh *dm, float *varray)
|
|
|
|
|
{
|
|
|
|
|
int i, totpoly;
|
|
|
|
|
int start;
|
|
|
|
|
const MLoopUV *mloopuv;
|
|
|
|
|
#ifndef USE_LOOP_LAYOUT_FAST
|
|
|
|
|
const MPoly *mpoly = dm->getPolyArray(dm);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totpoly = dm->getNumPolys(dm);
|
|
|
|
|
start = 0;
|
|
|
|
|
|
|
|
|
|
#ifndef USE_LOOP_LAYOUT_FAST
|
|
|
|
|
for (i = 0; i < totpoly; i++, mpoly++) {
|
|
|
|
|
for (j = 0; j < mpoly->totloop; j++) {
|
|
|
|
|
copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
|
|
|
|
|
start += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
for (i = 0; i < totpoly; i++) {
|
|
|
|
|
copy_v2_v2(&varray[start + 0], mloopuv[(i * 4) + 0].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 2], mloopuv[(i * 4) + 1].uv);
|
|
|
|
|
|
|
|
|
|
copy_v2_v2(&varray[start + 4], mloopuv[(i * 4) + 1].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 6], mloopuv[(i * 4) + 2].uv);
|
|
|
|
|
|
|
|
|
|
copy_v2_v2(&varray[start + 8], mloopuv[(i * 4) + 2].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 10], mloopuv[(i * 4) + 3].uv);
|
|
|
|
|
|
|
|
|
|
copy_v2_v2(&varray[start + 12], mloopuv[(i * 4) + 3].uv);
|
|
|
|
|
copy_v2_v2(&varray[start + 14], mloopuv[(i * 4) + 0].uv);
|
|
|
|
|
|
|
|
|
|
start += 16;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-23 16:05:00 +02:00
|
|
|
static void ccgDM_buffer_copy_edge(
|
|
|
|
|
DerivedMesh *dm, unsigned int *varray)
|
|
|
|
|
{
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2015-07-25 12:46:08 +02:00
|
|
|
/* getEdgeSuze returns num of verts, edges is one less */
|
|
|
|
|
int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss) - 1;
|
2015-07-23 16:05:00 +02:00
|
|
|
int totedge = ccgSubSurf_getNumEdges(ss);
|
|
|
|
|
int grid_face_side = ccgSubSurf_getGridSize(ss) - 1;
|
|
|
|
|
int totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
unsigned int index_start;
|
|
|
|
|
unsigned int tot_interior = 0;
|
|
|
|
|
unsigned int grid_tot_face = grid_face_side * grid_face_side;
|
|
|
|
|
|
2015-07-24 14:39:52 +02:00
|
|
|
unsigned int iloose, inorm, iloosehidden, inormhidden;
|
|
|
|
|
unsigned int tot_loose_hidden = 0, tot_loose = 0;
|
|
|
|
|
unsigned int tot_hidden = 0, tot = 0;
|
|
|
|
|
unsigned int iloosevert;
|
2015-07-23 16:05:00 +02:00
|
|
|
/* int tot_interior = 0; */
|
|
|
|
|
|
|
|
|
|
/* first, handle hidden/loose existing edges, then interior edges */
|
|
|
|
|
for (j = 0; j < totedge; j++) {
|
|
|
|
|
CCGEdge *e = ccgdm->edgeMap[j].edge;
|
|
|
|
|
|
|
|
|
|
if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
|
|
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose_hidden++;
|
|
|
|
|
else tot_hidden++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose++;
|
|
|
|
|
else tot++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inorm = 0;
|
2015-07-25 12:46:08 +02:00
|
|
|
inormhidden = tot * edgeSize;
|
|
|
|
|
iloose = (tot + tot_hidden) * edgeSize;
|
|
|
|
|
iloosehidden = (tot + tot_hidden + tot_loose) * edgeSize;
|
2015-07-24 14:39:52 +02:00
|
|
|
iloosevert = dm->drawObject->tot_loop_verts;
|
2015-07-23 16:05:00 +02:00
|
|
|
|
|
|
|
|
/* part one, handle all normal edges */
|
|
|
|
|
for (j = 0; j < totedge; j++) {
|
|
|
|
|
CCGFace *f;
|
2015-09-04 01:04:37 +02:00
|
|
|
int fhandle = 0;
|
|
|
|
|
int totvert = 0;
|
|
|
|
|
unsigned int S = 0;
|
2015-07-23 16:05:00 +02:00
|
|
|
CCGEdge *e = ccgdm->edgeMap[j].edge;
|
|
|
|
|
bool isloose = !ccgSubSurf_getEdgeNumFaces(e);
|
|
|
|
|
|
|
|
|
|
if (!isloose) {
|
|
|
|
|
CCGVert *v1, *v2;
|
|
|
|
|
CCGVert *ev1 = ccgSubSurf_getEdgeVert0(e);
|
|
|
|
|
CCGVert *ev2 = ccgSubSurf_getEdgeVert1(e);
|
|
|
|
|
|
|
|
|
|
f = ccgSubSurf_getEdgeFace(e, 0);
|
|
|
|
|
fhandle = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
|
|
|
|
totvert = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
/* find the index of vertices in the face */
|
|
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
|
v1 = ccgSubSurf_getFaceVert(f, i);
|
|
|
|
|
v2 = ccgSubSurf_getFaceVert(f, (i + 1) % totvert);
|
|
|
|
|
|
|
|
|
|
if ((ev1 == v1 && ev2 == v2) || (ev1 == v2 && ev2 == v1)) {
|
|
|
|
|
S = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
|
2015-07-25 22:32:55 +02:00
|
|
|
if (isloose) {
|
2015-07-25 12:46:08 +02:00
|
|
|
for (i = 0; i < edgeSize; i++) {
|
2015-07-23 16:05:00 +02:00
|
|
|
varray[iloosehidden * 2] = iloosevert;
|
|
|
|
|
varray[iloosehidden * 2 + 1] = iloosevert + 1;
|
|
|
|
|
iloosehidden++;
|
|
|
|
|
iloosevert++;
|
|
|
|
|
}
|
2015-07-24 14:39:52 +02:00
|
|
|
/* we are through with this loose edge and moving to the next, so increase by one */
|
|
|
|
|
iloosevert++;
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
index_start = ccgdm->faceMap[fhandle].startFace;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < grid_face_side; i++) {
|
2015-07-25 12:46:08 +02:00
|
|
|
varray[inormhidden * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
|
|
|
|
|
varray[inormhidden * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
|
|
|
|
|
varray[inormhidden * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
|
|
|
|
|
varray[inormhidden * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
|
|
|
|
|
inormhidden += 2;
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-07-25 22:32:55 +02:00
|
|
|
if (isloose) {
|
2015-07-25 12:46:08 +02:00
|
|
|
for (i = 0; i < edgeSize; i++) {
|
2015-07-23 16:05:00 +02:00
|
|
|
varray[iloose * 2] = iloosevert;
|
|
|
|
|
varray[iloose * 2 + 1] = iloosevert + 1;
|
|
|
|
|
iloose++;
|
|
|
|
|
iloosevert++;
|
|
|
|
|
}
|
2015-07-24 14:39:52 +02:00
|
|
|
/* we are through with this loose edge and moving to the next, so increase by one */
|
|
|
|
|
iloosevert++;
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
index_start = ccgdm->faceMap[fhandle].startFace;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < grid_face_side; i++) {
|
2015-07-25 12:46:08 +02:00
|
|
|
varray[inorm * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
|
|
|
|
|
varray[inorm * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
|
|
|
|
|
varray[inorm * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
|
|
|
|
|
varray[inorm * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
|
|
|
|
|
inorm += 2;
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* part two, handle interior edges */
|
|
|
|
|
inorm = totedge * grid_face_side * 2;
|
|
|
|
|
|
|
|
|
|
index_start = 0;
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
unsigned int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (x = 1; x < grid_face_side; x++) {
|
|
|
|
|
for (y = 0; y < grid_face_side; y++) {
|
|
|
|
|
unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
|
|
|
|
|
varray[inorm * 2] = tmp;
|
|
|
|
|
varray[inorm * 2 + 1] = tmp + 1;
|
|
|
|
|
inorm++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (x = 0; x < grid_face_side; x++) {
|
|
|
|
|
for (y = 0; y < grid_face_side; y++) {
|
|
|
|
|
unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
|
|
|
|
|
varray[inorm * 2] = tmp + 3;
|
|
|
|
|
varray[inorm * 2 + 1] = tmp;
|
|
|
|
|
inorm++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-23 23:21:19 +02:00
|
|
|
tot_interior += grid_face_side * (2 * grid_face_side - 1);
|
2015-07-23 16:05:00 +02:00
|
|
|
index_start += grid_tot_face;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-25 12:46:08 +02:00
|
|
|
dm->drawObject->tot_loose_edge_drawn = tot_loose * edgeSize;
|
|
|
|
|
dm->drawObject->loose_edge_offset = (tot + tot_hidden) * edgeSize;
|
|
|
|
|
dm->drawObject->tot_edge_drawn = tot * edgeSize;
|
2015-07-23 16:05:00 +02:00
|
|
|
|
2015-07-25 12:46:08 +02:00
|
|
|
dm->drawObject->interior_offset = totedge * edgeSize;
|
2015-07-23 16:05:00 +02:00
|
|
|
dm->drawObject->totinterior = tot_interior;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 11:43:23 +10:00
|
|
|
static void ccgDM_copy_gpu_data(
|
2015-07-15 12:42:41 +10:00
|
|
|
DerivedMesh *dm, int type, void *varray_p,
|
|
|
|
|
const int *mat_orig_to_new, const void *user_data)
|
|
|
|
|
{
|
|
|
|
|
/* 'varray_p' cast is redundant but include for self-documentation */
|
2015-07-15 11:43:23 +10:00
|
|
|
switch (type) {
|
2015-07-14 16:48:23 +02:00
|
|
|
case GPU_BUFFER_VERTEX:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_vertex(dm, (float *)varray_p);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case GPU_BUFFER_NORMAL:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_normal(dm, (short *)varray_p);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case GPU_BUFFER_UV:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_uv(dm, (float *)varray_p);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case GPU_BUFFER_UV_TEXPAINT:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_uv_texpaint(dm, (float *)varray_p);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case GPU_BUFFER_COLOR:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_color(dm, (unsigned char *)varray_p, user_data);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
2015-07-18 23:45:51 +10:00
|
|
|
case GPU_BUFFER_UVEDGE:
|
|
|
|
|
ccgDM_buffer_copy_uvedge(dm, (float *)varray_p);
|
|
|
|
|
break;
|
2015-07-23 16:05:00 +02:00
|
|
|
case GPU_BUFFER_EDGE:
|
|
|
|
|
ccgDM_buffer_copy_edge(dm, (unsigned int *)varray_p);
|
|
|
|
|
break;
|
2015-07-14 16:48:23 +02:00
|
|
|
case GPU_BUFFER_TRIANGLES:
|
2015-07-15 12:42:41 +10:00
|
|
|
ccgDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new);
|
2015-07-14 16:48:23 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 11:43:23 +10:00
|
|
|
static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
|
|
|
|
|
{
|
2015-07-14 16:48:23 +02:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
|
|
|
|
GPUDrawObject *gdo;
|
|
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2015-07-25 12:46:08 +02:00
|
|
|
int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
|
2015-09-17 20:40:51 +10:00
|
|
|
const short dm_totmat = (faceFlags) ? dm->totmat : 1;
|
2015-07-25 13:17:37 +02:00
|
|
|
GPUBufferMaterial *matinfo;
|
|
|
|
|
int i;
|
2015-07-23 16:05:00 +02:00
|
|
|
unsigned int tot_internal_edges = 0;
|
2015-07-25 12:46:08 +02:00
|
|
|
int edgeVerts = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
int edgeSize = edgeVerts - 1;
|
2015-07-23 16:05:00 +02:00
|
|
|
|
|
|
|
|
int totedge = ccgSubSurf_getNumEdges(ss);
|
|
|
|
|
int totface = ccgSubSurf_getNumFaces(ss);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
/* object contains at least one material (default included) so zero means uninitialized dm */
|
2015-09-17 20:40:51 +10:00
|
|
|
BLI_assert(dm_totmat != 0);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-09-17 20:40:51 +10:00
|
|
|
matinfo = MEM_callocN(sizeof(*matinfo) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
if (faceFlags) {
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2015-09-17 20:40:51 +10:00
|
|
|
const short new_matnr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
|
2015-07-25 13:17:37 +02:00
|
|
|
matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6;
|
|
|
|
|
matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4;
|
|
|
|
|
matinfo[new_matnr].totpolys++;
|
2015-07-23 23:21:19 +02:00
|
|
|
tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (i = 0; i < totface; i++) {
|
2015-07-23 16:05:00 +02:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2015-07-25 13:17:37 +02:00
|
|
|
matinfo[0].totelements += numVerts * gridFaces * gridFaces * 6;
|
|
|
|
|
matinfo[0].totloops += numVerts * gridFaces * gridFaces * 4;
|
|
|
|
|
matinfo[0].totpolys++;
|
2015-07-23 23:21:19 +02:00
|
|
|
tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create the GPUDrawObject */
|
|
|
|
|
gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
|
2015-07-24 12:24:05 +02:00
|
|
|
gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */
|
2015-07-25 12:46:08 +02:00
|
|
|
gdo->totedge = (totedge * edgeSize + tot_internal_edges);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
2015-09-17 20:40:51 +10:00
|
|
|
GPU_buffer_material_finalize(gdo, matinfo, dm_totmat);
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
/* store total number of points used for triangles */
|
2015-07-25 13:17:37 +02:00
|
|
|
gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6;
|
2015-07-23 16:05:00 +02:00
|
|
|
gdo->tot_loop_verts = ccgSubSurf_getNumFinalFaces(ss) * 4;
|
|
|
|
|
|
|
|
|
|
/* finally, count loose points */
|
|
|
|
|
for (i = 0; i < totedge; i++) {
|
|
|
|
|
CCGEdge *e = ccgdm->edgeMap[i].edge;
|
|
|
|
|
|
|
|
|
|
if (!ccgSubSurf_getEdgeNumFaces(e))
|
2015-07-25 12:46:08 +02:00
|
|
|
gdo->tot_loose_point += edgeVerts;
|
2015-07-23 16:05:00 +02:00
|
|
|
}
|
2015-07-14 16:48:23 +02:00
|
|
|
|
|
|
|
|
return gdo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Only used by non-editmesh types */
|
|
|
|
|
static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
|
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
|
2015-07-16 16:22:28 +02:00
|
|
|
ccgdm_pbvh_update(ccgdm);
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
if (ccgdm->pbvh && ccgdm->multires.mmd) {
|
|
|
|
|
if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
|
|
|
|
|
BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
|
|
|
|
|
setMaterial, false, fast);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2015-08-25 15:05:28 +02:00
|
|
|
const DMFlagMat *faceFlags = ccgdm->faceFlags;
|
|
|
|
|
const int level = ccgSubSurf_getSubdivisionLevels(ss);
|
|
|
|
|
const int face_side = 1 << level;
|
|
|
|
|
const int grid_side = 1 << (level - 1);
|
|
|
|
|
const int face_patches = face_side * face_side;
|
|
|
|
|
const int grid_patches = grid_side * grid_side;
|
|
|
|
|
const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
|
|
|
|
|
int i, current_patch = 0;
|
|
|
|
|
int mat_nr = -1;
|
|
|
|
|
bool draw_smooth = false;
|
|
|
|
|
int start_draw_patch = -1, num_draw_patches = 0;
|
2016-07-22 14:46:13 +02:00
|
|
|
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL, -1) == false)) {
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2015-08-25 15:05:28 +02:00
|
|
|
if (setMaterial == NULL) {
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
-1,
|
|
|
|
|
-1);
|
|
|
|
|
return;
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
2015-08-25 15:05:28 +02:00
|
|
|
for (i = 0; i < num_base_faces; ++i) {
|
|
|
|
|
const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
|
|
|
|
|
const int num_patches = (num_face_verts == 4) ? face_patches
|
|
|
|
|
: num_face_verts * grid_patches;
|
|
|
|
|
int new_matnr;
|
|
|
|
|
bool new_draw_smooth;
|
|
|
|
|
if (faceFlags) {
|
|
|
|
|
new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
|
|
|
|
|
new_matnr = (faceFlags[i].mat_nr + 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
new_draw_smooth = true;
|
|
|
|
|
new_matnr = 1;
|
|
|
|
|
}
|
|
|
|
|
if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
|
|
|
|
|
if (num_draw_patches != 0) {
|
2015-08-25 15:22:26 +02:00
|
|
|
bool do_draw = setMaterial(mat_nr, NULL);
|
2015-08-25 15:05:28 +02:00
|
|
|
if (do_draw) {
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
start_draw_patch = current_patch;
|
|
|
|
|
num_draw_patches = num_patches;
|
|
|
|
|
mat_nr = new_matnr;
|
|
|
|
|
draw_smooth = new_draw_smooth;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
num_draw_patches += num_patches;
|
|
|
|
|
}
|
|
|
|
|
current_patch += num_patches;
|
|
|
|
|
}
|
|
|
|
|
if (num_draw_patches != 0) {
|
|
|
|
|
bool do_draw = setMaterial(mat_nr, NULL);
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
|
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
2016-07-25 18:30:48 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-07-14 16:48:23 +02:00
|
|
|
GPU_vertex_setup(dm);
|
|
|
|
|
GPU_normal_setup(dm);
|
|
|
|
|
GPU_triangle_setup(dm);
|
|
|
|
|
for (a = 0; a < dm->drawObject->totmaterial; a++) {
|
|
|
|
|
if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
|
|
|
|
|
GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start,
|
|
|
|
|
dm->drawObject->materials[a].totelements);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-20 12:12:28 +02:00
|
|
|
GPU_buffers_unbind();
|
2015-07-14 16:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
typedef struct {
|
|
|
|
|
DMVertexAttribs attribs;
|
|
|
|
|
int numdata;
|
|
|
|
|
|
|
|
|
|
GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
|
|
|
|
|
} GPUMaterialConv;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
/* Only used by non-editmesh types */
|
2012-02-05 08:18:34 +00:00
|
|
|
static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
2012-04-22 00:20:58 +00:00
|
|
|
DMSetMaterial setMaterial,
|
|
|
|
|
DMSetDrawOptions setDrawOptions,
|
|
|
|
|
void *userData)
|
2011-12-01 12:12:39 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
GPUVertexAttribs gattribs;
|
2015-11-23 11:27:02 +11:00
|
|
|
int a, b;
|
|
|
|
|
const DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2015-10-15 22:24:40 +03:00
|
|
|
unsigned char *varray;
|
|
|
|
|
size_t max_element_size = 0;
|
|
|
|
|
int tot_loops = 0;
|
|
|
|
|
int totpoly = ccgSubSurf_getNumFaces(ss);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
2015-08-25 15:22:26 +02:00
|
|
|
const int level = ccgSubSurf_getSubdivisionLevels(ss);
|
|
|
|
|
const int face_side = 1 << level;
|
|
|
|
|
const int grid_side = 1 << (level - 1);
|
|
|
|
|
const int face_patches = face_side * face_side;
|
|
|
|
|
const int grid_patches = grid_side * grid_side;
|
|
|
|
|
const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
|
|
|
|
|
int i, current_patch = 0;
|
|
|
|
|
int mat_nr = -1;
|
|
|
|
|
bool draw_smooth = false;
|
|
|
|
|
int start_draw_patch = -1, num_draw_patches = 0;
|
2015-07-20 16:08:06 +02:00
|
|
|
GPU_draw_update_fvar_offset(dm);
|
2016-07-22 14:46:13 +02:00
|
|
|
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false, -1) == false)) {
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2015-08-25 15:22:26 +02:00
|
|
|
for (i = 0; i < num_base_faces; ++i) {
|
|
|
|
|
const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
|
|
|
|
|
const int num_patches = (num_face_verts == 4) ? face_patches
|
|
|
|
|
: num_face_verts * grid_patches;
|
|
|
|
|
int new_matnr;
|
|
|
|
|
bool new_draw_smooth;
|
2015-11-23 11:27:02 +11:00
|
|
|
|
2015-08-25 15:22:26 +02:00
|
|
|
if (faceFlags) {
|
|
|
|
|
new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
|
|
|
|
|
new_matnr = (faceFlags[i].mat_nr + 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
new_draw_smooth = true;
|
|
|
|
|
new_matnr = 1;
|
|
|
|
|
}
|
|
|
|
|
if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
|
|
|
|
|
if (num_draw_patches != 0) {
|
|
|
|
|
bool do_draw = setMaterial(mat_nr, &gattribs);
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
start_draw_patch = current_patch;
|
|
|
|
|
num_draw_patches = num_patches;
|
|
|
|
|
mat_nr = new_matnr;
|
|
|
|
|
draw_smooth = new_draw_smooth;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
num_draw_patches += num_patches;
|
|
|
|
|
}
|
|
|
|
|
current_patch += num_patches;
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
2015-08-25 15:22:26 +02:00
|
|
|
if (num_draw_patches != 0) {
|
|
|
|
|
bool do_draw = setMaterial(mat_nr, &gattribs);
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
|
|
|
|
}
|
2015-08-05 18:29:43 +02:00
|
|
|
}
|
2016-07-25 18:30:48 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm_pbvh_update(ccgdm);
|
2010-02-07 13:22:46 +00:00
|
|
|
|
2015-11-26 11:08:25 +11:00
|
|
|
if (setDrawOptions != NULL) {
|
2015-10-15 22:24:40 +03:00
|
|
|
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
|
|
|
|
|
DMVertexAttribs attribs = {{{NULL}}};
|
|
|
|
|
int i;
|
|
|
|
|
int matnr = -1;
|
2015-11-23 11:27:02 +11:00
|
|
|
int do_draw = 0;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2016-09-05 13:30:57 -04:00
|
|
|
#define PASSATTRIB(dx, dy, vert) { \
|
|
|
|
|
if (attribs.totorco) \
|
|
|
|
|
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
|
|
|
|
else \
|
|
|
|
|
index = 0; \
|
|
|
|
|
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
|
|
|
|
DM_draw_attrib_vertex_uniforms(&attribs); \
|
2012-05-17 07:59:25 +00:00
|
|
|
} (void)0
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
totpoly = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
for (a = 0, i = 0; i < totpoly; i++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
|
|
|
|
const float (*ln)[3] = NULL;
|
|
|
|
|
int S, x, y, drawSmooth;
|
|
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
|
|
|
|
int origIndex = ccgDM_getFaceMapIndex(ss, f);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2015-11-23 11:27:02 +11:00
|
|
|
int new_matnr;
|
2014-04-13 12:29:21 +02:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
if (faceFlags) {
|
|
|
|
|
drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
|
|
|
|
|
new_matnr = faceFlags[index].mat_nr + 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
drawSmooth = 1;
|
|
|
|
|
new_matnr = 1;
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
if (lnors) {
|
|
|
|
|
ln = lnors;
|
|
|
|
|
lnors += (gridFaces * gridFaces * numVerts) * 4;
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
if (new_matnr != matnr) {
|
|
|
|
|
do_draw = setMaterial(matnr = new_matnr, &gattribs);
|
|
|
|
|
if (do_draw)
|
|
|
|
|
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
|
|
|
|
|
(setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
|
|
|
|
|
{
|
|
|
|
|
a += gridFaces * gridFaces * numVerts;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-04-13 12:29:21 +02:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
|
|
|
|
CCGElem *vda, *vdb;
|
|
|
|
|
|
|
|
|
|
if (ln) {
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
|
|
|
|
|
float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
|
|
|
|
|
float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
|
|
|
|
glNormal3fv(ln[1]);
|
|
|
|
|
glVertex3fv(dco);
|
|
|
|
|
PASSATTRIB(1, 1, 2);
|
|
|
|
|
glNormal3fv(ln[2]);
|
|
|
|
|
glVertex3fv(cco);
|
|
|
|
|
PASSATTRIB(1, 0, 3);
|
|
|
|
|
glNormal3fv(ln[3]);
|
|
|
|
|
glVertex3fv(bco);
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
|
|
|
|
glNormal3fv(ln[0]);
|
|
|
|
|
glVertex3fv(aco);
|
|
|
|
|
|
|
|
|
|
ln += 4;
|
|
|
|
|
a++;
|
|
|
|
|
}
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
glEnd();
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
else if (drawSmooth) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
|
|
|
|
|
vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
|
|
|
|
glNormal3fv(CCG_elem_no(&key, vda));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vda));
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
|
|
|
|
glNormal3fv(CCG_elem_no(&key, vdb));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vdb));
|
|
|
|
|
|
|
|
|
|
if (x != gridFaces - 1)
|
|
|
|
|
a++;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
|
|
|
|
|
vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
2015-10-15 22:24:40 +03:00
|
|
|
|
|
|
|
|
PASSATTRIB(0, 0, 3);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vda));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vda));
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
PASSATTRIB(0, 1, 2);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vdb));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vdb));
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
|
|
a++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
|
|
|
|
|
float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
|
|
|
|
|
float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
ccgDM_glNormalFast(aco, bco, cco, dco);
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
|
|
|
|
glVertex3fv(dco);
|
|
|
|
|
PASSATTRIB(1, 1, 2);
|
|
|
|
|
glVertex3fv(cco);
|
|
|
|
|
PASSATTRIB(1, 0, 3);
|
|
|
|
|
glVertex3fv(bco);
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
|
|
|
|
glVertex3fv(aco);
|
|
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
a++;
|
2015-10-15 22:24:40 +03:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2016-08-19 23:04:43 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2015-10-15 22:24:40 +03:00
|
|
|
#undef PASSATTRIB
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPUMaterialConv *matconv;
|
|
|
|
|
size_t offset;
|
|
|
|
|
int *mat_orig_to_new;
|
|
|
|
|
int tot_active_mat;
|
|
|
|
|
GPUBuffer *buffer = NULL;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
GPU_vertex_setup(dm);
|
|
|
|
|
GPU_normal_setup(dm);
|
|
|
|
|
GPU_triangle_setup(dm);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
tot_active_mat = dm->drawObject->totmaterial;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
|
|
|
|
|
"cdDM_drawMappedFacesGLSL.matconv");
|
|
|
|
|
mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
|
|
|
|
|
"cdDM_drawMappedFacesGLSL.mat_orig_to_new");
|
|
|
|
|
|
|
|
|
|
/* part one, check what attributes are needed per material */
|
|
|
|
|
for (a = 0; a < tot_active_mat; a++) {
|
2015-11-23 11:27:02 +11:00
|
|
|
int new_matnr;
|
|
|
|
|
int do_draw;
|
|
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
new_matnr = dm->drawObject->materials[a].mat_nr;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
/* map from original material index to new
|
|
|
|
|
* GPUBufferMaterial index */
|
|
|
|
|
mat_orig_to_new[new_matnr] = a;
|
|
|
|
|
do_draw = setMaterial(new_matnr + 1, &gattribs);
|
|
|
|
|
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
int numdata = 0;
|
|
|
|
|
DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
|
|
|
|
|
|
|
|
|
|
if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
|
|
|
|
|
matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
|
2016-05-31 14:39:49 +02:00
|
|
|
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
|
2015-10-15 22:24:40 +03:00
|
|
|
matconv[a].datatypes[numdata].size = 3;
|
|
|
|
|
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
|
|
|
|
numdata++;
|
|
|
|
|
}
|
|
|
|
|
for (b = 0; b < matconv[a].attribs.tottface; b++) {
|
|
|
|
|
if (matconv[a].attribs.tface[b].array) {
|
|
|
|
|
matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
|
2016-05-31 14:39:49 +02:00
|
|
|
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
|
2015-10-15 22:24:40 +03:00
|
|
|
matconv[a].datatypes[numdata].size = 2;
|
|
|
|
|
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
|
|
|
|
numdata++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (b = 0; b < matconv[a].attribs.totmcol; b++) {
|
|
|
|
|
if (matconv[a].attribs.mcol[b].array) {
|
|
|
|
|
matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
|
2016-05-31 14:39:49 +02:00
|
|
|
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
|
2015-10-15 22:24:40 +03:00
|
|
|
matconv[a].datatypes[numdata].size = 4;
|
|
|
|
|
matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
|
|
|
|
|
numdata++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-26 18:43:02 +10:00
|
|
|
for (b = 0; b < matconv[a].attribs.tottang; b++) {
|
|
|
|
|
if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) {
|
|
|
|
|
matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
|
2016-05-31 14:39:49 +02:00
|
|
|
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
|
2016-04-26 18:43:02 +10:00
|
|
|
matconv[a].datatypes[numdata].size = 4;
|
|
|
|
|
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
|
|
|
|
numdata++;
|
|
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
}
|
|
|
|
|
if (numdata != 0) {
|
|
|
|
|
matconv[a].numdata = numdata;
|
|
|
|
|
max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* part two, generate and fill the arrays with the data */
|
|
|
|
|
if (max_element_size > 0) {
|
2015-11-22 19:46:31 +01:00
|
|
|
buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts);
|
2015-10-15 22:24:40 +03:00
|
|
|
|
|
|
|
|
varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY);
|
|
|
|
|
if (varray == NULL) {
|
|
|
|
|
GPU_buffers_unbind();
|
|
|
|
|
GPU_buffer_free(buffer);
|
|
|
|
|
MEM_freeN(mat_orig_to_new);
|
|
|
|
|
MEM_freeN(matconv);
|
|
|
|
|
fprintf(stderr, "Out of memory, can't draw object\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (a = 0; a < totpoly; a++) {
|
|
|
|
|
CCGFace *f = ccgdm->faceMap[a].face;
|
2015-11-23 11:27:02 +11:00
|
|
|
int orig_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2015-10-15 22:24:40 +03:00
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (faceFlags) {
|
2015-11-23 11:27:02 +11:00
|
|
|
i = mat_orig_to_new[faceFlags[orig_index].mat_nr];
|
2015-10-15 22:24:40 +03:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
i = mat_orig_to_new[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (matconv[i].numdata != 0) {
|
|
|
|
|
for (S = 0; S < numVerts; S++) {
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
|
|
|
|
|
offset = tot_loops * max_element_size;
|
|
|
|
|
|
|
|
|
|
if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
index = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize);
|
|
|
|
|
copy_v3_v3((float *)&varray[offset],
|
|
|
|
|
(float *)matconv[i].attribs.orco.array[index]);
|
|
|
|
|
index = getFaceIndex(ss, f, S, x + 1, y, edgeSize, gridSize);
|
|
|
|
|
copy_v3_v3((float *)&varray[offset + max_element_size],
|
|
|
|
|
(float *)matconv[i].attribs.orco.array[index]);
|
|
|
|
|
index = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
|
|
|
|
|
copy_v3_v3((float *)&varray[offset + 2 * max_element_size],
|
|
|
|
|
(float *)matconv[i].attribs.orco.array[index]);
|
|
|
|
|
index = getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize);
|
|
|
|
|
copy_v3_v3((float *)&varray[offset + 3 * max_element_size],
|
|
|
|
|
(float *)matconv[i].attribs.orco.array[index]);
|
|
|
|
|
|
|
|
|
|
offset += sizeof(float) * 3;
|
|
|
|
|
}
|
|
|
|
|
for (b = 0; b < matconv[i].attribs.tottface; b++) {
|
|
|
|
|
if (matconv[i].attribs.tface[b].array) {
|
|
|
|
|
const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array + tot_loops;
|
|
|
|
|
|
|
|
|
|
copy_v2_v2((float *)&varray[offset], mloopuv[0].uv);
|
|
|
|
|
copy_v2_v2((float *)&varray[offset + max_element_size], mloopuv[3].uv);
|
|
|
|
|
copy_v2_v2((float *)&varray[offset + 2 * max_element_size], mloopuv[2].uv);
|
|
|
|
|
copy_v2_v2((float *)&varray[offset + 3 * max_element_size], mloopuv[1].uv);
|
|
|
|
|
|
|
|
|
|
offset += sizeof(float) * 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (b = 0; b < matconv[i].attribs.totmcol; b++) {
|
|
|
|
|
if (matconv[i].attribs.mcol[b].array) {
|
|
|
|
|
const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array + tot_loops;
|
|
|
|
|
|
|
|
|
|
copy_v4_v4_uchar(&varray[offset], &mloopcol[0].r);
|
|
|
|
|
copy_v4_v4_uchar(&varray[offset + max_element_size], &mloopcol[3].r);
|
|
|
|
|
copy_v4_v4_uchar(&varray[offset + 2 * max_element_size], &mloopcol[2].r);
|
|
|
|
|
copy_v4_v4_uchar(&varray[offset + 3 * max_element_size], &mloopcol[1].r);
|
|
|
|
|
|
|
|
|
|
offset += sizeof(unsigned char) * 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-26 18:43:02 +10:00
|
|
|
for (b = 0; b < matconv[i].attribs.tottang; b++) {
|
|
|
|
|
if (matconv[i].attribs.tottang && matconv[i].attribs.tang[b].array) {
|
|
|
|
|
const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang[b].array + tot_loops;
|
2015-10-15 22:24:40 +03:00
|
|
|
|
2016-04-26 18:43:02 +10:00
|
|
|
copy_v4_v4((float *)&varray[offset], looptang[0]);
|
|
|
|
|
copy_v4_v4((float *)&varray[offset + max_element_size], looptang[3]);
|
|
|
|
|
copy_v4_v4((float *)&varray[offset + 2 * max_element_size], looptang[2]);
|
|
|
|
|
copy_v4_v4((float *)&varray[offset + 3 * max_element_size], looptang[1]);
|
2015-10-15 22:24:40 +03:00
|
|
|
|
2016-04-26 18:43:02 +10:00
|
|
|
offset += sizeof(float) * 4;
|
|
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tot_loops += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
else {
|
|
|
|
|
tot_loops += 4 * numVerts * gridFaces * gridFaces;
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2015-10-15 22:24:40 +03:00
|
|
|
|
|
|
|
|
for (a = 0; a < tot_active_mat; a++) {
|
2015-11-23 11:27:02 +11:00
|
|
|
int new_matnr;
|
|
|
|
|
int do_draw;
|
|
|
|
|
|
2015-10-15 22:24:40 +03:00
|
|
|
new_matnr = dm->drawObject->materials[a].mat_nr;
|
|
|
|
|
|
|
|
|
|
do_draw = setMaterial(new_matnr + 1, &gattribs);
|
|
|
|
|
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
if (matconv[a].numdata) {
|
|
|
|
|
GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size);
|
|
|
|
|
}
|
|
|
|
|
GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES,
|
|
|
|
|
dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
|
|
|
|
|
if (matconv[a].numdata) {
|
|
|
|
|
GPU_interleaved_attrib_unbind();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPU_buffers_unbind();
|
|
|
|
|
if (buffer)
|
|
|
|
|
GPU_buffer_free(buffer);
|
|
|
|
|
|
|
|
|
|
MEM_freeN(mat_orig_to_new);
|
|
|
|
|
MEM_freeN(matconv);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-07 04:41:14 +00:00
|
|
|
static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
/* Only used by non-editmesh types */
|
2012-05-13 11:05:52 +00:00
|
|
|
static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
|
2014-04-17 19:33:54 +10:00
|
|
|
void (*setMaterial)(void *userData, int matnr, void *attribs),
|
2013-07-19 10:40:52 +00:00
|
|
|
bool (*setFace)(void *userData, int index), void *userData)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2011-11-08 13:07:16 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2011-11-08 13:07:16 +00:00
|
|
|
GPUVertexAttribs gattribs;
|
2012-04-22 00:20:58 +00:00
|
|
|
DMVertexAttribs attribs = {{{NULL}}};
|
2011-11-08 13:07:16 +00:00
|
|
|
int gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
int gridFaces = gridSize - 1;
|
|
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2015-08-20 09:20:41 +10:00
|
|
|
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
|
2015-11-23 11:27:02 +11:00
|
|
|
int a, i, numVerts, matnr, totface;
|
2011-11-08 13:07:16 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
2016-09-07 09:47:35 +02:00
|
|
|
const int level = ccgSubSurf_getSubdivisionLevels(ss);
|
|
|
|
|
const int face_side = 1 << level;
|
|
|
|
|
const int grid_side = 1 << (level - 1);
|
|
|
|
|
const int face_patches = face_side * face_side;
|
|
|
|
|
const int grid_patches = grid_side * grid_side;
|
|
|
|
|
const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
|
|
|
|
|
int current_patch = 0;
|
|
|
|
|
int mat_nr = -1;
|
|
|
|
|
bool draw_smooth = false;
|
|
|
|
|
int start_draw_patch = -1, num_draw_patches = 0;
|
2015-08-25 13:16:24 +02:00
|
|
|
GPU_draw_update_fvar_offset(dm);
|
2016-07-22 14:46:13 +02:00
|
|
|
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) {
|
2015-08-25 13:16:24 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2016-09-07 09:47:35 +02:00
|
|
|
for (i = 0; i < num_base_faces; ++i) {
|
|
|
|
|
const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
|
|
|
|
|
const int num_patches = (num_face_verts == 4) ? face_patches
|
|
|
|
|
: num_face_verts * grid_patches;
|
|
|
|
|
int new_matnr;
|
|
|
|
|
bool new_draw_smooth;
|
|
|
|
|
|
|
|
|
|
if (faceFlags) {
|
|
|
|
|
new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
|
|
|
|
|
new_matnr = (faceFlags[i].mat_nr + 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
new_draw_smooth = true;
|
|
|
|
|
new_matnr = 1;
|
|
|
|
|
}
|
|
|
|
|
if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
|
|
|
|
|
if (num_draw_patches != 0) {
|
|
|
|
|
setMaterial(userData, mat_nr, &gattribs);
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
|
|
|
|
}
|
|
|
|
|
start_draw_patch = current_patch;
|
|
|
|
|
num_draw_patches = num_patches;
|
|
|
|
|
mat_nr = new_matnr;
|
|
|
|
|
draw_smooth = new_draw_smooth;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
num_draw_patches += num_patches;
|
|
|
|
|
}
|
|
|
|
|
current_patch += num_patches;
|
2015-08-25 13:16:24 +02:00
|
|
|
}
|
2016-09-07 09:47:35 +02:00
|
|
|
if (num_draw_patches != 0) {
|
|
|
|
|
setMaterial(userData, mat_nr, &gattribs);
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss,
|
|
|
|
|
true,
|
|
|
|
|
start_draw_patch,
|
|
|
|
|
num_draw_patches);
|
2015-08-25 13:16:24 +02:00
|
|
|
}
|
2016-07-25 18:30:48 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
2011-11-08 13:07:16 +00:00
|
|
|
ccgdm_pbvh_update(ccgdm);
|
|
|
|
|
|
|
|
|
|
matnr = -1;
|
|
|
|
|
|
2016-09-05 13:30:57 -04:00
|
|
|
#define PASSATTRIB(dx, dy, vert) { \
|
|
|
|
|
if (attribs.totorco) \
|
|
|
|
|
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
|
|
|
|
else \
|
|
|
|
|
index = 0; \
|
|
|
|
|
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
|
|
|
|
DM_draw_attrib_vertex_uniforms(&attribs); \
|
2012-05-17 07:59:25 +00:00
|
|
|
} (void)0
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a = 0, i = 0; i < totface; i++) {
|
2011-11-08 13:07:16 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
2015-08-20 09:20:41 +10:00
|
|
|
const float (*ln)[3] = NULL;
|
2011-11-08 13:07:16 +00:00
|
|
|
int S, x, y, drawSmooth;
|
2012-03-06 01:01:42 +00:00
|
|
|
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2011-11-08 13:07:16 +00:00
|
|
|
int origIndex = ccgDM_getFaceMapIndex(ss, f);
|
2015-11-23 11:27:02 +11:00
|
|
|
int new_matnr;
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
/* get flags */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (faceFlags) {
|
2014-04-13 12:29:21 +02:00
|
|
|
drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
|
2012-04-22 00:20:58 +00:00
|
|
|
new_matnr = faceFlags[index].mat_nr + 1;
|
2011-11-08 13:07:16 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
drawSmooth = 1;
|
2012-04-22 00:20:58 +00:00
|
|
|
new_matnr = 1;
|
2011-11-08 13:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-13 12:29:21 +02:00
|
|
|
if (lnors) {
|
|
|
|
|
ln = lnors;
|
2015-08-20 09:20:41 +10:00
|
|
|
lnors += (gridFaces * gridFaces * numVerts) * 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-08 13:07:16 +00:00
|
|
|
/* material */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (new_matnr != matnr) {
|
2011-11-08 13:07:16 +00:00
|
|
|
setMaterial(userData, matnr = new_matnr, &gattribs);
|
|
|
|
|
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* face hiding */
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((setFace && (origIndex != ORIGINDEX_NONE) && !setFace(userData, origIndex))) {
|
2012-04-22 00:20:58 +00:00
|
|
|
a += gridFaces * gridFaces * numVerts;
|
2011-11-08 13:07:16 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* draw face*/
|
2012-05-11 08:05:47 +00:00
|
|
|
glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
|
2012-04-22 00:20:58 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
|
|
|
|
CCGElem *vda, *vdb;
|
2011-11-08 13:07:16 +00:00
|
|
|
|
2014-04-13 12:29:21 +02:00
|
|
|
if (ln) {
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
|
|
|
|
|
float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
|
|
|
|
|
float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[1]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(dco);
|
|
|
|
|
PASSATTRIB(1, 1, 2);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[2]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(cco);
|
|
|
|
|
PASSATTRIB(1, 0, 3);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[3]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(bco);
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[0]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(aco);
|
|
|
|
|
|
2015-08-20 09:20:41 +10:00
|
|
|
ln += 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
a++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
else if (drawSmooth) {
|
2012-04-22 00:20:58 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
2011-11-08 13:07:16 +00:00
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-04-22 00:20:58 +00:00
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
vda = CCG_grid_elem(&key, faceGridData, x, y);
|
|
|
|
|
vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vda));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vda));
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vdb));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vdb));
|
2011-11-08 13:07:16 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (x != gridFaces - 1)
|
2011-11-08 13:07:16 +00:00
|
|
|
a++;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
|
|
|
|
|
vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
PASSATTRIB(0, 0, 3);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vda));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vda));
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 2);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, vdb));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, vdb));
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
|
|
a++;
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2011-11-08 13:07:16 +00:00
|
|
|
glBegin(GL_QUADS);
|
2012-05-11 08:05:47 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
|
|
|
|
|
float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
|
|
|
|
|
float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
2011-11-08 13:07:16 +00:00
|
|
|
|
|
|
|
|
ccgDM_glNormalFast(aco, bco, cco, dco);
|
|
|
|
|
|
|
|
|
|
PASSATTRIB(0, 1, 1);
|
|
|
|
|
glVertex3fv(dco);
|
|
|
|
|
PASSATTRIB(1, 1, 2);
|
|
|
|
|
glVertex3fv(cco);
|
|
|
|
|
PASSATTRIB(1, 0, 3);
|
|
|
|
|
glVertex3fv(bco);
|
|
|
|
|
PASSATTRIB(0, 0, 0);
|
|
|
|
|
glVertex3fv(aco);
|
|
|
|
|
|
|
|
|
|
a++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 23:04:43 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2011-11-08 13:07:16 +00:00
|
|
|
#undef PASSATTRIB
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-01 12:12:39 +00:00
|
|
|
static void ccgDM_drawMappedFaces(DerivedMesh *dm,
|
2012-04-22 00:20:58 +00:00
|
|
|
DMSetDrawOptions setDrawOptions,
|
|
|
|
|
DMSetMaterial setMaterial,
|
|
|
|
|
DMCompareDrawOptions compareDrawOptions,
|
|
|
|
|
void *userData, DMDrawFlag flag)
|
2011-12-01 12:12:39 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2015-07-17 03:36:03 +10:00
|
|
|
MLoopCol *mloopcol = NULL;
|
2015-08-20 09:20:41 +10:00
|
|
|
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
int i, gridSize = ccgSubSurf_getGridSize(ss);
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
2012-03-07 12:48:52 +00:00
|
|
|
int useColors = flag & DM_DRAW_USE_COLORS;
|
2009-12-14 17:08:02 +00:00
|
|
|
int gridFaces = gridSize - 1, totface;
|
2014-11-27 20:12:46 +01:00
|
|
|
int prev_mat_nr = -1;
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
|
2017-09-28 01:38:17 +10:00
|
|
|
if (ccgdm->pbvh) {
|
|
|
|
|
if (G.debug_value == 14)
|
|
|
|
|
BKE_pbvh_draw_BB(ccgdm->pbvh);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
2015-08-25 13:16:24 +02:00
|
|
|
int new_matnr;
|
|
|
|
|
bool draw_smooth, do_draw = true;
|
2015-07-20 16:08:06 +02:00
|
|
|
if (setDrawOptions == NULL) {
|
2015-08-25 13:16:24 +02:00
|
|
|
/* TODO(sergey): This is for cases when vertex colors or weights
|
|
|
|
|
* are visualising. Currently we don't have CD layers for this data
|
|
|
|
|
* and here we only make it so there's no garbage displayed.
|
|
|
|
|
*
|
|
|
|
|
* In the future we'll either need to have CD for this data or pass
|
|
|
|
|
* this data as face-varying or vertex-varying data in OSD mesh.
|
|
|
|
|
*/
|
2015-07-20 16:08:06 +02:00
|
|
|
glColor3f(0.8f, 0.8f, 0.8f);
|
|
|
|
|
}
|
2016-07-22 14:46:13 +02:00
|
|
|
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) {
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2015-08-25 13:16:24 +02:00
|
|
|
if (faceFlags) {
|
|
|
|
|
draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
|
|
|
|
|
new_matnr = (faceFlags[0].mat_nr + 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
draw_smooth = true;
|
|
|
|
|
new_matnr = 1;
|
|
|
|
|
}
|
|
|
|
|
if (setMaterial) {
|
|
|
|
|
setMaterial(new_matnr, NULL);
|
|
|
|
|
}
|
|
|
|
|
if (setDrawOptions) {
|
|
|
|
|
if (setDrawOptions(userData, 0) == DM_DRAW_OPTION_SKIP) {
|
|
|
|
|
do_draw = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (do_draw) {
|
|
|
|
|
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
|
|
|
|
ccgSubSurf_drawGLMesh(ss, true, -1, -1);
|
2016-08-19 23:04:43 +02:00
|
|
|
glShadeModel(GL_SMOOTH);
|
2015-08-25 13:16:24 +02:00
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2011-08-29 16:07:44 +00:00
|
|
|
/* currently unused -- each original face is handled separately */
|
|
|
|
|
(void)compareDrawOptions;
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (useColors) {
|
2015-07-17 03:36:03 +10:00
|
|
|
mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
|
|
|
|
|
if (!mloopcol)
|
|
|
|
|
mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
|
2009-12-14 17:08:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < totface; i++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[i].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
|
2006-08-28 01:12:36 +00:00
|
|
|
int origIndex;
|
2012-04-22 00:20:58 +00:00
|
|
|
unsigned char *cp = NULL;
|
2015-08-20 09:20:41 +10:00
|
|
|
const float (*ln)[3] = NULL;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-06 01:01:42 +00:00
|
|
|
origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flag & DM_DRAW_ALWAYS_SMOOTH) drawSmooth = 1;
|
2014-04-13 12:29:21 +02:00
|
|
|
else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
|
2006-08-28 01:12:36 +00:00
|
|
|
else drawSmooth = 1;
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (mloopcol) {
|
|
|
|
|
cp = (unsigned char *)mloopcol;
|
|
|
|
|
mloopcol += gridFaces * gridFaces * numVerts * 4;
|
2009-12-14 17:08:02 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-13 12:29:21 +02:00
|
|
|
if (lnors) {
|
|
|
|
|
ln = lnors;
|
2015-08-20 09:20:41 +10:00
|
|
|
lnors += (gridFaces * gridFaces * numVerts) * 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
|
|
|
|
|
2010-10-05 11:25:34 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
|
2010-10-05 11:25:34 +00:00
|
|
|
|
2014-11-27 20:12:46 +01:00
|
|
|
if (setMaterial) {
|
|
|
|
|
int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1;
|
|
|
|
|
|
|
|
|
|
if (mat_nr != prev_mat_nr) {
|
|
|
|
|
setMaterial(mat_nr, NULL); /* XXX, no faceFlags no material */
|
|
|
|
|
prev_mat_nr = mat_nr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (setDrawOptions && (index != ORIGINDEX_NONE))
|
2012-04-22 00:20:58 +00:00
|
|
|
draw_option = setDrawOptions(userData, index);
|
2010-10-05 11:25:34 +00:00
|
|
|
|
2012-03-08 06:47:05 +00:00
|
|
|
if (draw_option != DM_DRAW_OPTION_SKIP) {
|
|
|
|
|
if (draw_option == DM_DRAW_OPTION_STIPPLE) {
|
2015-12-25 22:57:50 +01:00
|
|
|
GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
|
|
|
|
|
GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
|
2007-09-25 03:31:12 +00:00
|
|
|
}
|
2011-07-08 11:03:37 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (S = 0; S < numVerts; S++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
2014-04-13 12:29:21 +02:00
|
|
|
if (ln) {
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
|
|
|
|
|
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
|
|
|
|
|
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
|
|
|
|
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[4]);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[1]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(d);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[8]);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[2]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(c);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[12]);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[3]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(b);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[0]);
|
2015-08-20 09:20:41 +10:00
|
|
|
glNormal3fv(ln[0]);
|
2014-04-13 12:29:21 +02:00
|
|
|
glVertex3fv(a);
|
|
|
|
|
|
|
|
|
|
if (cp) cp += 16;
|
2015-08-20 09:20:41 +10:00
|
|
|
ln += 4;
|
2014-04-13 12:29:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
else if (drawSmooth) {
|
2012-04-22 00:20:58 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *a, *b;
|
2007-09-25 03:31:12 +00:00
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-04-22 00:20:58 +00:00
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
|
|
|
|
|
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
2007-09-25 03:31:12 +00:00
|
|
|
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[0]);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, a));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, a));
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[4]);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, b));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, b));
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (x != gridFaces - 1) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cp) cp += 16;
|
2009-12-14 17:08:02 +00:00
|
|
|
}
|
2007-09-25 03:31:12 +00:00
|
|
|
}
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
|
|
|
|
|
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[12]);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, a));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, a));
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[8]);
|
2012-05-10 20:33:09 +00:00
|
|
|
glNormal3fv(CCG_elem_no(&key, b));
|
|
|
|
|
glVertex3fv(CCG_elem_co(&key, b));
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cp) cp += 16;
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2007-09-25 03:31:12 +00:00
|
|
|
glEnd();
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2007-09-25 03:31:12 +00:00
|
|
|
glBegin(GL_QUADS);
|
2012-04-22 00:20:58 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
|
|
|
|
|
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
|
|
|
|
|
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
|
|
|
|
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
2009-12-14 17:08:02 +00:00
|
|
|
|
|
|
|
|
ccgDM_glNormalFast(a, b, c, d);
|
2007-09-25 03:31:12 +00:00
|
|
|
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[4]);
|
2007-09-25 03:31:12 +00:00
|
|
|
glVertex3fv(d);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[8]);
|
2007-09-25 03:31:12 +00:00
|
|
|
glVertex3fv(c);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[12]);
|
2007-09-25 03:31:12 +00:00
|
|
|
glVertex3fv(b);
|
2017-09-30 19:20:04 +10:00
|
|
|
if (cp) glColor4ubv(&cp[0]);
|
2007-09-25 03:31:12 +00:00
|
|
|
glVertex3fv(a);
|
2009-12-14 17:08:02 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cp) cp += 16;
|
2007-09-25 03:31:12 +00:00
|
|
|
}
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
}
|
2007-09-25 03:31:12 +00:00
|
|
|
glEnd();
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-03-08 06:47:05 +00:00
|
|
|
if (draw_option == DM_DRAW_OPTION_STIPPLE)
|
2015-12-25 22:57:50 +01:00
|
|
|
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2012-03-07 04:41:14 +00:00
|
|
|
static void ccgDM_drawMappedEdges(DerivedMesh *dm,
|
2012-04-22 00:20:58 +00:00
|
|
|
DMSetDrawOptions setDrawOptions,
|
|
|
|
|
void *userData)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGEdgeIterator ei;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
2015-08-25 13:16:24 +02:00
|
|
|
/* TODO(sergey): Only draw edges from base mesh. */
|
2016-07-22 14:46:13 +02:00
|
|
|
if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) {
|
2015-08-25 13:16:24 +02:00
|
|
|
if (!setDrawOptions || (setDrawOptions(userData, 0) != DM_DRAW_OPTION_SKIP)) {
|
|
|
|
|
ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
|
2008-09-29 17:08:11 +00:00
|
|
|
int index = ccgDM_getEdgeMapIndex(ss, e);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
|
|
|
|
glBegin(GL_LINE_STRIP);
|
2012-04-22 00:20:58 +00:00
|
|
|
if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) {
|
|
|
|
|
if (useAging && !(G.f & G_BACKBUFSEL)) {
|
|
|
|
|
int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
|
|
|
|
|
glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
|
2005-03-31 15:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < edgeSize - 1; i++) {
|
2012-05-10 20:33:09 +00:00
|
|
|
glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
|
|
|
|
|
glVertex3fv(CCG_elem_offset_co(&key, edgeData, i + 1));
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2012-03-07 04:41:14 +00:00
|
|
|
static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
|
2012-04-22 00:20:58 +00:00
|
|
|
DMSetDrawOptions setDrawOptions,
|
|
|
|
|
DMSetDrawInterpOptions setDrawInterpOptions,
|
|
|
|
|
void *userData)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGEdgeIterator ei;
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
BLI_assert(!"Not currently supported");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
|
|
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
|
2008-09-29 17:08:11 +00:00
|
|
|
int index = ccgDM_getEdgeMapIndex(ss, e);
|
2005-03-30 08:12:27 +00:00
|
|
|
|
|
|
|
|
glBegin(GL_LINE_STRIP);
|
2012-04-22 00:20:58 +00:00
|
|
|
if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) {
|
|
|
|
|
for (i = 0; i < edgeSize; i++) {
|
|
|
|
|
setDrawInterpOptions(userData, index, (float) i / (edgeSize - 1));
|
2005-03-31 15:44:05 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (useAging && !(G.f & G_BACKBUFSEL)) {
|
|
|
|
|
int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
|
|
|
|
|
glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
|
2005-03-31 15:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 16:49:59 +00:00
|
|
|
|
2012-04-09 07:06:06 +00:00
|
|
|
static void ccgDM_foreachMappedFaceCenter(
|
2012-08-23 16:17:47 +00:00
|
|
|
DerivedMesh *dm,
|
|
|
|
|
void (*func)(void *userData, int index, const float co[3], const float no[3]),
|
2013-07-22 22:59:47 +00:00
|
|
|
void *userData,
|
|
|
|
|
DMForeachFlag flag)
|
2012-02-25 16:49:59 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGFaceIterator fi;
|
2005-08-03 04:04:05 +00:00
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(&key, ss);
|
|
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
|
|
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2013-07-22 22:59:47 +00:00
|
|
|
const int index = ccgDM_getFaceMapIndex(ss, f);
|
Big commit, had to rework lots of selection stuff so that things
worked properly with modifiers. Needs more testing I am sure.
No, honestly, I wasn't just cleaning for the hell of it, it
was *necessary* (I would never do such a thing). Selection should
work completely with cage options of modifiers now.
- added DerivedMesh foreach functions to iterate over mapped
verts/edges/face centers. These replaced some of the drawing
functions and are more general anyway. Special edge drawing
functions remain for performance reasons.
- removed EditFace xs, ys fields
- added general functions to iterate over screen coordinates of
mesh/curve/lattice objects
- removed all calc_*verts* functions that were used for storing
screen coordinates in objects. they were recalc'd on the fly
for most situations anyway, so now we just always do that.
calc_*verts_ext was one of those calls that did dirty things
deep down in the callstack (changing curarea and poking at
matrices)
- rewrote all vertex level selection routines (circle, lasso, bbox)
and closest vertex routines (rightmouse select) to use the new
system. This cleaned up the selection code a lot and the structure
of selection is much easier to see now. This is good for future
work on allowing modifiers to completely override the selection
system. It also points out some discrepancies in the way selection
is handled that might be nice to resolve (mesh vertex selection has
fancy stuff to try to help with selecting overlapping, but it only
works w/o bbuf select, and curves/lattices don't have at all).
- had to remove ton's code to move Manipulator to cage location, this
is not reliable (can come up with a different method if requested)
- as it happens BezTriple.s and BPoint.s are basically available to
be removed, just need to rewrite editipo code that still does
background calc of screen coordinates
- MVert.{xs,ys} are still around because they are abused in some places
for other info (not sure if this is safe actually, since they are
short's and the mvert limit went up).
And did I mention this commit is comes out to -305 lines? Well it does.
2005-08-09 08:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
if (index != -1) {
|
2012-05-11 08:05:47 +00:00
|
|
|
/* Face center data normal isn't updated atm. */
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
|
2013-07-22 22:59:47 +00:00
|
|
|
const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
|
|
|
|
|
func(userData, index, CCG_elem_co(&key, vd), no);
|
2005-08-08 18:50:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2012-02-25 16:49:59 +00:00
|
|
|
static void ccgDM_release(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
if (DM_release(dm)) {
|
2009-11-25 13:11:44 +00:00
|
|
|
/* Before freeing, need to update the displacement map */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->multires.modified_flags) {
|
2009-11-25 13:11:44 +00:00
|
|
|
/* Check that mmd still exists */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ccgdm->multires.local_mmd &&
|
2012-04-22 00:20:58 +00:00
|
|
|
BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
|
2012-04-28 06:31:57 +00:00
|
|
|
{
|
2009-11-25 13:11:44 +00:00
|
|
|
ccgdm->multires.mmd = NULL;
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->multires.mmd) {
|
2018-02-08 21:14:26 +11:00
|
|
|
if (ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED) {
|
|
|
|
|
/* TODO/OBMODE, pass real mode? */
|
|
|
|
|
multires_modifier_update_mdisps(dm, OB_MODE_OBJECT);
|
|
|
|
|
}
|
|
|
|
|
if (ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED) {
|
2012-03-14 06:32:03 +00:00
|
|
|
multires_modifier_update_hidden(dm);
|
2018-02-08 21:14:26 +11:00
|
|
|
}
|
2012-03-14 06:32:03 +00:00
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
2010-07-19 04:44:37 +00:00
|
|
|
if (ccgdm->ehash)
|
|
|
|
|
BLI_edgehash_free(ccgdm->ehash, NULL);
|
2010-01-05 22:33:41 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap);
|
|
|
|
|
if (ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
|
|
|
|
|
if (ccgdm->gridData) MEM_freeN(ccgdm->gridData);
|
|
|
|
|
if (ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset);
|
|
|
|
|
if (ccgdm->gridFlagMats) MEM_freeN(ccgdm->gridFlagMats);
|
|
|
|
|
if (ccgdm->gridHidden) {
|
2017-11-19 16:45:27 +11:00
|
|
|
/* Using dm->getNumGrids(dm) accesses freed memory */
|
|
|
|
|
uint numGrids = ccgdm->numGrid;
|
|
|
|
|
for (uint i = 0; i < numGrids; i++) {
|
|
|
|
|
if (ccgdm->gridHidden[i]) {
|
2012-03-14 06:31:49 +00:00
|
|
|
MEM_freeN(ccgdm->gridHidden[i]);
|
2017-11-19 16:45:27 +11:00
|
|
|
}
|
2012-03-14 06:31:49 +00:00
|
|
|
}
|
|
|
|
|
MEM_freeN(ccgdm->gridHidden);
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss);
|
|
|
|
|
if (ccgdm->pmap) MEM_freeN(ccgdm->pmap);
|
|
|
|
|
if (ccgdm->pmap_mem) MEM_freeN(ccgdm->pmap_mem);
|
2009-11-25 13:11:44 +00:00
|
|
|
MEM_freeN(ccgdm->edgeFlags);
|
|
|
|
|
MEM_freeN(ccgdm->faceFlags);
|
2015-07-20 16:08:06 +02:00
|
|
|
if (ccgdm->useGpuBackend == false) {
|
|
|
|
|
MEM_freeN(ccgdm->vertMap);
|
|
|
|
|
MEM_freeN(ccgdm->edgeMap);
|
|
|
|
|
MEM_freeN(ccgdm->faceMap);
|
|
|
|
|
}
|
2017-12-22 12:45:06 +01:00
|
|
|
|
2018-01-11 14:32:56 +01:00
|
|
|
BLI_mutex_end(&ccgdm->loops_cache_lock);
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_end(&ccgdm->origindex_cache_rwlock);
|
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MEM_freeN(ccgdm);
|
|
|
|
|
}
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
|
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (type == CD_ORIGINDEX) {
|
2009-11-25 13:11:44 +00:00
|
|
|
/* create origindex on demand to save memory */
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2009-11-25 13:11:44 +00:00
|
|
|
int *origindex;
|
|
|
|
|
int a, index, totnone, totorig;
|
|
|
|
|
|
2011-11-29 13:11:14 +00:00
|
|
|
/* Avoid re-creation if the layer exists already */
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_READ);
|
2011-11-29 13:11:14 +00:00
|
|
|
origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
|
2011-11-29 13:11:14 +00:00
|
|
|
if (origindex) {
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_WRITE);
|
2009-11-25 13:11:44 +00:00
|
|
|
DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
|
2012-04-22 00:20:58 +00:00
|
|
|
origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
totorig = ccgSubSurf_getNumVerts(ss);
|
2012-04-22 00:20:58 +00:00
|
|
|
totnone = dm->numVertData - totorig;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
/* original vertices are at the end */
|
2012-04-22 00:20:58 +00:00
|
|
|
for (a = 0; a < totnone; a++)
|
|
|
|
|
origindex[a] = ORIGINDEX_NONE;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < totorig; index++, a++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGVert *v = ccgdm->vertMap[index].vert;
|
|
|
|
|
origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_vert_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
|
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (type == CD_ORIGINDEX) {
|
2009-11-25 13:11:44 +00:00
|
|
|
/* create origindex on demand to save memory */
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2009-11-25 13:11:44 +00:00
|
|
|
int *origindex;
|
|
|
|
|
int a, i, index, totnone, totorig, totedge;
|
2012-04-22 00:20:58 +00:00
|
|
|
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2011-11-29 13:11:14 +00:00
|
|
|
/* Avoid re-creation if the layer exists already */
|
|
|
|
|
origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
|
|
|
|
|
if (origindex) {
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
|
2012-04-22 00:20:58 +00:00
|
|
|
origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
totedge = ccgSubSurf_getNumEdges(ss);
|
|
|
|
|
totorig = totedge * (edgeSize - 1);
|
|
|
|
|
totnone = dm->numEdgeData - totorig;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
/* original edges are at the end */
|
2012-04-22 00:20:58 +00:00
|
|
|
for (a = 0; a < totnone; a++)
|
|
|
|
|
origindex[a] = ORIGINDEX_NONE;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < totedge; index++) {
|
|
|
|
|
CCGEdge *e = ccgdm->edgeMap[index].edge;
|
|
|
|
|
int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < edgeSize - 1; i++, a++)
|
2012-04-22 00:20:58 +00:00
|
|
|
origindex[a] = mapIndex;
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_edge_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-29 13:01:51 +00:00
|
|
|
static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type)
|
2012-10-30 19:20:17 +00:00
|
|
|
{
|
|
|
|
|
if (type == CD_ORIGINDEX) {
|
|
|
|
|
/* create origindex on demand to save memory */
|
|
|
|
|
int *origindex;
|
|
|
|
|
|
|
|
|
|
/* Avoid re-creation if the layer exists already */
|
|
|
|
|
origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
|
|
|
|
|
if (origindex) {
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
|
|
|
|
|
origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
|
|
|
|
|
|
|
|
|
|
/* silly loop counting up */
|
|
|
|
|
range_vn_i(origindex, dm->getNumTessFaces(dm), 0);
|
|
|
|
|
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-21 10:20:44 +02:00
|
|
|
if (type == CD_TESSLOOPNORMAL) {
|
|
|
|
|
/* Create tessloopnormal on demand to save memory. */
|
|
|
|
|
/* Note that since tessellated face corners are the same a loops in CCGDM, and since all faces have four
|
|
|
|
|
* loops/corners, we can simplify the code here by converting tessloopnormals from 'short (*)[4][3]'
|
|
|
|
|
* to 'short (*)[3]'.
|
|
|
|
|
*/
|
|
|
|
|
short (*tlnors)[3];
|
|
|
|
|
|
|
|
|
|
/* Avoid re-creation if the layer exists already */
|
|
|
|
|
tlnors = DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
|
|
|
|
|
if (!tlnors) {
|
|
|
|
|
float (*lnors)[3];
|
|
|
|
|
short (*tlnors_it)[3];
|
|
|
|
|
const int numLoops = ccgDM_getNumLoops(dm);
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
lnors = dm->getLoopDataArray(dm, CD_NORMAL);
|
|
|
|
|
if (!lnors) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DM_add_tessface_layer(dm, CD_TESSLOOPNORMAL, CD_CALLOC, NULL);
|
|
|
|
|
tlnors = tlnors_it = (short (*)[3])DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
|
|
|
|
|
|
|
|
|
|
/* With ccgdm, we have a simple one to one mapping between loops and tessellated face corners. */
|
|
|
|
|
for (i = 0; i < numLoops; ++i, ++tlnors_it, ++lnors) {
|
|
|
|
|
normal_float_to_short_v3(*tlnors_it, *lnors);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tlnors;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 19:20:17 +00:00
|
|
|
return DM_get_tessface_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
|
2009-11-25 13:11:44 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (type == CD_ORIGINDEX) {
|
2009-11-25 13:11:44 +00:00
|
|
|
/* create origindex on demand to save memory */
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2009-11-25 13:11:44 +00:00
|
|
|
int *origindex;
|
|
|
|
|
int a, i, index, totface;
|
|
|
|
|
int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
|
|
|
|
|
|
2011-11-29 13:11:14 +00:00
|
|
|
/* Avoid re-creation if the layer exists already */
|
2012-10-30 19:20:17 +00:00
|
|
|
origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
|
2011-11-29 13:11:14 +00:00
|
|
|
if (origindex) {
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 19:20:17 +00:00
|
|
|
DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
|
|
|
|
|
origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (a = 0, index = 0; index < totface; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2009-11-25 13:11:44 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
int mapIndex = ccgDM_getFaceMapIndex(ss, f);
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < gridFaces * gridFaces * numVerts; i++, a++)
|
|
|
|
|
origindex[a] = mapIndex;
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return origindex;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 19:20:17 +00:00
|
|
|
return DM_get_poly_data_layer(dm, type);
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-29 13:11:14 +00:00
|
|
|
static void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type)
|
|
|
|
|
{
|
|
|
|
|
if (type == CD_ORIGINDEX) {
|
|
|
|
|
/* ensure creation of CD_ORIGINDEX layer */
|
|
|
|
|
ccgDM_get_vert_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_vert_data(dm, index, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *ccgDM_get_edge_data(DerivedMesh *dm, int index, int type)
|
|
|
|
|
{
|
|
|
|
|
if (type == CD_ORIGINDEX) {
|
|
|
|
|
/* ensure creation of CD_ORIGINDEX layer */
|
|
|
|
|
ccgDM_get_edge_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_edge_data(dm, index, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type)
|
|
|
|
|
{
|
2014-04-21 10:20:44 +02:00
|
|
|
if (ELEM(type, CD_ORIGINDEX, CD_TESSLOOPNORMAL)) {
|
|
|
|
|
/* ensure creation of CD_ORIGINDEX/CD_TESSLOOPNORMAL layers */
|
2011-11-29 13:11:14 +00:00
|
|
|
ccgDM_get_tessface_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_tessface_data(dm, index, type);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 19:20:17 +00:00
|
|
|
static void *ccgDM_get_poly_data(DerivedMesh *dm, int index, int type)
|
|
|
|
|
{
|
|
|
|
|
if (type == CD_ORIGINDEX) {
|
|
|
|
|
/* ensure creation of CD_ORIGINDEX layer */
|
|
|
|
|
ccgDM_get_tessface_data_layer(dm, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DM_get_poly_data(dm, index, type);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
static int ccgDM_getNumGrids(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2009-11-25 13:11:44 +00:00
|
|
|
int index, numFaces, numGrids;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
numFaces = ccgSubSurf_getNumFaces(ccgdm->ss);
|
|
|
|
|
numGrids = 0;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (index = 0; index < numFaces; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2009-11-25 13:11:44 +00:00
|
|
|
numGrids += ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return numGrids;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ccgDM_getGridSize(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgSubSurf_getGridSize(ccgdm->ss);
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ccgdm_create_grids(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
|
|
|
|
CCGSubSurf *ss = ccgdm->ss;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGElem **gridData;
|
2012-03-06 02:40:08 +00:00
|
|
|
DMFlagMat *gridFlagMats;
|
2009-11-25 13:11:44 +00:00
|
|
|
CCGFace **gridFaces;
|
|
|
|
|
int *gridOffset;
|
2011-01-10 03:55:47 +00:00
|
|
|
int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ccgdm->gridData)
|
2009-11-25 13:11:44 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
numGrids = ccgDM_getNumGrids(dm);
|
|
|
|
|
numFaces = ccgSubSurf_getNumFaces(ss);
|
2011-01-10 03:55:47 +00:00
|
|
|
/*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
/* compute offset into grid array for each face */
|
2012-04-22 00:20:58 +00:00
|
|
|
gridOffset = MEM_mallocN(sizeof(int) * numFaces, "ccgdm.gridOffset");
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (gIndex = 0, index = 0; index < numFaces; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2009-11-25 13:11:44 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
|
|
|
|
gridOffset[index] = gIndex;
|
|
|
|
|
gIndex += numVerts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute grid data */
|
2012-05-10 20:33:09 +00:00
|
|
|
gridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "ccgdm.gridData");
|
2012-04-22 00:20:58 +00:00
|
|
|
gridFaces = MEM_mallocN(sizeof(CCGFace *) * numGrids, "ccgdm.gridFaces");
|
|
|
|
|
gridFlagMats = MEM_mallocN(sizeof(DMFlagMat) * numGrids, "ccgdm.gridFlagMats");
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2013-07-22 23:20:48 +00:00
|
|
|
ccgdm->gridHidden = MEM_callocN(sizeof(*ccgdm->gridHidden) * numGrids, "ccgdm.gridHidden");
|
2012-03-14 06:31:49 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (gIndex = 0, index = 0; index < numFaces; index++) {
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2009-11-25 13:11:44 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (S = 0; S < numVerts; S++, gIndex++) {
|
2009-11-25 13:11:44 +00:00
|
|
|
gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
|
|
|
|
gridFaces[gIndex] = f;
|
2012-03-06 02:40:08 +00:00
|
|
|
gridFlagMats[gIndex] = ccgdm->faceFlags[index];
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->gridData = gridData;
|
|
|
|
|
ccgdm->gridFaces = gridFaces;
|
|
|
|
|
ccgdm->gridOffset = gridOffset;
|
2012-03-06 02:40:08 +00:00
|
|
|
ccgdm->gridFlagMats = gridFlagMats;
|
2017-11-19 16:45:27 +11:00
|
|
|
ccgdm->numGrid = numGrids;
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
static CCGElem **ccgDM_getGridData(DerivedMesh *dm)
|
2009-11-25 13:11:44 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
|
|
|
|
ccgdm_create_grids(dm);
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgdm->gridData;
|
2009-11-25 13:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
2009-12-03 18:35:37 +00:00
|
|
|
static int *ccgDM_getGridOffset(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2009-12-03 18:35:37 +00:00
|
|
|
|
|
|
|
|
ccgdm_create_grids(dm);
|
2012-02-05 08:18:34 +00:00
|
|
|
return ccgdm->gridOffset;
|
2009-12-03 18:35:37 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:33:09 +00:00
|
|
|
static void ccgDM_getGridKey(DerivedMesh *dm, CCGKey *key)
|
|
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCG_key_top_level(key, ccgdm->ss);
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-06 02:40:08 +00:00
|
|
|
static DMFlagMat *ccgDM_getGridFlagMats(DerivedMesh *dm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-03-06 02:40:08 +00:00
|
|
|
|
|
|
|
|
ccgdm_create_grids(dm);
|
|
|
|
|
return ccgdm->gridFlagMats;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-22 23:20:48 +00:00
|
|
|
static BLI_bitmap **ccgDM_getGridHidden(DerivedMesh *dm)
|
2012-03-14 06:31:49 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-03-14 06:31:49 +00:00
|
|
|
|
|
|
|
|
ccgdm_create_grids(dm);
|
|
|
|
|
return ccgdm->gridHidden;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-17 10:23:44 +00:00
|
|
|
static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
|
2012-02-05 06:20:51 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-02-05 06:20:51 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
|
2012-04-22 00:20:58 +00:00
|
|
|
Mesh *me = ob->data;
|
2012-02-05 06:20:51 +00:00
|
|
|
|
2013-03-17 19:55:10 +00:00
|
|
|
BKE_mesh_vert_poly_map_create(&ccgdm->pmap, &ccgdm->pmap_mem,
|
2012-02-05 06:20:51 +00:00
|
|
|
me->mpoly, me->mloop,
|
2012-02-05 07:09:30 +00:00
|
|
|
me->totvert, me->totpoly, me->totloop);
|
2012-02-05 06:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ccgdm->pmap;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 13:15:42 +00:00
|
|
|
static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
|
|
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
MultiresModifierData *mmd = ccgdm->multires.mmd;
|
2011-05-04 13:15:42 +00:00
|
|
|
|
2012-03-09 00:41:09 +00:00
|
|
|
/* both of multires and subsurf modifiers are CCG, but
|
2012-03-03 20:19:11 +00:00
|
|
|
* grids should only be used when sculpting on multires */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!mmd)
|
2011-05-04 13:15:42 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-08 21:14:26 +11:00
|
|
|
static struct PBVH *ccgDM_getPBVH(
|
|
|
|
|
Object *ob, DerivedMesh *dm, eObjectMode object_mode)
|
2009-11-25 13:11:44 +00:00
|
|
|
{
|
2012-04-22 00:20:58 +00:00
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
2012-05-10 20:33:09 +00:00
|
|
|
CCGKey key;
|
2018-01-24 11:13:49 +01:00
|
|
|
int numGrids;
|
2012-05-10 20:33:09 +00:00
|
|
|
|
|
|
|
|
CCG_key_top_level(&key, ccgdm->ss);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ob) {
|
2012-04-22 00:20:58 +00:00
|
|
|
ccgdm->pbvh = NULL;
|
2010-03-22 11:59:36 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ob->sculpt)
|
2010-03-22 11:59:36 +00:00
|
|
|
return NULL;
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2018-01-24 11:13:49 +01:00
|
|
|
bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
|
2018-02-08 21:14:26 +11:00
|
|
|
if ((object_mode & OB_MODE_SCULPT) == 0) {
|
2018-01-24 11:13:49 +01:00
|
|
|
/* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions.
|
|
|
|
|
* More complex cases break 'history' trail back to original vertices, in that case we fall back to
|
|
|
|
|
* deformed cage only (i.e. original deformed mesh). */
|
|
|
|
|
VirtualModifierData virtualModifierData;
|
|
|
|
|
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
|
|
|
|
|
|
|
|
|
|
grid_pbvh = true;
|
|
|
|
|
bool has_one_ccg_modifier = false;
|
|
|
|
|
for (; md; md = md->next) {
|
|
|
|
|
/* We can only accept to use this ccgdm if:
|
|
|
|
|
* - it's the only active ccgdm in the stack.
|
|
|
|
|
* - there is no topology-modifying modifier in the stack.
|
|
|
|
|
* Otherwise, there is no way to map back to original geometry from grid-generated PBVH.
|
|
|
|
|
*/
|
|
|
|
|
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
|
|
|
|
|
if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
|
|
|
|
|
if (has_one_ccg_modifier) {
|
|
|
|
|
/* We only allow a single active ccg modifier in the stack. */
|
|
|
|
|
grid_pbvh = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
has_one_ccg_modifier = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Any other non-deforming modifier makes it impossible to use grid pbvh. */
|
|
|
|
|
grid_pbvh = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-04 13:15:42 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ob->sculpt->pbvh) {
|
2018-01-24 11:13:49 +01:00
|
|
|
/* Note that we have to clean up exisitng pbvh instead of updating it in case it does not match current
|
|
|
|
|
* grid_pbvh status. */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (grid_pbvh) {
|
2018-01-24 11:13:49 +01:00
|
|
|
if (BKE_pbvh_get_ccgdm(ob->sculpt->pbvh) != NULL) {
|
|
|
|
|
/* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
|
|
|
|
|
* but this can be freed on ccgdm release, this updates the pointers
|
|
|
|
|
* when the ccgdm gets remade, the assumption is that the topology
|
|
|
|
|
* does not change. */
|
|
|
|
|
ccgdm_create_grids(dm);
|
|
|
|
|
BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, (void **)ccgdm->gridFaces,
|
|
|
|
|
ccgdm->gridFlagMats, ccgdm->gridHidden);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_pbvh_free(ob->sculpt->pbvh);
|
|
|
|
|
ob->sculpt->pbvh = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (BKE_pbvh_get_ccgdm(ob->sculpt->pbvh) != NULL) {
|
|
|
|
|
BKE_pbvh_free(ob->sculpt->pbvh);
|
|
|
|
|
ob->sculpt->pbvh = NULL;
|
2011-05-04 13:15:42 +00:00
|
|
|
}
|
2010-06-02 18:04:31 +00:00
|
|
|
|
|
|
|
|
ccgdm->pbvh = ob->sculpt->pbvh;
|
|
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2017-09-28 01:38:17 +10:00
|
|
|
if (ccgdm->pbvh) {
|
2018-01-24 11:13:49 +01:00
|
|
|
/* For grid pbvh, keep track of ccgdm */
|
|
|
|
|
if (grid_pbvh) {
|
2017-09-28 01:38:17 +10:00
|
|
|
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
|
|
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
return ccgdm->pbvh;
|
2017-09-28 01:38:17 +10:00
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2018-01-24 11:13:49 +01:00
|
|
|
/* No pbvh exists yet, we need to create one. only in case of multires
|
2012-03-03 20:19:11 +00:00
|
|
|
* we build a pbvh over the modified mesh, in other cases the base mesh
|
|
|
|
|
* is being sculpted, so we build a pbvh from that. */
|
2018-01-24 11:13:49 +01:00
|
|
|
/* Note: vwpaint tries to always build a pbvh over the modified mesh. */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (grid_pbvh) {
|
2011-05-04 13:15:42 +00:00
|
|
|
ccgdm_create_grids(dm);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2011-05-04 13:15:42 +00:00
|
|
|
numGrids = ccgDM_getNumGrids(dm);
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
|
2015-05-27 19:52:12 +02:00
|
|
|
BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData,
|
2012-05-11 08:05:47 +00:00
|
|
|
numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-11 08:05:47 +00:00
|
|
|
else if (ob->type == OB_MESH) {
|
|
|
|
|
Mesh *me = ob->data;
|
2015-07-17 03:36:03 +10:00
|
|
|
const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
|
|
|
|
|
MLoopTri *looptri;
|
|
|
|
|
|
|
|
|
|
looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
|
|
|
|
|
|
2015-07-17 04:22:24 +10:00
|
|
|
BKE_mesh_recalc_looptri(
|
|
|
|
|
me->mloop, me->mpoly,
|
|
|
|
|
me->mvert,
|
|
|
|
|
me->totloop, me->totpoly,
|
|
|
|
|
looptri);
|
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
|
2015-07-17 03:36:03 +10:00
|
|
|
BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
|
|
|
|
|
looptri, looptris_num);
|
2018-01-24 11:17:53 +01:00
|
|
|
|
|
|
|
|
if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) {
|
|
|
|
|
DerivedMesh *deformdm = ob->derivedDeform;
|
|
|
|
|
float (*vertCos)[3];
|
|
|
|
|
int totvert;
|
|
|
|
|
|
|
|
|
|
totvert = deformdm->getNumVerts(deformdm);
|
|
|
|
|
vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos");
|
|
|
|
|
deformdm->getVertCos(deformdm, vertCos);
|
|
|
|
|
BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos);
|
|
|
|
|
MEM_freeN(vertCos);
|
|
|
|
|
}
|
2011-05-04 13:15:42 +00:00
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
|
2018-01-15 11:38:56 +01:00
|
|
|
if (ccgdm->pbvh != NULL) {
|
2012-10-22 17:33:53 +00:00
|
|
|
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
|
2018-01-15 11:38:56 +01:00
|
|
|
pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask);
|
|
|
|
|
}
|
2012-10-22 17:33:53 +00:00
|
|
|
|
2018-01-24 11:13:49 +01:00
|
|
|
/* For grid pbvh, keep track of ccgdm. */
|
|
|
|
|
if (grid_pbvh && ccgdm->pbvh) {
|
2017-09-28 01:38:17 +10:00
|
|
|
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
|
|
|
|
|
}
|
2009-11-25 13:11:44 +00:00
|
|
|
return ccgdm->pbvh;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
|
2011-11-17 18:48:49 +00:00
|
|
|
{
|
|
|
|
|
/* Nothing to do: CCG handles creating its own tessfaces */
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-11 16:51:19 +02:00
|
|
|
/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
|
2016-11-23 17:19:03 -02:00
|
|
|
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
|
2015-07-17 03:36:03 +10:00
|
|
|
{
|
2017-08-11 16:51:19 +02:00
|
|
|
MLoopTri *mlooptri = dm->looptris.array;
|
2016-11-23 17:19:03 -02:00
|
|
|
const int tottri = dm->numPolyData * 2;
|
|
|
|
|
int i, poly_index;
|
|
|
|
|
|
|
|
|
|
DM_ensure_looptri_data(dm);
|
2017-09-19 13:57:46 +02:00
|
|
|
mlooptri = dm->looptris.array_wip;
|
2016-11-23 17:19:03 -02:00
|
|
|
|
2017-09-20 20:45:51 +02:00
|
|
|
BLI_assert(tottri == 0 || mlooptri != NULL);
|
2016-11-23 17:19:03 -02:00
|
|
|
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
|
|
|
|
|
BLI_assert(tottri == dm->looptris.num);
|
|
|
|
|
|
|
|
|
|
for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
|
|
|
|
|
MLoopTri *lt;
|
|
|
|
|
lt = &mlooptri[i];
|
|
|
|
|
/* quad is (0, 3, 2, 1) */
|
|
|
|
|
lt->tri[0] = (poly_index * 4) + 0;
|
|
|
|
|
lt->tri[1] = (poly_index * 4) + 2;
|
|
|
|
|
lt->tri[2] = (poly_index * 4) + 3;
|
|
|
|
|
lt->poly = poly_index;
|
|
|
|
|
|
|
|
|
|
lt = &mlooptri[i + 1];
|
|
|
|
|
lt->tri[0] = (poly_index * 4) + 0;
|
|
|
|
|
lt->tri[1] = (poly_index * 4) + 1;
|
|
|
|
|
lt->tri[2] = (poly_index * 4) + 2;
|
|
|
|
|
lt->poly = poly_index;
|
|
|
|
|
}
|
2017-09-19 13:57:46 +02:00
|
|
|
|
|
|
|
|
BLI_assert(dm->looptris.array == NULL);
|
2017-09-25 10:40:50 +02:00
|
|
|
atomic_cas_ptr((void **)&dm->looptris.array, dm->looptris.array, dm->looptris.array_wip);
|
2017-09-25 09:56:02 +02:00
|
|
|
dm->looptris.array_wip = NULL;
|
2015-07-17 03:36:03 +10:00
|
|
|
}
|
|
|
|
|
|
2013-05-30 17:36:43 +00:00
|
|
|
static void ccgDM_calcNormals(DerivedMesh *dm)
|
2011-11-13 15:13:59 +00:00
|
|
|
{
|
|
|
|
|
/* Nothing to do: CCG calculates normals during drawing */
|
2013-05-30 17:36:43 +00:00
|
|
|
dm->dirty &= ~DM_DIRTY_NORMALS;
|
2011-11-13 15:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.getMinMax = ccgDM_getMinMax;
|
|
|
|
|
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
|
|
|
|
|
ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
|
|
|
|
|
ccgdm->dm.getNumLoops = ccgDM_getNumLoops;
|
|
|
|
|
/* reuse of ccgDM_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */
|
2015-08-17 17:24:34 +10:00
|
|
|
ccgdm->dm.getNumPolys = ccgDM_getNumPolys;
|
|
|
|
|
ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
ccgdm->dm.getVert = ccgDM_getFinalVert;
|
|
|
|
|
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
|
2010-07-19 04:44:37 +00:00
|
|
|
ccgdm->dm.getTessFace = ccgDM_getFinalFace;
|
2013-09-04 01:29:34 +00:00
|
|
|
|
2010-04-05 11:11:15 +00:00
|
|
|
ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
|
|
|
|
|
ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
|
2013-09-04 01:29:34 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
|
|
|
|
|
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
|
2010-07-19 04:44:37 +00:00
|
|
|
ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
|
2011-06-14 03:16:08 +00:00
|
|
|
ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
|
|
|
|
|
ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
|
2011-11-29 13:11:14 +00:00
|
|
|
|
|
|
|
|
ccgdm->dm.getVertData = ccgDM_get_vert_data;
|
|
|
|
|
ccgdm->dm.getEdgeData = ccgDM_get_edge_data;
|
|
|
|
|
ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data;
|
2012-10-30 19:20:17 +00:00
|
|
|
ccgdm->dm.getPolyData = ccgDM_get_poly_data;
|
2009-11-25 13:11:44 +00:00
|
|
|
ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
|
|
|
|
|
ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
|
2011-11-29 13:01:51 +00:00
|
|
|
ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer;
|
2012-10-30 19:20:17 +00:00
|
|
|
ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer;
|
2009-11-25 13:11:44 +00:00
|
|
|
ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
|
|
|
|
|
ccgdm->dm.getGridSize = ccgDM_getGridSize;
|
|
|
|
|
ccgdm->dm.getGridData = ccgDM_getGridData;
|
2009-12-03 18:35:37 +00:00
|
|
|
ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
|
2012-05-10 20:33:09 +00:00
|
|
|
ccgdm->dm.getGridKey = ccgDM_getGridKey;
|
2012-03-06 02:40:08 +00:00
|
|
|
ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
|
2012-03-14 06:31:49 +00:00
|
|
|
ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
|
2012-02-05 06:20:51 +00:00
|
|
|
ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
|
2009-11-25 13:11:44 +00:00
|
|
|
ccgdm->dm.getPBVH = ccgDM_getPBVH;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2011-11-13 15:13:59 +00:00
|
|
|
ccgdm->dm.calcNormals = ccgDM_calcNormals;
|
2014-04-13 12:18:51 +02:00
|
|
|
ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
|
Add Custom Loop Normals.
This is the core code for it, tools (datatransfer and modifier) will come in next commits).
RNA api is already there, though.
See the code for details, but basically, we define, for each 'smooth fan'
(which is a set of adjacent loops around a same vertex that are smooth, i.e. have a single same normal),
a 'loop normal space' (or lnor space), using auto-computed normal and relevant edges, and store
custom normal as two angular factors inside that space. This allows to have custom normals
'following' deformations of the geometry, and to only save two shorts per loop in new clnor CDLayer.
Normal manipulation (editing, mixing, interpolating, etc.) shall always happen with plain 3D vectors normals,
and be converted back into storage format at the end.
Clnor computation has also been threaded (at least for Mesh case, not for BMesh), since the process can
be rather heavy with high poly meshes.
Also, bumping subversion, and fix mess in 2.70 versioning code.
2015-02-05 14:24:48 +01:00
|
|
|
ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
|
2015-08-24 15:14:34 +10:00
|
|
|
ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents;
|
2012-03-02 16:05:54 +00:00
|
|
|
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
|
2015-07-17 03:36:03 +10:00
|
|
|
ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
|
2011-11-13 15:13:59 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.getVertCos = ccgdm_getVertCos;
|
|
|
|
|
ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
|
|
|
|
|
ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
|
2014-04-23 15:18:11 +02:00
|
|
|
ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop;
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
|
2015-07-20 16:08:06 +02:00
|
|
|
|
2005-03-30 08:12:27 +00:00
|
|
|
ccgdm->dm.drawVerts = ccgDM_drawVerts;
|
|
|
|
|
ccgdm->dm.drawEdges = ccgDM_drawEdges;
|
2005-08-21 20:48:45 +00:00
|
|
|
ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
|
2005-03-30 08:12:27 +00:00
|
|
|
ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
|
- convert all DerivedMesh map functions to use index based
mapping (instead of Edit{Vert,Edge,Face} pointers)
- dropped convertToDispListMeshMapped (whew, glad of it too)
- added DerivedMesh drawMappedFaces function
- dropped EM suffix for DerivedMesh functions, it was neither
particularly correct nor descriptive
- converted test_index_mface to test_index_face that also corrects
MCol and TFace. Good thing we had three versions of this routine,
you never know when one might burn down.
- removed flipnorm_mesh, not used anymore (and was incorrect to
boot)
- Getting face select to work with modifiers turned out to be much
more complicated than expected. Reworked mapping architecture for
modifiers - basically elements in a DispListMesh are now required
to be stored in an order that corresponds exactly to original
ordering. MVert/MEdge/MFace all have a new flag ME_XXX_STEPINDEX
that is set on each element that is set on the first derived element
of each original element. I can't say the code to follow these
requirements for subsurf is particularly transparent, but on the
upside it is a reasonably consistent and simple system that is memory
efficient and allows keeping the DispListMesh structure.
- rewrote mirror modifier to be simpler/conform to new requirements
for mapped DispListMesh structure. This also means that mirror interacts
much better with incremental subsurf calculation (it used to recalc
one entire side on any topology change, now it generally avoids that).
- added EM_{init,free}_index_arrays and EM_get_{vert,edge,face}_for_index
functions to handle mapping indices back into appropriate EditMesh
structures.
- bug fix, make edges didn't recalc object data
- bug fix, initial image assignment to TFace's didn't recalc object data
- new feature, added circle select support for FACESELECT
- bug fix, creating new faces in editmode duplicated the TFACE active
flag - but there should only be one active tface
- bug fix, possible crash when deleting all faces in faceselect mode
on mesh with tfaces...
Still todo: TFace edge drawing is still not always correct in face
mode, in particular with a mirror modifier when mesh has edges (and
no preceeding subsurf). Have not yet decided how to deal with this.
Best solution is probably to do switch to meshes all having MEdge's,
in which case I can get rid of TFace edge flags (and need to recalc
modifiers on tface selection change).
2005-08-20 03:08:23 +00:00
|
|
|
ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
|
|
|
|
|
ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
|
|
|
|
|
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
|
2015-07-14 16:48:23 +02:00
|
|
|
ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
|
|
|
|
|
ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
|
|
|
|
|
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->dm.release = ccgDM_release;
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void create_ccgdm_maps(CCGDerivedMesh *ccgdm,
|
|
|
|
|
CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
CCGVertIterator vi;
|
|
|
|
|
CCGEdgeIterator ei;
|
|
|
|
|
CCGFaceIterator fi;
|
|
|
|
|
int totvert, totedge, totface;
|
2005-03-30 08:12:27 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
totvert = ccgSubSurf_getNumVerts(ss);
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
|
2015-07-20 16:08:06 +02:00
|
|
|
for (ccgSubSurf_initVertIterator(ss, &vi);
|
|
|
|
|
!ccgVertIterator_isStopped(&vi);
|
|
|
|
|
ccgVertIterator_next(&vi))
|
|
|
|
|
{
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totedge = ccgSubSurf_getNumEdges(ss);
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
|
2015-07-20 16:08:06 +02:00
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ei);
|
|
|
|
|
!ccgEdgeIterator_isStopped(&ei);
|
|
|
|
|
ccgEdgeIterator_next(&ei))
|
|
|
|
|
{
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totface = ccgSubSurf_getNumFaces(ss);
|
2012-02-05 08:18:34 +00:00
|
|
|
ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
|
2015-07-20 16:08:06 +02:00
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &fi);
|
|
|
|
|
!ccgFaceIterator_isStopped(&fi);
|
|
|
|
|
ccgFaceIterator_next(&fi))
|
|
|
|
|
{
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGFace *f = ccgFaceIterator_getCurrent(&fi);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-06 01:01:42 +00:00
|
|
|
ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))].face = f;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill in all geometry arrays making it possible to access any
|
|
|
|
|
* hires data from the CPU.
|
|
|
|
|
*/
|
|
|
|
|
static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
|
|
|
|
|
CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
bool useSubsurfUv)
|
|
|
|
|
{
|
|
|
|
|
const int totvert = ccgSubSurf_getNumVerts(ss);
|
|
|
|
|
const int totedge = ccgSubSurf_getNumEdges(ss);
|
|
|
|
|
const int totface = ccgSubSurf_getNumFaces(ss);
|
|
|
|
|
int index;
|
|
|
|
|
int i;
|
|
|
|
|
int vertNum = 0, edgeNum = 0, faceNum = 0;
|
|
|
|
|
int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
|
|
|
|
|
short *edgeFlags = ccgdm->edgeFlags;
|
|
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
|
|
|
|
int *polyidx = NULL;
|
|
|
|
|
#ifndef USE_DYNSIZE
|
|
|
|
|
int *loopidx = NULL, *vertidx = NULL;
|
|
|
|
|
BLI_array_declare(loopidx);
|
|
|
|
|
BLI_array_declare(vertidx);
|
|
|
|
|
#endif
|
|
|
|
|
int loopindex, loopindex2;
|
|
|
|
|
int edgeSize;
|
|
|
|
|
int gridSize;
|
|
|
|
|
int gridFaces, gridCuts;
|
|
|
|
|
int gridSideEdges;
|
|
|
|
|
int gridInternalEdges;
|
|
|
|
|
WeightTable wtable = {NULL};
|
|
|
|
|
MEdge *medge = NULL;
|
|
|
|
|
MPoly *mpoly = NULL;
|
|
|
|
|
bool has_edge_cd;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
edgeSize = ccgSubSurf_getEdgeSize(ss);
|
|
|
|
|
gridSize = ccgSubSurf_getGridSize(ss);
|
|
|
|
|
gridFaces = gridSize - 1;
|
2009-08-16 19:55:05 +00:00
|
|
|
gridCuts = gridSize - 2;
|
2008-09-29 17:08:11 +00:00
|
|
|
/*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
|
2006-08-28 01:12:36 +00:00
|
|
|
gridSideEdges = gridSize - 1;
|
2015-07-20 16:08:06 +02:00
|
|
|
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2011-09-07 06:49:20 +00:00
|
|
|
/* mvert = dm->getVertArray(dm); */ /* UNUSED */
|
2007-08-28 08:53:36 +00:00
|
|
|
medge = dm->getEdgeArray(dm);
|
2011-09-07 06:49:20 +00:00
|
|
|
/* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-08-30 21:30:07 +00:00
|
|
|
mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
|
2011-06-01 19:30:19 +00:00
|
|
|
base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
|
2009-08-30 21:30:07 +00:00
|
|
|
|
2010-07-19 04:44:37 +00:00
|
|
|
vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
|
2014-04-24 05:14:35 +10:00
|
|
|
edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
|
2009-08-15 17:31:28 +00:00
|
|
|
|
2012-10-30 19:20:17 +00:00
|
|
|
faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
|
2011-11-29 05:09:54 +00:00
|
|
|
polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX);
|
2009-08-15 17:31:28 +00:00
|
|
|
|
2014-04-24 05:20:45 +10:00
|
|
|
has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 0);
|
|
|
|
|
|
2011-10-30 03:57:46 +00:00
|
|
|
#if 0
|
|
|
|
|
/* this is not in trunk, can gives problems because colors initialize
|
2012-03-18 07:38:51 +00:00
|
|
|
* as black, just don't do it!, it works fine - campbell */
|
2010-07-19 04:44:37 +00:00
|
|
|
if (!CustomData_has_layer(&ccgdm->dm.faceData, CD_MCOL))
|
|
|
|
|
DM_add_tessface_layer(&ccgdm->dm, CD_MCOL, CD_CALLOC, NULL);
|
|
|
|
|
mcol = DM_get_tessface_data_layer(&ccgdm->dm, CD_MCOL);
|
2011-10-30 03:57:46 +00:00
|
|
|
#endif
|
|
|
|
|
|
2012-05-13 11:05:52 +00:00
|
|
|
loopindex = loopindex2 = 0; /* current loop index */
|
2009-08-18 20:05:08 +00:00
|
|
|
for (index = 0; index < totface; index++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGFace *f = ccgdm->faceMap[index].face;
|
2008-09-29 17:08:11 +00:00
|
|
|
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
2009-08-15 17:31:28 +00:00
|
|
|
int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
|
2012-03-06 01:01:42 +00:00
|
|
|
int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
2012-04-22 00:20:58 +00:00
|
|
|
int g2_wid = gridCuts + 2;
|
2013-03-16 14:33:32 +00:00
|
|
|
float *w, *w2;
|
2009-08-15 17:31:28 +00:00
|
|
|
int s, x, y;
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifdef USE_DYNSIZE
|
|
|
|
|
int loopidx[numVerts], vertidx[numVerts];
|
|
|
|
|
#endif
|
2009-08-18 20:05:08 +00:00
|
|
|
w = get_ss_weights(&wtable, gridCuts, numVerts);
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
ccgdm->faceMap[index].startVert = vertNum;
|
|
|
|
|
ccgdm->faceMap[index].startEdge = edgeNum;
|
|
|
|
|
ccgdm->faceMap[index].startFace = faceNum;
|
2015-07-20 16:08:06 +02:00
|
|
|
|
2012-03-06 00:17:03 +00:00
|
|
|
faceFlags->flag = mpoly ? mpoly[origIndex].flag : 0;
|
|
|
|
|
faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
|
|
|
|
|
faceFlags++;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
/* set the face base vert */
|
2012-04-22 00:20:58 +00:00
|
|
|
*((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2018-02-01 12:06:57 +11:00
|
|
|
BLI_array_clear(loopidx);
|
2012-04-28 15:14:16 +00:00
|
|
|
BLI_array_grow_items(loopidx, numVerts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2012-01-23 13:51:44 +00:00
|
|
|
for (s = 0; s < numVerts; s++) {
|
2009-08-16 19:55:05 +00:00
|
|
|
loopidx[s] = loopindex++;
|
2009-08-15 17:31:28 +00:00
|
|
|
}
|
2013-06-04 07:41:21 +00:00
|
|
|
|
|
|
|
|
#ifndef USE_DYNSIZE
|
2018-02-01 12:06:57 +11:00
|
|
|
BLI_array_clear(vertidx);
|
2012-04-28 15:14:16 +00:00
|
|
|
BLI_array_grow_items(vertidx, numVerts);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2012-01-23 13:51:44 +00:00
|
|
|
for (s = 0; s < numVerts; s++) {
|
2012-03-06 01:01:42 +00:00
|
|
|
CCGVert *v = ccgSubSurf_getFaceVert(f, s);
|
2010-01-05 22:33:41 +00:00
|
|
|
vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
2009-08-15 17:31:28 +00:00
|
|
|
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
/*I think this is for interpolating the center vert?*/
|
2013-01-07 03:24:22 +00:00
|
|
|
w2 = w; // + numVerts*(g2_wid-1) * (g2_wid-1); //numVerts*((g2_wid-1) * g2_wid+g2_wid-1);
|
2010-07-19 04:44:37 +00:00
|
|
|
DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
|
2009-08-18 20:05:08 +00:00
|
|
|
numVerts, vertNum);
|
2010-01-05 22:33:41 +00:00
|
|
|
if (vertOrigIndex) {
|
2009-08-18 20:05:08 +00:00
|
|
|
*vertOrigIndex = ORIGINDEX_NONE;
|
2012-05-09 09:24:15 +00:00
|
|
|
vertOrigIndex++;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-09 09:24:15 +00:00
|
|
|
vertNum++;
|
2009-08-16 19:55:05 +00:00
|
|
|
|
2009-08-18 20:05:08 +00:00
|
|
|
/*interpolate per-vert data*/
|
2012-03-24 06:18:31 +00:00
|
|
|
for (s = 0; s < numVerts; s++) {
|
|
|
|
|
for (x = 1; x < gridFaces; x++) {
|
2012-04-22 00:20:58 +00:00
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + x * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
|
2012-04-22 00:20:58 +00:00
|
|
|
numVerts, vertNum);
|
2009-08-18 20:05:08 +00:00
|
|
|
|
2010-01-05 22:33:41 +00:00
|
|
|
if (vertOrigIndex) {
|
2009-08-18 20:05:08 +00:00
|
|
|
*vertOrigIndex = ORIGINDEX_NONE;
|
2012-05-09 09:24:15 +00:00
|
|
|
vertOrigIndex++;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-09 09:24:15 +00:00
|
|
|
vertNum++;
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-08-16 19:55:05 +00:00
|
|
|
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
/*interpolate per-vert data*/
|
2012-03-24 06:18:31 +00:00
|
|
|
for (s = 0; s < numVerts; s++) {
|
|
|
|
|
for (y = 1; y < gridFaces; y++) {
|
|
|
|
|
for (x = 1; x < gridFaces; x++) {
|
2012-04-22 00:20:58 +00:00
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + (y * g2_wid + x) * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
|
2012-04-22 00:20:58 +00:00
|
|
|
numVerts, vertNum);
|
2009-08-16 19:55:05 +00:00
|
|
|
|
2010-01-05 22:33:41 +00:00
|
|
|
if (vertOrigIndex) {
|
2009-08-18 20:05:08 +00:00
|
|
|
*vertOrigIndex = ORIGINDEX_NONE;
|
2012-05-09 09:24:15 +00:00
|
|
|
vertOrigIndex++;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-09 09:24:15 +00:00
|
|
|
vertNum++;
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-16 19:55:05 +00:00
|
|
|
|
2014-04-24 05:14:35 +10:00
|
|
|
if (edgeOrigIndex) {
|
|
|
|
|
for (i = 0; i < numFinalEdges; ++i) {
|
|
|
|
|
edgeOrigIndex[edgeNum + i] = ORIGINDEX_NONE;
|
|
|
|
|
}
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (s = 0; s < numVerts; s++) {
|
2009-08-18 20:05:08 +00:00
|
|
|
/*interpolate per-face data*/
|
2012-04-22 00:20:58 +00:00
|
|
|
for (y = 0; y < gridFaces; y++) {
|
|
|
|
|
for (x = 0; x < gridFaces; x++) {
|
|
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + (y * g2_wid + x) * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
|
2009-08-16 19:55:05 +00:00
|
|
|
loopidx, w2, NULL, numVerts, loopindex2);
|
|
|
|
|
loopindex2++;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + ((y + 1) * g2_wid + (x)) * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
|
2009-08-16 19:55:05 +00:00
|
|
|
loopidx, w2, NULL, numVerts, loopindex2);
|
|
|
|
|
loopindex2++;
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + ((y + 1) * g2_wid + (x + 1)) * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
|
2009-08-16 19:55:05 +00:00
|
|
|
loopidx, w2, NULL, numVerts, loopindex2);
|
|
|
|
|
loopindex2++;
|
2015-07-20 16:08:06 +02:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
w2 = w + s * numVerts * g2_wid * g2_wid + ((y) * g2_wid + (x + 1)) * numVerts;
|
2010-07-19 04:44:37 +00:00
|
|
|
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
|
2009-08-16 19:55:05 +00:00
|
|
|
loopidx, w2, NULL, numVerts, loopindex2);
|
|
|
|
|
loopindex2++;
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
|
2009-08-18 20:05:08 +00:00
|
|
|
/*copy over poly data, e.g. mtexpoly*/
|
2010-07-19 04:44:37 +00:00
|
|
|
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
|
2009-08-16 19:55:05 +00:00
|
|
|
|
2009-08-30 21:52:13 +00:00
|
|
|
/*set original index data*/
|
2010-01-05 22:33:41 +00:00
|
|
|
if (faceOrigIndex) {
|
2012-10-30 19:20:17 +00:00
|
|
|
/* reference the index in 'polyOrigIndex' */
|
|
|
|
|
*faceOrigIndex = faceNum;
|
2010-01-05 22:33:41 +00:00
|
|
|
faceOrigIndex++;
|
|
|
|
|
}
|
|
|
|
|
if (polyOrigIndex) {
|
2013-03-13 22:15:59 +00:00
|
|
|
*polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
|
2010-01-05 22:33:41 +00:00
|
|
|
polyOrigIndex++;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2009-08-30 21:52:13 +00:00
|
|
|
|
2010-07-19 04:44:37 +00:00
|
|
|
ccgdm->reverseFaceMap[faceNum] = index;
|
2009-09-15 15:32:09 +00:00
|
|
|
|
Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
2012-03-18 22:06:57 +00:00
|
|
|
/* This is a simple one to one mapping, here... */
|
2015-08-17 17:24:34 +10:00
|
|
|
if (polyidx) {
|
|
|
|
|
polyidx[faceNum] = faceNum;
|
|
|
|
|
}
|
Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
2012-03-18 22:06:57 +00:00
|
|
|
|
2009-08-22 04:45:19 +00:00
|
|
|
faceNum++;
|
2009-08-15 17:31:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-18 20:05:08 +00:00
|
|
|
|
|
|
|
|
edgeNum += numFinalEdges;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totedge; ++index) {
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGEdge *e = ccgdm->edgeMap[index].edge;
|
2009-08-18 20:05:08 +00:00
|
|
|
int numFinalEdges = edgeSize - 1;
|
2010-01-05 22:33:41 +00:00
|
|
|
int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
|
2009-08-18 20:05:08 +00:00
|
|
|
int x;
|
|
|
|
|
int vertIdx[2];
|
2008-09-29 17:08:11 +00:00
|
|
|
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
|
2009-08-18 20:05:08 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
CCGVert *v;
|
2008-09-29 17:08:11 +00:00
|
|
|
v = ccgSubSurf_getEdgeVert0(e);
|
|
|
|
|
vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
|
|
|
|
|
v = ccgSubSurf_getEdgeVert1(e);
|
|
|
|
|
vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
|
2009-08-18 20:05:08 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
ccgdm->edgeMap[index].startVert = vertNum;
|
|
|
|
|
ccgdm->edgeMap[index].startEdge = edgeNum;
|
2009-08-18 20:05:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (edgeIdx >= 0 && edgeFlags)
|
2010-01-05 22:33:41 +00:00
|
|
|
edgeFlags[edgeIdx] = medge[edgeIdx].flag;
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-08-18 20:05:08 +00:00
|
|
|
/* set the edge base vert */
|
2012-04-22 00:20:58 +00:00
|
|
|
*((int *)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
|
2009-08-18 20:05:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (x = 1; x < edgeSize - 1; x++) {
|
2009-08-18 20:05:08 +00:00
|
|
|
float w[2];
|
|
|
|
|
w[1] = (float) x / (edgeSize - 1);
|
|
|
|
|
w[0] = 1 - w[1];
|
2006-08-28 01:12:36 +00:00
|
|
|
DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
|
2010-01-05 22:33:41 +00:00
|
|
|
if (vertOrigIndex) {
|
|
|
|
|
*vertOrigIndex = ORIGINDEX_NONE;
|
2012-05-09 09:24:15 +00:00
|
|
|
vertOrigIndex++;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
2012-05-09 09:24:15 +00:00
|
|
|
vertNum++;
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-24 05:20:45 +10:00
|
|
|
if (has_edge_cd) {
|
2014-06-02 14:24:25 +06:00
|
|
|
BLI_assert(edgeIdx >= 0 && edgeIdx < dm->getNumEdges(dm));
|
2014-04-24 05:20:45 +10:00
|
|
|
for (i = 0; i < numFinalEdges; ++i) {
|
2014-06-02 14:24:25 +06:00
|
|
|
CustomData_copy_data(&dm->edgeData, &ccgdm->dm.edgeData, edgeIdx, edgeNum + i, 1);
|
2014-04-24 05:20:45 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 05:14:35 +10:00
|
|
|
if (edgeOrigIndex) {
|
|
|
|
|
for (i = 0; i < numFinalEdges; ++i) {
|
|
|
|
|
edgeOrigIndex[edgeNum + i] = mapIndex;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
edgeNum += numFinalEdges;
|
2009-08-15 17:31:28 +00:00
|
|
|
}
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (useSubsurfUv) {
|
2011-10-30 09:48:59 +00:00
|
|
|
CustomData *ldata = &ccgdm->dm.loopData;
|
|
|
|
|
CustomData *dmldata = &dm->loopData;
|
|
|
|
|
int numlayer = CustomData_number_of_layers(ldata, CD_MLOOPUV);
|
|
|
|
|
int dmnumlayer = CustomData_number_of_layers(dmldata, CD_MLOOPUV);
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < numlayer && i < dmnumlayer; i++)
|
2011-10-30 09:48:59 +00:00
|
|
|
set_subsurf_uv(ss, dm, &ccgdm->dm, i);
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (index = 0; index < totvert; ++index) {
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGVert *v = ccgdm->vertMap[index].vert;
|
2010-07-19 04:44:37 +00:00
|
|
|
int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
|
2011-12-05 05:28:31 +00:00
|
|
|
int vertIdx;
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2011-12-05 05:28:31 +00:00
|
|
|
vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
ccgdm->vertMap[index].startVert = vertNum;
|
2009-08-22 04:45:19 +00:00
|
|
|
|
|
|
|
|
/* set the vert base vert */
|
2012-04-22 00:20:58 +00:00
|
|
|
*((int *) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2011-12-05 05:28:31 +00:00
|
|
|
DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
|
2009-08-22 04:45:19 +00:00
|
|
|
|
2010-01-05 22:33:41 +00:00
|
|
|
if (vertOrigIndex) {
|
|
|
|
|
*vertOrigIndex = mapIndex;
|
2012-05-09 09:24:15 +00:00
|
|
|
vertOrigIndex++;
|
2010-01-05 22:33:41 +00:00
|
|
|
}
|
2012-05-09 09:24:15 +00:00
|
|
|
vertNum++;
|
2009-08-22 04:45:19 +00:00
|
|
|
}
|
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
|
|
|
|
2013-06-04 07:41:21 +00:00
|
|
|
#ifndef USE_DYNSIZE
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_free(vertidx);
|
|
|
|
|
BLI_array_free(loopidx);
|
2013-06-04 07:41:21 +00:00
|
|
|
#endif
|
2009-08-29 23:55:35 +00:00
|
|
|
free_ss_weights(&wtable);
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
BLI_assert(vertNum == ccgSubSurf_getNumFinalVerts(ss));
|
|
|
|
|
BLI_assert(edgeNum == ccgSubSurf_getNumFinalEdges(ss));
|
|
|
|
|
BLI_assert(loopindex2 == ccgSubSurf_getNumFinalFaces(ss) * 4);
|
|
|
|
|
BLI_assert(faceNum == ccgSubSurf_getNumFinalFaces(ss));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill in only geometry arrays needed for the GPU tessellation. */
|
2015-08-03 19:47:06 +02:00
|
|
|
static void set_ccgdm_gpu_geometry(CCGDerivedMesh *ccgdm, DerivedMesh *dm)
|
2015-07-20 16:08:06 +02:00
|
|
|
{
|
2015-08-03 19:47:06 +02:00
|
|
|
const int totface = dm->getNumPolys(dm);
|
2015-07-20 16:08:06 +02:00
|
|
|
MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
|
|
|
|
|
int index;
|
|
|
|
|
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
|
|
|
|
|
|
|
|
|
for (index = 0; index < totface; index++) {
|
|
|
|
|
faceFlags->flag = mpoly ? mpoly[index].flag : 0;
|
2015-08-25 15:05:28 +02:00
|
|
|
faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0;
|
2015-07-20 16:08:06 +02:00
|
|
|
faceFlags++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Fill in edge flags. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
|
|
|
|
int drawInteriorEdges,
|
|
|
|
|
int useSubsurfUv,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
bool use_gpu_backend)
|
|
|
|
|
{
|
2015-08-03 16:44:46 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
const int totedge = dm->getNumEdges(dm);
|
|
|
|
|
const int totface = dm->getNumPolys(dm);
|
|
|
|
|
#else
|
2015-07-20 16:08:06 +02:00
|
|
|
const int totedge = ccgSubSurf_getNumEdges(ss);
|
|
|
|
|
const int totface = ccgSubSurf_getNumFaces(ss);
|
2015-08-03 16:44:46 +02:00
|
|
|
#endif
|
2015-07-20 16:08:06 +02:00
|
|
|
CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
|
|
|
|
|
|
|
|
|
|
if (use_gpu_backend == false) {
|
2015-08-03 16:44:46 +02:00
|
|
|
BLI_assert(totedge == ccgSubSurf_getNumEdges(ss));
|
|
|
|
|
BLI_assert(totface == ccgSubSurf_getNumFaces(ss));
|
2015-07-20 16:08:06 +02:00
|
|
|
DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
|
|
|
|
|
ccgSubSurf_getNumFinalVerts(ss),
|
|
|
|
|
ccgSubSurf_getNumFinalEdges(ss),
|
2015-08-17 17:24:34 +10:00
|
|
|
0,
|
2015-07-20 16:08:06 +02:00
|
|
|
ccgSubSurf_getNumFinalFaces(ss) * 4,
|
|
|
|
|
ccgSubSurf_getNumFinalFaces(ss));
|
|
|
|
|
|
|
|
|
|
CustomData_free_layer_active(&ccgdm->dm.polyData, CD_NORMAL,
|
|
|
|
|
ccgdm->dm.numPolyData);
|
|
|
|
|
|
|
|
|
|
ccgdm->reverseFaceMap =
|
|
|
|
|
MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss),
|
|
|
|
|
"reverseFaceMap");
|
|
|
|
|
|
|
|
|
|
create_ccgdm_maps(ccgdm, ss);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
|
|
|
|
|
0, 0, 0, 0, dm->getNumPolys(dm));
|
|
|
|
|
CustomData_copy_data(&dm->polyData,
|
|
|
|
|
&ccgdm->dm.polyData,
|
|
|
|
|
0, 0, dm->getNumPolys(dm));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_default_ccgdm_callbacks(ccgdm);
|
|
|
|
|
|
|
|
|
|
ccgdm->ss = ss;
|
|
|
|
|
ccgdm->drawInteriorEdges = drawInteriorEdges;
|
|
|
|
|
ccgdm->useSubsurfUv = useSubsurfUv;
|
|
|
|
|
ccgdm->useGpuBackend = use_gpu_backend;
|
|
|
|
|
|
|
|
|
|
/* CDDM hack. */
|
|
|
|
|
ccgdm->edgeFlags = MEM_callocN(sizeof(short) * totedge, "edgeFlags");
|
|
|
|
|
ccgdm->faceFlags = MEM_callocN(sizeof(DMFlagMat) * totface, "faceFlags");
|
|
|
|
|
|
|
|
|
|
if (use_gpu_backend == false) {
|
|
|
|
|
set_ccgdm_all_geometry(ccgdm, ss, dm, useSubsurfUv != 0);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-08-03 19:47:06 +02:00
|
|
|
set_ccgdm_gpu_geometry(ccgdm, dm);
|
2015-07-20 16:08:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ccgdm->dm.numVertData = ccgSubSurf_getNumFinalVerts(ss);
|
|
|
|
|
ccgdm->dm.numEdgeData = ccgSubSurf_getNumFinalEdges(ss);
|
2015-08-17 17:24:34 +10:00
|
|
|
ccgdm->dm.numPolyData = ccgSubSurf_getNumFinalFaces(ss);
|
|
|
|
|
ccgdm->dm.numLoopData = ccgdm->dm.numPolyData * 4;
|
|
|
|
|
ccgdm->dm.numTessFaceData = 0;
|
2015-07-20 16:08:06 +02:00
|
|
|
|
2018-01-11 14:32:56 +01:00
|
|
|
BLI_mutex_init(&ccgdm->loops_cache_lock);
|
2017-12-22 12:45:06 +01:00
|
|
|
BLI_rw_mutex_init(&ccgdm->origindex_cache_rwlock);
|
|
|
|
|
|
2005-03-31 15:44:05 +00:00
|
|
|
return ccgdm;
|
2005-03-30 08:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***/
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
static bool subsurf_use_gpu_backend(SubsurfFlags flags)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
/* Use GPU backend if it's a last modifier in the stack
|
|
|
|
|
* and user choosed to use any of the OSD compute devices,
|
|
|
|
|
* but also check if GPU has all needed features.
|
|
|
|
|
*/
|
|
|
|
|
return
|
|
|
|
|
(flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
|
2017-05-18 17:28:04 -04:00
|
|
|
(U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE);
|
2015-07-20 16:08:06 +02:00
|
|
|
#else
|
|
|
|
|
(void)flags;
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
struct DerivedMesh *subsurf_make_derived_from_derived(
|
2012-04-22 00:20:58 +00:00
|
|
|
struct DerivedMesh *dm,
|
|
|
|
|
struct SubsurfModifierData *smd,
|
2012-05-10 20:31:55 +00:00
|
|
|
float (*vertCos)[3],
|
|
|
|
|
SubsurfFlags flags)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-08-18 19:54:21 +00:00
|
|
|
int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0;
|
2015-06-04 15:28:26 +10:00
|
|
|
CCGFlags useAging = (smd->flags & eSubsurfModifierFlag_DebugIncr) ? CCG_USE_AGING : 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
|
|
|
|
|
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
|
2012-02-05 08:18:34 +00:00
|
|
|
CCGDerivedMesh *result;
|
2015-07-20 16:08:06 +02:00
|
|
|
bool use_gpu_backend = subsurf_use_gpu_backend(flags);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2013-09-12 10:41:00 +00:00
|
|
|
/* note: editmode calculation can only run once per
|
|
|
|
|
* modifier stack evaluation (uses freed cache) [#36299] */
|
2012-05-10 20:31:55 +00:00
|
|
|
if (flags & SUBSURF_FOR_EDIT_MODE) {
|
2015-05-04 16:26:28 +05:00
|
|
|
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
|
2010-01-25 11:39:56 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
/* TODO(sergey): Same as emCache below. */
|
|
|
|
|
if ((flags & SUBSURF_IN_EDIT_MODE) && smd->mCache) {
|
|
|
|
|
ccgSubSurf_free(smd->mCache);
|
|
|
|
|
smd->mCache = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-18 19:54:21 +00:00
|
|
|
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend);
|
|
|
|
|
#endif
|
2016-07-22 17:52:30 +02:00
|
|
|
ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple, useSubsurfUv);
|
2009-11-25 13:11:44 +00:00
|
|
|
result = getCCGDerivedMesh(smd->emCache,
|
2012-04-22 00:20:58 +00:00
|
|
|
drawInteriorEdges,
|
2015-07-20 16:08:06 +02:00
|
|
|
useSubsurfUv, dm, use_gpu_backend);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-10 20:31:55 +00:00
|
|
|
else if (flags & SUBSURF_USE_RENDER_PARAMS) {
|
2006-08-28 01:12:36 +00:00
|
|
|
/* Do not use cache in render mode. */
|
2008-02-13 11:18:08 +00:00
|
|
|
CCGSubSurf *ss;
|
2015-05-04 16:26:28 +05:00
|
|
|
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels, true) : smd->renderLevels;
|
2010-01-25 21:58:00 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (levels == 0)
|
2008-02-13 11:18:08 +00:00
|
|
|
return dm;
|
|
|
|
|
|
2012-08-18 19:54:21 +00:00
|
|
|
ss = _getSubSurf(NULL, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2016-07-22 17:52:30 +02:00
|
|
|
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
result = getCCGDerivedMesh(ss,
|
2015-07-20 16:08:06 +02:00
|
|
|
drawInteriorEdges, useSubsurfUv, dm, false);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
result->freeSS = 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-02-05 07:44:40 +00:00
|
|
|
int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
|
2015-05-04 16:26:28 +05:00
|
|
|
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
|
2006-08-28 01:12:36 +00:00
|
|
|
CCGSubSurf *ss;
|
2011-05-19 11:24:56 +00:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* It is quite possible there is a much better place to do this. It
|
2012-03-01 12:20:18 +00:00
|
|
|
* depends a bit on how rigorously we expect this function to never
|
2006-08-28 01:12:36 +00:00
|
|
|
* be called in editmode. In semi-theory we could share a single
|
|
|
|
|
* cache, but the handles used inside and outside editmode are not
|
|
|
|
|
* the same so we would need some way of converting them. Its probably
|
|
|
|
|
* not worth the effort. But then why am I even writing this long
|
|
|
|
|
* comment that no one will read? Hmmm. - zr
|
2011-05-19 11:24:56 +00:00
|
|
|
*
|
|
|
|
|
* Addendum: we can't really ensure that this is never called in edit
|
|
|
|
|
* mode, so now we have a parameter to verify it. - brecht
|
2006-08-28 01:12:36 +00:00
|
|
|
*/
|
2012-05-10 20:31:55 +00:00
|
|
|
if (!(flags & SUBSURF_IN_EDIT_MODE) && smd->emCache) {
|
2006-08-28 01:12:36 +00:00
|
|
|
ccgSubSurf_free(smd->emCache);
|
|
|
|
|
smd->emCache = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 20:31:55 +00:00
|
|
|
if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) {
|
2012-08-18 19:54:21 +00:00
|
|
|
smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
|
2012-05-10 20:32:41 +00:00
|
|
|
|
2016-07-22 17:52:30 +02:00
|
|
|
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-11-25 13:11:44 +00:00
|
|
|
result = getCCGDerivedMesh(smd->mCache,
|
2012-04-22 00:20:58 +00:00
|
|
|
drawInteriorEdges,
|
2015-07-20 16:08:06 +02:00
|
|
|
useSubsurfUv, dm, false);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-08-18 19:54:21 +00:00
|
|
|
CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
|
2015-07-20 16:08:06 +02:00
|
|
|
CCGSubSurf *prevSS = NULL;
|
|
|
|
|
|
2012-05-10 20:31:55 +00:00
|
|
|
if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
|
2015-07-20 16:08:06 +02:00
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
/* With OpenSubdiv enabled we always tries to re-use previos
|
|
|
|
|
* subsurf structure in order to save computation time since
|
|
|
|
|
* re-creation is rather a complicated business.
|
|
|
|
|
*
|
|
|
|
|
* TODO(sergey): There was a good eason why final calculation
|
|
|
|
|
* used to free entirely cached subsurf structure. reason of
|
2015-09-14 02:21:15 +10:00
|
|
|
* this is to be investigated still to be sure we don't have
|
2015-07-20 16:08:06 +02:00
|
|
|
* regressions here.
|
|
|
|
|
*/
|
2015-08-05 11:54:11 +02:00
|
|
|
if (use_gpu_backend) {
|
|
|
|
|
prevSS = smd->mCache;
|
|
|
|
|
}
|
|
|
|
|
else
|
2015-07-20 16:08:06 +02:00
|
|
|
#endif
|
2015-08-05 11:54:11 +02:00
|
|
|
{
|
|
|
|
|
ccgSubSurf_free(smd->mCache);
|
|
|
|
|
smd->mCache = NULL;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
|
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
have a mask layer and what that layer's offset is. Unlike normals
however, it doesn't change any behavior during CCG calculation; it's
there only to give CCGKey information on the mask.
* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
an extra layer is allocated, but the number of CCG layers is not set
to include it. This is done because GridPaintMasks are absolute,
rather than being relative to the subdivided output (as MDisp
displacements are), so we skip subdividing paint masks here.
* Add a new flag to subsurf_make_derived_from_derived(),
SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
set for _getSubSurf(). Related, masks are never loaded in during
ss_sync_from_derivedmesh(). After subdivision is finished, if the
alloc mask flag is set, the number of CCG layers is increase to 4
with ccgSubSurf_setNumLayers().
* Add a new flag to multires_make_from_derived(),
MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
mask data (e.g. multiresModifier_base_apply.) This flag is always
set in MOD_multires.c so that subdividing a mesh with a mask updates
properly even when not in sculpt mode.
* Update multiresModifier_disp_run() to apply, calculate, and add mask
elements. It's almost the same as the existing operations with xyz
coordinates, but treats masks as absolute rather than displacements
relative to subdivided values.
* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
addition to CD_MDISPS.
* Update multires_del_higher() to call the new function
multires_grid_paint_mask_downsample(), which allocates a
lower-resolution paint mask grid and copies values over from the
high-resolution grid.
2012-05-10 20:34:08 +00:00
|
|
|
if (flags & SUBSURF_ALLOC_PAINT_MASK)
|
|
|
|
|
ccg_flags |= CCG_ALLOC_MASK;
|
|
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
ss = _getSubSurf(prevSS, levels, 3, ccg_flags);
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
ccgSubSurf_setSkipGrids(ss, use_gpu_backend);
|
|
|
|
|
#endif
|
2016-07-22 17:52:30 +02:00
|
|
|
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2015-07-20 16:08:06 +02:00
|
|
|
result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-05-10 20:31:55 +00:00
|
|
|
if (flags & SUBSURF_IS_FINAL_CALC)
|
2009-11-25 13:11:44 +00:00
|
|
|
smd->mCache = ss;
|
|
|
|
|
else
|
|
|
|
|
result->freeSS = 1;
|
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
have a mask layer and what that layer's offset is. Unlike normals
however, it doesn't change any behavior during CCG calculation; it's
there only to give CCGKey information on the mask.
* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
an extra layer is allocated, but the number of CCG layers is not set
to include it. This is done because GridPaintMasks are absolute,
rather than being relative to the subdivided output (as MDisp
displacements are), so we skip subdividing paint masks here.
* Add a new flag to subsurf_make_derived_from_derived(),
SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
set for _getSubSurf(). Related, masks are never loaded in during
ss_sync_from_derivedmesh(). After subdivision is finished, if the
alloc mask flag is set, the number of CCG layers is increase to 4
with ccgSubSurf_setNumLayers().
* Add a new flag to multires_make_from_derived(),
MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
mask data (e.g. multiresModifier_base_apply.) This flag is always
set in MOD_multires.c so that subdividing a mesh with a mask updates
properly even when not in sculpt mode.
* Update multiresModifier_disp_run() to apply, calculate, and add mask
elements. It's almost the same as the existing operations with xyz
coordinates, but treats masks as absolute rather than displacements
relative to subdivided values.
* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
addition to CD_MDISPS.
* Update multires_del_higher() to call the new function
multires_grid_paint_mask_downsample(), which allocates a
lower-resolution paint mask grid and copies values over from the
high-resolution grid.
2012-05-10 20:34:08 +00:00
|
|
|
|
|
|
|
|
if (flags & SUBSURF_ALLOC_PAINT_MASK)
|
|
|
|
|
ccgSubSurf_setNumLayers(ss, 4);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
return (DerivedMesh *)result;
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-16 03:24:05 +11:00
|
|
|
void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3])
|
2005-04-04 04:20:32 +00:00
|
|
|
{
|
2007-07-28 14:04:02 +00:00
|
|
|
/* Finds the subsurf limit positions for the verts in a mesh
|
|
|
|
|
* and puts them in an array of floats. Please note that the
|
|
|
|
|
* calculated vert positions is incorrect for the verts
|
|
|
|
|
* on the boundary of the mesh.
|
|
|
|
|
*/
|
2012-05-10 20:32:41 +00:00
|
|
|
CCGSubSurf *ss = _getSubSurf(NULL, 1, 3, CCG_USE_ARENA);
|
2005-04-04 04:20:32 +00:00
|
|
|
float edge_sum[3], face_sum[3];
|
2014-12-10 11:06:00 +01:00
|
|
|
CCGVertIterator vi;
|
2013-12-26 08:26:41 +11:00
|
|
|
DerivedMesh *dm = CDDM_from_mesh(me);
|
2005-04-04 04:20:32 +00:00
|
|
|
|
2016-07-22 17:52:30 +02:00
|
|
|
ss_sync_from_derivedmesh(ss, dm, NULL, 0, 0);
|
2005-04-04 04:20:32 +00:00
|
|
|
|
2014-12-10 11:06:00 +01:00
|
|
|
for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
|
|
|
|
|
CCGVert *v = ccgVertIterator_getCurrent(&vi);
|
2008-09-29 17:08:11 +00:00
|
|
|
int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
|
|
|
|
|
int N = ccgSubSurf_getVertNumEdges(v);
|
|
|
|
|
int numFaces = ccgSubSurf_getVertNumFaces(v);
|
2005-04-04 04:20:32 +00:00
|
|
|
float *co;
|
|
|
|
|
int i;
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2012-05-13 11:05:52 +00:00
|
|
|
zero_v3(edge_sum);
|
|
|
|
|
zero_v3(face_sum);
|
2005-04-04 04:20:32 +00:00
|
|
|
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < N; i++) {
|
2008-09-29 17:08:11 +00:00
|
|
|
CCGEdge *e = ccgSubSurf_getVertEdge(v, i);
|
2009-11-10 20:43:45 +00:00
|
|
|
add_v3_v3v3(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
|
2005-04-04 04:20:32 +00:00
|
|
|
}
|
2012-04-22 00:20:58 +00:00
|
|
|
for (i = 0; i < numFaces; i++) {
|
2008-09-29 17:08:11 +00:00
|
|
|
CCGFace *f = ccgSubSurf_getVertFace(v, i);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(face_sum, ccgSubSurf_getFaceCenterData(f));
|
2005-04-04 04:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
2007-07-28 14:04:02 +00:00
|
|
|
/* ad-hoc correction for boundary vertices, to at least avoid them
|
2012-03-03 20:19:11 +00:00
|
|
|
* moving completely out of place (brecht) */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (numFaces && numFaces != N)
|
2012-04-22 00:20:58 +00:00
|
|
|
mul_v3_fl(face_sum, (float)N / (float)numFaces);
|
2007-07-28 14:04:02 +00:00
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
co = ccgSubSurf_getVertData(ss, v);
|
2014-03-16 03:24:05 +11:00
|
|
|
r_positions[idx][0] = (co[0] * N * N + edge_sum[0] * 4 + face_sum[0]) / (N * (N + 5));
|
|
|
|
|
r_positions[idx][1] = (co[1] * N * N + edge_sum[1] * 4 + face_sum[1]) / (N * (N + 5));
|
|
|
|
|
r_positions[idx][2] = (co[2] * N * N + edge_sum[2] * 4 + face_sum[2]) / (N * (N + 5));
|
2005-04-04 04:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
ccgSubSurf_free(ss);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
|
|
|
|
dm->release(dm);
|
2005-04-04 04:20:32 +00:00
|
|
|
}
|
2015-08-05 15:11:50 +02:00
|
|
|
|
|
|
|
|
bool subsurf_has_edges(DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-08-05 23:50:22 +10:00
|
|
|
#else
|
|
|
|
|
(void)ccgdm;
|
2015-08-05 15:11:50 +02:00
|
|
|
#endif
|
|
|
|
|
return dm->getNumEdges(dm) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool subsurf_has_faces(DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
if (ccgdm->useGpuBackend) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-08-05 23:50:22 +10:00
|
|
|
#else
|
|
|
|
|
(void)ccgdm;
|
2015-08-05 15:11:50 +02:00
|
|
|
#endif
|
|
|
|
|
return dm->getNumPolys(dm) != 0;
|
|
|
|
|
}
|