forked from bartvdbraak/blender
Split Normals I (1/5): basis for split normals (nearly nothing user-visible here):
* Add a new calcLoopNormals function to DerivedMesh struct, and implement it for CDDM and CCGDM (subsurf). EditDerivedBMesh (edit mode DM) only gets a dummy one in this commit. * Add a tessellated version of CD_LOOPNORMAL layer (CD_TESSLOOPNORMAL), with relevant code to handle it (tessellation, rna access, etc.). * Change auto_smooth options of Mesh (angle now in radian internaly, and toggle is now used to enable/disable split normals in DM creation process). Note BI render code is not touched here, hence its behavior regarding this option is now incoherent, will be addressed in a separate commit. Reviewers: campbellbarton CC: brecht Differential Revision: https://developer.blender.org/D365
This commit is contained in:
parent
a872d0b414
commit
18e4224142
@ -2760,6 +2760,15 @@ class VIEW3D_PT_view3d_name(Panel):
|
||||
row.label(text="", icon='BONE_DATA')
|
||||
row.prop(bone, "name", text="")
|
||||
|
||||
elif ob.type == 'MESH':
|
||||
me = ob.data
|
||||
row = layout.row()
|
||||
row.prop(me, "use_auto_smooth")
|
||||
row = row.row()
|
||||
if not me.use_auto_smooth:
|
||||
row.active = False
|
||||
row.prop(me, "auto_smooth_angle", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_display(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@ -2936,14 +2945,14 @@ class VIEW3D_PT_view3d_meshdisplay(Panel):
|
||||
|
||||
col.separator()
|
||||
col.label(text="Normals:")
|
||||
row = col.row()
|
||||
row = col.row(align=True)
|
||||
|
||||
row.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
|
||||
row.prop(mesh, "show_normal_loop", text="", icon='VERTEXSEL')
|
||||
row.prop(mesh, "show_normal_face", text="", icon='FACESEL')
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
|
||||
sub.prop(mesh, "show_normal_face", text="", icon='FACESEL')
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.active = mesh.show_normal_vertex or mesh.show_normal_face
|
||||
sub.active = mesh.show_normal_vertex or mesh.show_normal_face or mesh.show_normal_loop
|
||||
sub.prop(context.scene.tool_settings, "normal_size", text="Size")
|
||||
|
||||
col.separator()
|
||||
|
@ -193,6 +193,9 @@ struct DerivedMesh {
|
||||
/** Calculate vert and face normals */
|
||||
void (*calcNormals)(DerivedMesh *dm);
|
||||
|
||||
/** Calculate loop (split) normals */
|
||||
void (*calcLoopNormals)(DerivedMesh *dm, const float split_angle);
|
||||
|
||||
/** Recalculates mesh tessellation */
|
||||
void (*recalcTessellation)(DerivedMesh *dm);
|
||||
|
||||
|
@ -42,7 +42,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 270
|
||||
#define BLENDER_SUBVERSION 1
|
||||
#define BLENDER_SUBVERSION 2
|
||||
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
|
||||
#define BLENDER_MINVERSION 262
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@ -100,6 +100,8 @@ void CDDM_calc_normals_mapping(struct DerivedMesh *dm);
|
||||
void CDDM_calc_normals(struct DerivedMesh *dm);
|
||||
void CDDM_calc_normals_tessface(struct DerivedMesh *dm);
|
||||
|
||||
void CDDM_calc_loop_normals(struct DerivedMesh *dm, const float split_angle);
|
||||
|
||||
/* calculates edges for a CDDerivedMesh (from face data)
|
||||
* this completely replaces the current edge data in the DerivedMesh
|
||||
* builds edges from the tessellated face data.
|
||||
|
@ -215,7 +215,7 @@ void BKE_mesh_loops_to_mface_corners(
|
||||
struct CustomData *pdata, unsigned int lindex[4], int findex,
|
||||
const int polyindex, const int mf_len,
|
||||
const int numTex, const int numCol,
|
||||
const bool hasPCol, const bool hasOrigSpace);
|
||||
const bool hasPCol, const bool hasOrigSpace, const bool hasLNor);
|
||||
void BKE_mesh_loops_to_tessdata(
|
||||
struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
|
||||
int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
|
||||
|
@ -399,6 +399,11 @@ void DM_ensure_normals(DerivedMesh *dm)
|
||||
BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
|
||||
}
|
||||
|
||||
static void DM_calc_loop_normals(DerivedMesh *dm, float split_angle)
|
||||
{
|
||||
dm->calcLoopNormals(dm, split_angle);
|
||||
}
|
||||
|
||||
/* note: until all modifiers can take MPoly's as input,
|
||||
* use this at the start of modifiers */
|
||||
void DM_ensure_tessface(DerivedMesh *dm)
|
||||
@ -453,7 +458,8 @@ void DM_update_tessface_data(DerivedMesh *dm)
|
||||
if (CustomData_has_layer(fdata, CD_MTFACE) ||
|
||||
CustomData_has_layer(fdata, CD_MCOL) ||
|
||||
CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
|
||||
CustomData_has_layer(fdata, CD_ORIGSPACE))
|
||||
CustomData_has_layer(fdata, CD_ORIGSPACE) ||
|
||||
CustomData_has_layer(fdata, CD_TESSLOOPNORMAL))
|
||||
{
|
||||
loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
|
||||
|
||||
@ -1471,6 +1477,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
|
||||
/* XXX Same as above... For now, only weights preview in WPaint mode. */
|
||||
const bool do_mod_wmcol = do_init_wmcol;
|
||||
|
||||
const bool do_loop_normals = (me->flag & ME_AUTOSMOOTH);
|
||||
const float loop_normals_split_angle = me->smoothresh;
|
||||
|
||||
VirtualModifierData virtualModifierData;
|
||||
|
||||
ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
|
||||
@ -1865,7 +1874,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
|
||||
add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO);
|
||||
}
|
||||
|
||||
{
|
||||
if (do_loop_normals) {
|
||||
/* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
|
||||
DM_calc_loop_normals(finaldm, loop_normals_split_angle);
|
||||
|
||||
if (finaldm->getNumTessFaces(finaldm) == 0) {
|
||||
finaldm->recalcTessellation(finaldm);
|
||||
}
|
||||
/* Even if tessellation is not needed, we have for sure modified loop normals layer! */
|
||||
else {
|
||||
/* A tessellation already exists, it should always have a CD_ORIGINDEX. */
|
||||
BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX));
|
||||
DM_update_tessface_data(finaldm);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* calculating normals can re-calculate tessfaces in some cases */
|
||||
#if 0
|
||||
int num_tessface = finaldm->getNumTessFaces(finaldm);
|
||||
@ -1982,7 +2005,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
|
||||
ModifierData *md, *previewmd = NULL;
|
||||
float (*deformedVerts)[3] = NULL;
|
||||
CustomDataMask mask, previewmask = 0, append_mask = 0;
|
||||
DerivedMesh *dm, *orcodm = NULL;
|
||||
DerivedMesh *dm = NULL, *orcodm = NULL;
|
||||
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
|
||||
CDMaskLink *datamasks, *curr;
|
||||
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
|
||||
@ -1998,13 +2021,15 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
|
||||
const bool do_mod_wmcol = do_init_wmcol;
|
||||
VirtualModifierData virtualModifierData;
|
||||
|
||||
const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH);
|
||||
const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh;
|
||||
|
||||
modifiers_clearErrors(ob);
|
||||
|
||||
if (cage_r && cageIndex == -1) {
|
||||
*cage_r = getEditDerivedBMesh(em, ob, NULL);
|
||||
}
|
||||
|
||||
dm = NULL;
|
||||
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
|
||||
|
||||
/* copied from mesh_calc_modifiers */
|
||||
@ -2212,6 +2237,14 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
|
||||
DM_update_statvis_color(scene, ob, *final_r);
|
||||
}
|
||||
|
||||
if (do_loop_normals) {
|
||||
/* Compute loop normals */
|
||||
DM_calc_loop_normals(*final_r, loop_normals_split_angle);
|
||||
if (cage_r && *cage_r && (*cage_r != *final_r)) {
|
||||
DM_calc_loop_normals(*cage_r, loop_normals_split_angle);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- */
|
||||
/* BMESH_ONLY, ensure tessface's used for drawing,
|
||||
* but don't recalculate if the last modifier in the stack gives us tessfaces
|
||||
@ -2229,8 +2262,10 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
|
||||
}
|
||||
/* --- */
|
||||
|
||||
/* same as mesh_calc_modifiers */
|
||||
dm_ensure_display_normals(*final_r);
|
||||
/* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
|
||||
if (!do_loop_normals) {
|
||||
dm_ensure_display_normals(*final_r);
|
||||
}
|
||||
|
||||
/* add an orco layer if needed */
|
||||
if (dataMask & CD_MASK_ORCO)
|
||||
@ -2542,7 +2577,8 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
|
||||
/* ******************* GLSL ******************** */
|
||||
|
||||
typedef struct {
|
||||
float *precomputedFaceNormals;
|
||||
float (*precomputedFaceNormals)[3];
|
||||
short (*precomputedLoopNormals)[4][3];
|
||||
MTFace *mtface; /* texture coordinates */
|
||||
MFace *mface; /* indices */
|
||||
MVert *mvert; /* vertices & normals */
|
||||
@ -2594,11 +2630,14 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const i
|
||||
{
|
||||
//assert(vert_index >= 0 && vert_index < 4);
|
||||
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
|
||||
const bool smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH) != 0;
|
||||
|
||||
const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
|
||||
if (!smoothnormal) { // flat
|
||||
if (pMesh->precomputedLoopNormals) {
|
||||
normal_short_to_float_v3(r_no, pMesh->precomputedLoopNormals[face_num][vert_index]);
|
||||
}
|
||||
else if (!smoothnormal) { // flat
|
||||
if (pMesh->precomputedFaceNormals) {
|
||||
copy_v3_v3(r_no, &pMesh->precomputedFaceNormals[3 * face_num]);
|
||||
copy_v3_v3(r_no, pMesh->precomputedFaceNormals[face_num]);
|
||||
}
|
||||
else {
|
||||
MFace *mf = &pMesh->mface[face_num];
|
||||
@ -2638,12 +2677,17 @@ void DM_add_tangent_layer(DerivedMesh *dm)
|
||||
MFace *mface;
|
||||
float (*orco)[3] = NULL, (*tangent)[4];
|
||||
int /* totvert, */ totface;
|
||||
float *nors;
|
||||
float (*fnors)[3];
|
||||
short (*tlnors)[4][3];
|
||||
|
||||
if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
|
||||
return;
|
||||
|
||||
nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
|
||||
fnors = dm->getTessFaceDataArray(dm, CD_NORMAL);
|
||||
/* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
|
||||
* have to check this is valid...
|
||||
*/
|
||||
tlnors = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
|
||||
|
||||
/* check we have all the needed layers */
|
||||
/* totvert = dm->getNumVerts(dm); */ /* UNUSED */
|
||||
@ -2669,7 +2713,8 @@ void DM_add_tangent_layer(DerivedMesh *dm)
|
||||
SMikkTSpaceContext sContext = {NULL};
|
||||
SMikkTSpaceInterface sInterface = {NULL};
|
||||
|
||||
mesh2tangent.precomputedFaceNormals = nors;
|
||||
mesh2tangent.precomputedFaceNormals = fnors;
|
||||
mesh2tangent.precomputedLoopNormals = tlnors;
|
||||
mesh2tangent.mtface = mtface;
|
||||
mesh2tangent.mface = mface;
|
||||
mesh2tangent.mvert = mvert;
|
||||
|
@ -1738,6 +1738,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
|
||||
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
|
||||
|
||||
dm->calcNormals = CDDM_calc_normals;
|
||||
dm->calcLoopNormals = CDDM_calc_loop_normals;
|
||||
dm->recalcTessellation = CDDM_recalc_tessellation;
|
||||
|
||||
dm->getVertCos = cdDM_getVertCos;
|
||||
@ -2289,8 +2290,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
|
||||
CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
|
||||
}
|
||||
|
||||
|
||||
face_nors = MEM_mallocN(sizeof(float) * 3 * dm->numTessFaceData, "face_nors");
|
||||
face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numTessFaceData, "face_nors");
|
||||
|
||||
/* calculate face normals */
|
||||
BKE_mesh_calc_normals_mapping_ex(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
|
||||
@ -2298,8 +2298,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
|
||||
CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors,
|
||||
only_face_normals);
|
||||
|
||||
CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN,
|
||||
face_nors, dm->numTessFaceData);
|
||||
CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData);
|
||||
|
||||
cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
|
||||
}
|
||||
@ -2353,6 +2352,48 @@ void CDDM_calc_normals(DerivedMesh *dm)
|
||||
|
||||
#endif
|
||||
|
||||
void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
|
||||
{
|
||||
MVert *mverts = dm->getVertArray(dm);
|
||||
MEdge *medges = dm->getEdgeArray(dm);
|
||||
MLoop *mloops = dm->getLoopArray(dm);
|
||||
MPoly *mpolys = dm->getPolyArray(dm);
|
||||
|
||||
CustomData *ldata, *pdata;
|
||||
|
||||
float (*lnors)[3];
|
||||
float (*pnors)[3];
|
||||
|
||||
const int numVerts = dm->getNumVerts(dm);
|
||||
const int numEdges = dm->getNumEdges(dm);
|
||||
const int numLoops = dm->getNumLoops(dm);
|
||||
const int numPolys = dm->getNumPolys(dm);
|
||||
|
||||
ldata = dm->getLoopDataLayout(dm);
|
||||
if (CustomData_has_layer(ldata, CD_NORMAL)) {
|
||||
lnors = CustomData_get_layer(ldata, CD_NORMAL);
|
||||
}
|
||||
else {
|
||||
lnors = CustomData_add_layer(ldata, CD_NORMAL, CD_CALLOC, NULL, numLoops);
|
||||
}
|
||||
|
||||
/* Compute poly (always needed) and vert normals. */
|
||||
/* Note we can't use DM_ensure_normals, since it won't keep computed poly nors... */
|
||||
pdata = dm->getPolyDataLayout(dm);
|
||||
pnors = CustomData_get_layer(pdata, CD_NORMAL);
|
||||
if (!pnors) {
|
||||
pnors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
|
||||
}
|
||||
BKE_mesh_calc_normals_poly(mverts, numVerts, mloops, mpolys, numLoops, numPolys, pnors,
|
||||
(dm->dirty & DM_DIRTY_NORMALS) ? false : true);
|
||||
|
||||
dm->dirty &= ~DM_DIRTY_NORMALS;
|
||||
|
||||
BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
|
||||
mpolys, pnors, numPolys, split_angle);
|
||||
}
|
||||
|
||||
|
||||
void CDDM_calc_normals_tessface(DerivedMesh *dm)
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
|
||||
|
@ -1170,6 +1170,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
{sizeof(FreestyleFace), "FreestyleFace", 1, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
/* 39: CD_MLOOPTANGENT */
|
||||
{sizeof(float[4]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
/* 40: CD_TESSLOOPNORMAL */
|
||||
{sizeof(short[4][3]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/* note, numbers are from trunk and need updating for bmesh */
|
||||
@ -1185,7 +1187,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
||||
/* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight",
|
||||
/* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "CDBMElemPyPtr", "CDPaintMask",
|
||||
/* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
|
||||
/* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent",
|
||||
/* 37-40 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent", "CDTessLoopNormal",
|
||||
};
|
||||
|
||||
|
||||
@ -1217,9 +1219,9 @@ const CustomDataMask CD_MASK_BMESH =
|
||||
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
|
||||
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
|
||||
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
|
||||
const CustomDataMask CD_MASK_FACECORNERS =
|
||||
const CustomDataMask CD_MASK_FACECORNERS = /* XXX Not used anywhere! */
|
||||
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
|
||||
CD_MASK_MLOOPCOL;
|
||||
CD_MASK_MLOOPCOL | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT;
|
||||
const CustomDataMask CD_MASK_EVERYTHING =
|
||||
CD_MASK_MVERT | CD_MASK_MSTICKY /* DEPRECATED */ | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
|
||||
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
|
||||
@ -1229,7 +1231,9 @@ const CustomDataMask CD_MASK_EVERYTHING =
|
||||
CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE |
|
||||
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_BM_ELEM_PYPTR |
|
||||
/* BMESH ONLY END */
|
||||
CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
|
||||
CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN |
|
||||
CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
|
||||
CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL;
|
||||
|
||||
static const LayerTypeInfo *layerType_getInfo(int type)
|
||||
{
|
||||
@ -2283,6 +2287,9 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
|
||||
else if (fdata->layers[i].type == CD_MDISPS) {
|
||||
CustomData_add_layer_named(ldata, CD_MDISPS, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
|
||||
CustomData_add_layer_named(ldata, CD_NORMAL, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2304,6 +2311,9 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
|
||||
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
|
||||
CustomData_add_layer_named(fdata, CD_ORIGSPACE, CD_CALLOC, NULL, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_NORMAL) {
|
||||
CustomData_add_layer_named(fdata, CD_TESSLOOPNORMAL, CD_CALLOC, NULL, total, ldata->layers[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
|
||||
|
@ -171,6 +171,11 @@ static void emDM_calcNormals(DerivedMesh *dm)
|
||||
dm->dirty &= ~DM_DIRTY_NORMALS;
|
||||
}
|
||||
|
||||
static void emDM_calcLoopNormals(DerivedMesh *dm, const float split_angle)
|
||||
{
|
||||
/* Do nothing for now! */
|
||||
}
|
||||
|
||||
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
|
||||
{
|
||||
/* do nothing */
|
||||
@ -1654,6 +1659,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
|
||||
bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
|
||||
|
||||
bmdm->dm.calcNormals = emDM_calcNormals;
|
||||
bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
|
||||
bmdm->dm.recalcTessellation = emDM_recalcTessellation;
|
||||
|
||||
bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
|
||||
|
@ -574,6 +574,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
|
||||
#undef IS_EDGE_SHARP
|
||||
}
|
||||
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
@ -1103,7 +1104,8 @@ void BKE_mesh_loops_to_mface_corners(
|
||||
const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
|
||||
const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
|
||||
const bool hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */
|
||||
const bool hasOrigSpace /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
|
||||
const bool hasOrigSpace, /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
|
||||
const bool hasLNor /* CustomData_has_layer(ldata, CD_NORMAL) */
|
||||
)
|
||||
{
|
||||
MTFace *texface;
|
||||
@ -1152,6 +1154,14 @@ void BKE_mesh_loops_to_mface_corners(
|
||||
copy_v2_v2(of->uv[j], lof->uv);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLNor) {
|
||||
short (*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
|
||||
|
||||
for (j = 0; j < mf_len; j++) {
|
||||
normal_float_to_short_v3(tlnors[j], CustomData_get(ldata, (int)lindex[j], CD_NORMAL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1172,6 +1182,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
|
||||
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
|
||||
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
|
||||
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
|
||||
const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL);
|
||||
int findex, i, j;
|
||||
int *pidx;
|
||||
unsigned int (*lidx)[4];
|
||||
@ -1225,6 +1236,17 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLoopNormal) {
|
||||
short (*fnors)[4][3] = CustomData_get_layer(fdata, CD_TESSLOOPNORMAL);
|
||||
float (*lnors)[3] = CustomData_get_layer(ldata, CD_NORMAL);
|
||||
|
||||
for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, fnors++) {
|
||||
for (j = (*lidx)[3] ? 4 : 3; j--;) {
|
||||
normal_float_to_short_v3((*fnors)[j], lnors[(*lidx)[j]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1516,6 +1538,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
|
||||
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
|
||||
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
|
||||
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
|
||||
const bool hasLNor = CustomData_has_layer(ldata, CD_NORMAL);
|
||||
|
||||
/* over-alloc, ngons will be skipped */
|
||||
mface = MEM_mallocN(sizeof(*mface) * (size_t)totpoly, __func__);
|
||||
@ -1575,7 +1598,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
|
||||
|
||||
BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
|
||||
lindex, k, i, 3,
|
||||
numTex, numCol, hasPCol, hasOrigSpace);
|
||||
numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
|
||||
test_index_face(mf, fdata, k, 3);
|
||||
}
|
||||
else {
|
||||
@ -1595,7 +1618,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
|
||||
|
||||
BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
|
||||
lindex, k, i, 4,
|
||||
numTex, numCol, hasPCol, hasOrigSpace);
|
||||
numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
|
||||
test_index_face(mf, fdata, k, 4);
|
||||
}
|
||||
|
||||
@ -1651,6 +1674,16 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata,
|
||||
}
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) {
|
||||
float (*lnors)[3] = CustomData_get(ldata, loopstart, CD_NORMAL);
|
||||
short (*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
|
||||
const int max = mf->v4 ? 4 : 3;
|
||||
|
||||
for (i = 0; i < max; i++, lnors++, tlnors++) {
|
||||
normal_short_to_float_v3(*lnors, *tlnors);
|
||||
}
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_MDISPS)) {
|
||||
MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS);
|
||||
MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS);
|
||||
|
@ -3243,6 +3243,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
||||
ccgdm->dm.getPBVH = ccgDM_getPBVH;
|
||||
|
||||
ccgdm->dm.calcNormals = ccgDM_calcNormals;
|
||||
ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
|
||||
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
|
||||
|
||||
ccgdm->dm.getVertCos = ccgdm_getVertCos;
|
||||
|
@ -40,11 +40,13 @@
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_sdna_types.h"
|
||||
|
||||
#include "DNA_genfile.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
@ -160,4 +162,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(main, 270, 2)) {
|
||||
Mesh *me;
|
||||
|
||||
/* Mesh smoothresh deg->rad. */
|
||||
for (me = main->mesh.first; me; me = me->id.next) {
|
||||
me->smoothresh = DEG2RADF(me->smoothresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_freestyle_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
|
||||
@ -45,6 +47,7 @@ void BLO_update_defaults_startup_blend(Main *main)
|
||||
Scene *scene;
|
||||
SceneRenderLayer *srl;
|
||||
FreestyleLineStyle *linestyle;
|
||||
Mesh *me;
|
||||
|
||||
for (scene = main->scene.first; scene; scene = scene->id.next) {
|
||||
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
|
||||
@ -75,5 +78,9 @@ void BLO_update_defaults_startup_blend(Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (me = main->mesh.first; me; me = me->id.next) {
|
||||
me->smoothresh = DEG2RADF(180.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2403,6 +2403,48 @@ static int draw_dm_test_freestyle_face_mark(BMesh *bm, BMFace *efa)
|
||||
|
||||
#endif
|
||||
|
||||
/* Draw loop normals. */
|
||||
static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
|
||||
{
|
||||
/* XXX Would it be worth adding a dm->foreachMappedLoop func just for this? I doubt it... */
|
||||
|
||||
/* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
|
||||
* return loop data from bmesh itself. */
|
||||
float (*lnors)[3] = DM_get_loop_data_layer(dm, CD_NORMAL);
|
||||
|
||||
if (lnors) {
|
||||
drawDMNormal_userData data;
|
||||
MLoop *mloops = dm->getLoopArray(dm);
|
||||
MVert *mverts = dm->getVertArray(dm);
|
||||
int i, totloops = dm->getNumLoops(dm);
|
||||
|
||||
data.bm = em->bm;
|
||||
data.normalsize = scene->toolsettings->normalsize;
|
||||
|
||||
calcDrawDMNormalScale(ob, &data);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (i = 0; i < totloops; i++, mloops++, lnors++) {
|
||||
float no[3];
|
||||
float *co = mverts[mloops->v].co;
|
||||
|
||||
if (!data.uniform_scale) {
|
||||
mul_v3_m3v3(no, data.tmat, (float *)lnors);
|
||||
normalize_v3(no);
|
||||
mul_m3_v3(data.imat, no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(no,(float *)lnors);
|
||||
}
|
||||
mul_v3_fl(no, data.normalsize);
|
||||
add_v3_v3(no, co);
|
||||
glVertex3fv(co);
|
||||
glVertex3fv(no);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw faces with color set based on selection
|
||||
* return 2 for the active face so it renders with stipple enabled */
|
||||
static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
|
||||
@ -3351,6 +3393,10 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
|
||||
UI_ThemeColor(TH_VNORMAL);
|
||||
draw_dm_vert_normals(em, scene, ob, cageDM);
|
||||
}
|
||||
if (me->drawflag & ME_DRAW_LNORMALS) {
|
||||
UI_ThemeColor(TH_VNORMAL);
|
||||
draw_dm_loop_normals(em, scene, ob, cageDM);
|
||||
}
|
||||
|
||||
if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN |
|
||||
ME_DRAWEXTRA_FACEAREA |
|
||||
|
@ -63,10 +63,9 @@ typedef struct CustomDataExternal {
|
||||
* layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
|
||||
typedef struct CustomData {
|
||||
CustomDataLayer *layers; /* CustomDataLayers, ordered by type */
|
||||
int typemap[40]; /* runtime only! - maps types to indices of first layer of that type,
|
||||
int typemap[41]; /* runtime only! - maps types to indices of first layer of that type,
|
||||
* MUST be >= CD_NUMTYPES, but we cant use a define here.
|
||||
* Correct size is ensured in CustomData_update_typemap assert() */
|
||||
int pad[1];
|
||||
int totlayer, maxlayer; /* number of layers, size of layers array */
|
||||
int totsize; /* in editmode, total size of all data layers */
|
||||
struct BLI_mempool *pool; /* (BMesh Only): Memory pool for allocation of blocks */
|
||||
@ -119,7 +118,8 @@ enum {
|
||||
CD_FREESTYLE_EDGE = 37,
|
||||
CD_FREESTYLE_FACE = 38,
|
||||
CD_MLOOPTANGENT = 39,
|
||||
CD_NUMTYPES = 40,
|
||||
CD_TESSLOOPNORMAL = 40,
|
||||
CD_NUMTYPES = 41,
|
||||
};
|
||||
|
||||
/* Bits for CustomDataMask */
|
||||
@ -164,7 +164,8 @@ enum {
|
||||
#define CD_MASK_MVERT_SKIN (1LL << CD_MVERT_SKIN)
|
||||
#define CD_MASK_FREESTYLE_EDGE (1LL << CD_FREESTYLE_EDGE)
|
||||
#define CD_MASK_FREESTYLE_FACE (1LL << CD_FREESTYLE_FACE)
|
||||
#define CD_MASK_MLOOPTANGENT (1LL << CD_MLOOPTANGENT)
|
||||
#define CD_MASK_MLOOPTANGENT (1LL << CD_MLOOPTANGENT)
|
||||
#define CD_MASK_TESSLOOPNORMAL (1LL << CD_TESSLOOPNORMAL)
|
||||
|
||||
/* CustomData.flag */
|
||||
enum {
|
||||
|
@ -116,8 +116,9 @@ typedef struct Mesh {
|
||||
float rot[3];
|
||||
|
||||
int drawflag;
|
||||
short texflag, pad2[3];
|
||||
short smoothresh, flag;
|
||||
short texflag, flag;
|
||||
float smoothresh;
|
||||
int pad2;
|
||||
|
||||
/* customdata flag, for bevel-weight and crease, which are now optional */
|
||||
char cd_flag, pad;
|
||||
@ -212,6 +213,9 @@ typedef struct TFace {
|
||||
/* draw stats */
|
||||
#define ME_DRAW_STATVIS (1 << 17)
|
||||
|
||||
/* draw loop normals */
|
||||
#define ME_DRAW_LNORMALS (1 << 18)
|
||||
|
||||
/* Subsurf Type */
|
||||
#define ME_CC_SUBSURF 0
|
||||
#define ME_SIMPLE_SUBSURF 1
|
||||
|
@ -413,6 +413,21 @@ static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values)
|
||||
normal_tri_v3(values, me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co);
|
||||
}
|
||||
|
||||
static void rna_MeshTessFace_split_normals_get(PointerRNA *ptr, float *values)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
MFace *mface = (MFace *)ptr->data;
|
||||
const short (*vec)[4][3] = CustomData_get(&me->fdata, (int)(mface - me->mface), CD_TESSLOOPNORMAL);
|
||||
int i = 4;
|
||||
|
||||
if (!vec) {
|
||||
while (i--) zero_v3(&values[i * 3]);
|
||||
}
|
||||
else {
|
||||
while (i--) normal_short_to_float_v3(&values[i * 3], (const short*)(*vec)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static float rna_MeshTessFace_area_get(PointerRNA *ptr)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
@ -1105,20 +1120,6 @@ static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value)
|
||||
tf->tpage = (struct Image *)id;
|
||||
}
|
||||
|
||||
static void rna_Mesh_auto_smooth_angle_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
value = RAD2DEGF(value);
|
||||
CLAMP(value, 1.0f, 80.0f);
|
||||
me->smoothresh = (int)value;
|
||||
}
|
||||
|
||||
static float rna_Mesh_auto_smooth_angle_get(PointerRNA *ptr)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
return DEG2RADF((float)me->smoothresh);
|
||||
}
|
||||
|
||||
static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
|
||||
{
|
||||
MFace *face = (MFace *)ptr->data;
|
||||
@ -1817,6 +1818,7 @@ static void rna_def_mface(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
const int splitnor_dim[] = {4, 3};
|
||||
|
||||
srna = RNA_def_struct(brna, "MeshTessFace", NULL);
|
||||
RNA_def_struct_sdna(srna, "MFace");
|
||||
@ -1868,6 +1870,16 @@ static void rna_def_mface(BlenderRNA *brna)
|
||||
RNA_def_property_float_funcs(prop, "rna_MeshTessFace_normal_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Face Normal", "Local space unit length normal vector for this face");
|
||||
|
||||
prop = RNA_def_property(srna, "split_normals", PROP_FLOAT, PROP_DIRECTION);
|
||||
RNA_def_property_multi_array(prop, 2, splitnor_dim);
|
||||
RNA_def_property_range(prop, -1.0f, 1.0f);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_float_funcs(prop, "rna_MeshTessFace_split_normals_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Split Normals",
|
||||
"Local space unit length split normals vectors of the vertices of this face "
|
||||
"(must be computed beforehand using calc_normals_split or calc_tangents, "
|
||||
"and then calc_tessface)");
|
||||
|
||||
prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_float_funcs(prop, "rna_MeshTessFace_area_get", NULL, NULL);
|
||||
@ -3113,19 +3125,17 @@ static void rna_def_mesh(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH);
|
||||
RNA_def_property_ui_text(prop, "Auto Smooth",
|
||||
"Treat all set-smoothed faces with angles less than the specified angle "
|
||||
"as 'smooth' during render");
|
||||
"as 'smooth', unless they are linked by a sharp edge");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
|
||||
|
||||
#if 1 /* expose as radians */
|
||||
prop = RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_funcs(prop, "rna_Mesh_auto_smooth_angle_get", "rna_Mesh_auto_smooth_angle_set", NULL);
|
||||
RNA_def_property_ui_range(prop, DEG2RAD(1.0), DEG2RAD(80), 1.0, 1);
|
||||
#else
|
||||
prop = RNA_def_property(srna, "auto_smooth_angle", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "smoothresh");
|
||||
RNA_def_property_range(prop, 1, 80);
|
||||
#endif
|
||||
RNA_def_property_float_sdna(prop, NULL, "smoothresh");
|
||||
RNA_def_property_float_default(prop, DEG2RADF(180.0f));
|
||||
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
|
||||
RNA_def_property_ui_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f), 1.0, 1);
|
||||
RNA_def_property_ui_text(prop, "Auto Smooth Angle",
|
||||
"Maximum angle between face normals that 'Auto Smooth' will operate on");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
|
||||
|
||||
prop = RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED);
|
||||
@ -3183,6 +3193,11 @@ static void rna_def_mesh(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Draw Normals", "Display face normals as lines");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
|
||||
|
||||
prop = RNA_def_property(srna, "show_normal_loop", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_LNORMALS);
|
||||
RNA_def_property_ui_text(prop, "Draw Split Normals", "Display vertex-per-face normals as lines");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
|
||||
|
||||
prop = RNA_def_property(srna, "show_normal_vertex", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_VNORMALS);
|
||||
RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Display vertex normals as lines");
|
||||
|
Loading…
Reference in New Issue
Block a user