diff options
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_blender.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 38 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 45 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_geom.h | 6 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_geom.c | 43 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 7 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_lib.c | 25 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 113 |
9 files changed, 186 insertions, 95 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 857c88a6004..55ade5fe5d9 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -206,7 +206,7 @@ struct DerivedMesh { /* Fill the array (of length .getNumVerts()) with all vertex locations */ void (*getVertCos)(DerivedMesh *dm, float (*cos_r)[3]); - /* Get vertex normal, undefined if index is not valid */ + /* Get smooth vertex normal, undefined if index is not valid */ void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]); /* Get a map of vertices to faces diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 6cbc49e19c8..2bba079d605 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather then defining with quotes */ #define BLENDER_VERSION 256 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 407d2ded085..b7034a7db8a 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1798,7 +1798,7 @@ void CDDM_calc_normals(DerivedMesh *dm) int i; int numVerts = dm->numVertData; int numFaces = dm->numFaceData; - MFace *mf; + MFace *mfaces; MVert *mv; if(numVerts == 0) return; @@ -1817,27 +1817,43 @@ void CDDM_calc_normals(DerivedMesh *dm) NULL, dm->numFaceData); /* calculate face normals and add to vertex normals */ - mf = CDDM_get_faces(dm); - for(i = 0; i < numFaces; i++, mf++) { + mfaces = CDDM_get_faces(dm); + for(i = 0; i < numFaces; i++) { + MFace * mf = &mfaces[i]; float *f_no = face_nors[i]; if(mf->v4) - normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); + normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); else - normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); + normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); - add_v3_v3(temp_nors[mf->v1], f_no); - add_v3_v3(temp_nors[mf->v2], f_no); - add_v3_v3(temp_nors[mf->v3], f_no); - if(mf->v4) - add_v3_v3(temp_nors[mf->v4], f_no); + if((mf->flag&ME_SMOOTH)!=0) { + float *n4 = (mf->v4)? temp_nors[mf->v4]: NULL; + float *c4 = (mf->v4)? mv[mf->v4].co: NULL; + + accumulate_vertex_normals(temp_nors[mf->v1], temp_nors[mf->v2], temp_nors[mf->v3], n4, + f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, c4); + } + } + + for(i = 0; i < numFaces; i++) { + MFace * mf = &mfaces[i]; + + if((mf->flag&ME_SMOOTH)==0) { + float *f_no = face_nors[i]; + + if(is_zero_v3(temp_nors[mf->v1])) copy_v3_v3(temp_nors[mf->v1], f_no); + if(is_zero_v3(temp_nors[mf->v2])) copy_v3_v3(temp_nors[mf->v2], f_no); + if(is_zero_v3(temp_nors[mf->v3])) copy_v3_v3(temp_nors[mf->v3], f_no); + if(mf->v4 && is_zero_v3(temp_nors[mf->v4])) copy_v3_v3(temp_nors[mf->v4], f_no); + } } /* normalize vertex normals and assign */ for(i = 0; i < numVerts; i++, mv++) { float *no = temp_nors[i]; - if (normalize_v3(no) == 0.0) + if(normalize_v3(no) == 0.0f) normalize_v3_v3(no, mv->co); normal_float_to_short_v3(mv->no, no); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 247e48a5576..1e29f5c9d3f 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1278,26 +1278,42 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float *fnors= MEM_callocN(sizeof(*fnors)*3*numFaces, "meshnormals"); int i; - for (i=0; i<numFaces; i++) { + for(i=0; i<numFaces; i++) { MFace *mf= &mfaces[i]; float *f_no= &fnors[i*3]; - if (mf->v4) - normal_quad_v3( f_no,mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co); + if(mf->v4) + normal_quad_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co); else - normal_tri_v3( f_no,mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co); - - add_v3_v3(tnorms[mf->v1], f_no); - add_v3_v3(tnorms[mf->v2], f_no); - add_v3_v3(tnorms[mf->v3], f_no); - if (mf->v4) - add_v3_v3(tnorms[mf->v4], f_no); + normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co); + + if((mf->flag&ME_SMOOTH)!=0) { + float *n4 = (mf->v4)? tnorms[mf->v4]: NULL; + float *c4 = (mf->v4)? mverts[mf->v4].co: NULL; + + accumulate_vertex_normals(tnorms[mf->v1], tnorms[mf->v2], tnorms[mf->v3], n4, + f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, c4); + } + } + + for(i=0; i<numFaces; i++) { + MFace *mf= &mfaces[i]; + + if((mf->flag&ME_SMOOTH)==0) { + float *f_no= &fnors[i*3]; + if(is_zero_v3(tnorms[mf->v1])) copy_v3_v3(tnorms[mf->v1], f_no); + if(is_zero_v3(tnorms[mf->v2])) copy_v3_v3(tnorms[mf->v2], f_no); + if(is_zero_v3(tnorms[mf->v3])) copy_v3_v3(tnorms[mf->v3], f_no); + if(mf->v4 && is_zero_v3(tnorms[mf->v4])) copy_v3_v3(tnorms[mf->v4], f_no); + } } - for (i=0; i<numVerts; i++) { + + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ + for(i=0; i<numVerts; i++) { MVert *mv= &mverts[i]; float *no= tnorms[i]; - if (normalize_v3(no)==0.0) + if(normalize_v3(no) == 0.0f) normalize_v3_v3(no, mv->co); normal_float_to_short_v3(mv->no, no); @@ -1305,11 +1321,10 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, MEM_freeN(tnorms); - if (faceNors_r) { + if(faceNors_r) *faceNors_r = fnors; - } else { + else MEM_freeN(fnors); - } } float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 8d2f9ffa38b..3174c65beac 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -169,6 +169,12 @@ void box_minmax_bounds_m4(float min[3], float max[3], void map_to_tube(float *u, float *v, float x, float y, float z); void map_to_sphere(float *u, float *v, float x, float y, float z); +/********************************** Normals **********************************/ + +void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3], + float n4[3], const float f_no[3], const float co1[3], const float co2[3], + const float co3[3], const float co4[3]); + /********************************* Tangents **********************************/ typedef struct VertexTangent { diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 6a3abc697e9..b0709c30494 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1980,6 +1980,49 @@ void map_to_sphere(float *u, float *v,float x, float y, float z) } } +/********************************* Normals **********************************/ + +void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3], + float n4[3], const float f_no[3], const float co1[3], const float co2[3], + const float co3[3], const float co4[3]) +{ + float vdiffs[4][3]; + const int nverts= (n4!=NULL && co4!=NULL)? 4: 3; + + /* compute normalized edge vectors */ + sub_v3_v3v3(vdiffs[0], co2, co1); + sub_v3_v3v3(vdiffs[1], co3, co2); + + if(nverts==3) { + sub_v3_v3v3(vdiffs[2], co1, co3); + } + else { + sub_v3_v3v3(vdiffs[2], co4, co3); + sub_v3_v3v3(vdiffs[3], co1, co4); + normalize_v3(vdiffs[3]); + } + + normalize_v3(vdiffs[0]); + normalize_v3(vdiffs[1]); + normalize_v3(vdiffs[2]); + + /* accumulate angle weighted face normal */ + { + float *vn[]= {n1, n2, n3, n4}; + const float *prev_edge = vdiffs[nverts-1]; + int i; + + for(i=0; i<nverts; i++) { + const float *cur_edge= vdiffs[i]; + const float fac= saacos(-dot_v3v3(cur_edge, prev_edge)); + + // accumulate + madd_v3_v3fl(vn[i], f_no, fac); + prev_edge = cur_edge; + } + } +} + /********************************* Tangents **********************************/ /* For normal map tangents we need to detect uv boundaries, and only average diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 35aeb756274..9fe5fbb2a60 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -11551,6 +11551,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile <4)){ + Mesh *me; + + for(me= main->mesh.first; me; me= me->id.next) + mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + } + /* put compatibility code here until next subversion bump */ { diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c index 18706c0372e..384b311437b 100644 --- a/source/blender/editors/mesh/editmesh_lib.c +++ b/source/blender/editors/mesh/editmesh_lib.c @@ -2010,21 +2010,34 @@ void recalc_editnormals(EditMesh *em) if(efa->v4) { normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - add_v3_v3(efa->v4->no, efa->n); } else { normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); } - add_v3_v3(efa->v1->no, efa->n); - add_v3_v3(efa->v2->no, efa->n); - add_v3_v3(efa->v3->no, efa->n); + + if((efa->flag&ME_SMOOTH)!=0) { + float *n4= (efa->v4)? efa->v4->no: NULL; + float *c4= (efa->v4)? efa->v4->co: NULL; + + accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4, + efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4); + } + } + + for(efa= em->faces.first; efa; efa=efa->next) { + if((efa->flag&ME_SMOOTH)==0) { + if(is_zero_v3(efa->v1->no)) copy_v3_v3(efa->v1->no, efa->n); + if(is_zero_v3(efa->v2->no)) copy_v3_v3(efa->v2->no, efa->n); + if(is_zero_v3(efa->v3->no)) copy_v3_v3(efa->v3->no, efa->n); + if(efa->v4 && is_zero_v3(efa->v4->no)) copy_v3_v3(efa->v4->no, efa->n); + } } /* following Mesh convention; we use vertex coordinate itself for normal in this case */ for(eve= em->verts.first; eve; eve=eve->next) { - if (normalize_v3(eve->no)==0.0) { - VECCOPY(eve->no, eve->co); + if(normalize_v3(eve->no) == 0.0f) { + copy_v3_v3(eve->no, eve->co); normalize_v3(eve->no); } } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index d7eb22b5fc7..f51ed550813 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -499,6 +499,11 @@ static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemAr } + +/**************************************************************** +************ tangent space generation interface ***************** +****************************************************************/ + typedef struct { ObjectRen *obr; @@ -594,53 +599,11 @@ static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int d for(a=0; a<obr->totvlak; a++) { VlakRen *vlr= RE_findOrAddVlak(obr, a); if(vlr->flag & ME_SMOOTH) { - VertRen *v1= vlr->v1; - VertRen *v2= vlr->v2; - VertRen *v3= vlr->v3; - VertRen *v4= vlr->v4; - float n1[3], n2[3], n3[3], n4[3]; - float fac1, fac2, fac3, fac4=0.0f; - - sub_v3_v3v3(n1, v2->co, v1->co); - normalize_v3(n1); - sub_v3_v3v3(n2, v3->co, v2->co); - normalize_v3(n2); - if(v4==NULL) { - sub_v3_v3v3(n3, v1->co, v3->co); - normalize_v3(n3); - - fac1= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]); - fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); - fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); - } - else { - sub_v3_v3v3(n3, v4->co, v3->co); - normalize_v3(n3); - sub_v3_v3v3(n4, v1->co, v4->co); - normalize_v3(n4); - - fac1= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]); - fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); - fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); - fac4= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]); - - v4->n[0] +=fac4*vlr->n[0]; - v4->n[1] +=fac4*vlr->n[1]; - v4->n[2] +=fac4*vlr->n[2]; - } - - v1->n[0] +=fac1*vlr->n[0]; - v1->n[1] +=fac1*vlr->n[1]; - v1->n[2] +=fac1*vlr->n[2]; - - v2->n[0] +=fac2*vlr->n[0]; - v2->n[1] +=fac2*vlr->n[1]; - v2->n[2] +=fac2*vlr->n[2]; + float *n4= (vlr->v4)? vlr->v4->n: NULL; + float *c4= (vlr->v4)? vlr->v4->co: NULL; - v3->n[0] +=fac3*vlr->n[0]; - v3->n[1] +=fac3*vlr->n[1]; - v3->n[2] +=fac3*vlr->n[2]; - + accumulate_vertex_normals(vlr->v1->n, vlr->v2->n, vlr->v3->n, n4, + vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co, c4); } if(do_nmap_tangent || do_tangent) { /* tangents still need to be calculated for flat faces too */ @@ -652,17 +615,12 @@ static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int d /* do solid faces */ for(a=0; a<obr->totvlak; a++) { VlakRen *vlr= RE_findOrAddVlak(obr, a); + if((vlr->flag & ME_SMOOTH)==0) { - float *f1= vlr->v1->n; - if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); - f1= vlr->v2->n; - if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); - f1= vlr->v3->n; - if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); - if(vlr->v4) { - f1= vlr->v4->n; - if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); - } + if(is_zero_v3(vlr->v1->n)) VECCOPY(vlr->v1->n, vlr->n); + if(is_zero_v3(vlr->v2->n)) VECCOPY(vlr->v2->n, vlr->n); + if(is_zero_v3(vlr->v3->n)) VECCOPY(vlr->v3->n, vlr->n); + if(vlr->v4 && is_zero_v3(vlr->v4->n)) VECCOPY(vlr->v4->n, vlr->n); } if(do_nmap_tangent) { @@ -3236,6 +3194,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) int a, a1, ok, vertofs; int end, do_autosmooth=0, totvert = 0; int use_original_normals= 0; + int recalc_normals = 0; // false by default me= ob->data; @@ -3313,6 +3272,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) ma= give_render_material(re, ob, 1); + if(ma->material_type == MA_TYPE_HALO) { make_render_halos(re, obr, me, totvert, mvert, ma, orco); } @@ -3321,8 +3281,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) for(a=0; a<totvert; a++, mvert++) { ver= RE_findOrAddVert(obr, obr->totvert++); VECCOPY(ver->co, mvert->co); - if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */ + if(do_autosmooth==0) { /* autosmooth on original unrotated data to prevent differences between frames */ + ver->n[0]=mvert->no[0]; + ver->n[1]=mvert->no[1]; + ver->n[2]=mvert->no[2]; mul_m4_v3(mat, ver->co); + mul_transposed_m3_v3(imat, ver->n); + normalize_v3(ver->n); + negate_v3(ver->n); + } if(orco) { ver->orco= orco; @@ -3339,6 +3306,10 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if(!timeoffset) { /* store customdata names, because DerivedMesh is freed */ RE_set_customdata_names(obr, &dm->faceData); + + /* add tangent layer if we need one */ + if(need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) + DM_add_tangent_layer(dm); /* still to do for keys: the correct local texture coordinate */ @@ -3369,7 +3340,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if(ok) { end= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); - + for(a=0; a<end; a++, mface++) { int v1, v2, v3, v4, flag; @@ -3415,7 +3386,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) CustomDataLayer *layer; MTFace *mtface, *mtf; MCol *mcol, *mc; - int index, mtfn= 0, mcn= 0; + int index, mtfn= 0, mcn= 0, mtng=0; char *name; for(index=0; index<dm->faceData.totlayer; index++) { @@ -3432,6 +3403,22 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) mcol= (MCol*)layer->data; memcpy(mc, &mcol[a*4], sizeof(MCol)*4); } + else if(layer->type == CD_TANGENT && mtng < 1) + { + if(need_nmap_tangent!=0) + { + const float * tangent = (const float *) layer->data; + int t; + int nr_verts = v4!=0 ? 4 : 3; + float * ftang = RE_vlakren_get_nmap_tangent(obr, vlr, 1); + for(t=0; t<nr_verts; t++) + { + QUATCOPY(ftang+t*4, tangent+a*16+t*4); + mul_mat3_m4_v3(mat, ftang+t*4); + normalize_v3(ftang+t*4); + } + } + } } } } @@ -3447,6 +3434,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) MEdge *medge; struct edgesort *edgetable; int totedge= 0; + recalc_normals= 1; medge= dm->getEdgeArray(dm); @@ -3489,6 +3477,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if(!timeoffset) { if (test_for_displace(re, ob ) ) { + recalc_normals= 1; calc_vertexnormals(re, obr, 0, 0); if(do_autosmooth) do_displacement(re, obr, mat, imat); @@ -3497,11 +3486,13 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) } if(do_autosmooth) { + recalc_normals= 1; autosmooth(re, obr, mat, me->smoothresh); } - calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent); - + if(recalc_normals!=0 || need_tangent!=0) + calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent); + if(need_stress) calc_edge_stress(re, obr, me); } |