[Bf-codereview] modeler normals don't match render normals (issue4280049)
Morten Mikkelsen
mikkelsen7 at gmail.com
Tue Mar 15 17:20:14 CET 2011
Having trouble figuring out where, in the tool, I can add the alternative
patch.
So I am e-mailing it instead.
On Tue, Mar 15, 2011 at 8:22 AM, Morten Mikkelsen <mikkelsen7 at gmail.com>wrote:
> I'll make a version of the patch without any code sharing instead.
>
>
>
> On Tue, Mar 15, 2011 at 8:02 AM, <brechtvanlommel at gmail.com> wrote:
>
>> On 2011/03/15 14:51:05, mikkelsen7 wrote:
>>
>>> But it has to iterate over the faces twice.
>>>
>>
>> Removing the iteration from the abstraction would conflict with that.
>>>
>>
>> Is the second loop really necessary, those normals should never be used?
>> Maybe for export.. If it is necessary, just add two loops then.
>>
>>
>> http://codereview.appspot.com/4280049/
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.blender.org/pipermail/bf-codereview/attachments/20110315/0b289ba7/attachment-0001.htm
-------------- next part --------------
Index: render/intern/source/convertblender.c
===================================================================
--- render/intern/source/convertblender.c (revision 35505)
+++ render/intern/source/convertblender.c (working copy)
@@ -499,6 +499,11 @@
}
+
+/****************************************************************
+************ tangent space generation interface *****************
+****************************************************************/
+
typedef struct
{
ObjectRen *obr;
@@ -599,7 +604,6 @@
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);
@@ -608,10 +612,6 @@
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);
@@ -619,27 +619,22 @@
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];
+ v4->n[0] +=vlr->n[0];
+ v4->n[1] +=vlr->n[1];
+ v4->n[2] +=vlr->n[2];
}
- v1->n[0] +=fac1*vlr->n[0];
- v1->n[1] +=fac1*vlr->n[1];
- v1->n[2] +=fac1*vlr->n[2];
+ v1->n[0] +=vlr->n[0];
+ v1->n[1] +=vlr->n[1];
+ v1->n[2] +=vlr->n[2];
- v2->n[0] +=fac2*vlr->n[0];
- v2->n[1] +=fac2*vlr->n[1];
- v2->n[2] +=fac2*vlr->n[2];
+ v2->n[0] +=vlr->n[0];
+ v2->n[1] +=vlr->n[1];
+ v2->n[2] +=vlr->n[2];
- v3->n[0] +=fac3*vlr->n[0];
- v3->n[1] +=fac3*vlr->n[1];
- v3->n[2] +=fac3*vlr->n[2];
+ v3->n[0] +=vlr->n[0];
+ v3->n[1] +=vlr->n[1];
+ v3->n[2] +=vlr->n[2];
}
if(do_nmap_tangent || do_tangent) {
@@ -3236,6 +3231,7 @@
int a, a1, ok, vertofs;
int end, do_autosmooth=0, totvert = 0;
int use_original_normals= 0;
+ int iCalcNormalsInRender = 0; // false by default
me= ob->data;
@@ -3313,6 +3309,7 @@
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 +3318,17 @@
for(a=0; a<totvert; a++, mvert++) {
ver= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(ver->co, mvert->co);
+ ver->n[0]=mvert->no[0];
+ ver->n[1]=mvert->no[1];
+ ver->n[2]=mvert->no[2];
+ //dm->getVertNo(dm, a, ver->n);
if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */
+ {
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;
@@ -3370,6 +3376,9 @@
end= dm->getNumFaces(dm);
mface= dm->getFaceArray(dm);
+ if(need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
+ DM_add_tangent_layer(dm);
+
for(a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
@@ -3400,10 +3409,14 @@
len= normal_tri_v3( vlr->n,mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co);
}
else {
- if(vlr->v4)
+ /*if(vlr->v4)
len= normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
else
- len= normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co);
+ len= normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co);*/
+ len = dm->getFaceNo(dm, a, vlr->n);
+ mul_transposed_m3_v3(imat, vlr->n);
+ len *= normalize_v3(vlr->n);
+ negate_v3(vlr->n);
}
vlr->mat= ma;
@@ -3415,7 +3428,7 @@
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 +3445,22 @@
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 +3476,7 @@
MEdge *medge;
struct edgesort *edgetable;
int totedge= 0;
+ iCalcNormalsInRender=1;
medge= dm->getEdgeArray(dm);
@@ -3489,6 +3519,7 @@
if(!timeoffset) {
if (test_for_displace(re, ob ) ) {
+ iCalcNormalsInRender = 1;
calc_vertexnormals(re, obr, 0, 0);
if(do_autosmooth)
do_displacement(re, obr, mat, imat);
@@ -3497,11 +3528,13 @@
}
if(do_autosmooth) {
+ iCalcNormalsInRender = 1;
autosmooth(re, obr, mat, me->smoothresh);
}
- calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent);
-
+ if(iCalcNormalsInRender!=0 || need_tangent!=0)
+ calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent);
+
if(need_stress)
calc_edge_stress(re, obr, me);
}
Index: blenkernel/intern/cdderivedmesh.c
===================================================================
--- blenkernel/intern/cdderivedmesh.c (revision 35505)
+++ blenkernel/intern/cdderivedmesh.c (working copy)
@@ -179,6 +179,54 @@
no_r[2] = no[2]/32767.f;
}
+static void cdDM_getRealVertNo(DerivedMesh *dm, int face_index, int vert_num, float no_r[3])
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+ const int smoothnormal = (cddm->mface[face_index].flag & ME_SMOOTH);
+ if(!smoothnormal) // flat
+ {
+ dm->getFaceNo(dm, face_index, no_r);
+ }
+ else
+ {
+ unsigned int indices[] = { cddm->mface[face_index].v1, cddm->mface[face_index].v2,
+ cddm->mface[face_index].v3, cddm->mface[face_index].v4 };
+ dm->getVertNo(dm, indices[vert_num], no_r);
+ normalize_v3(no_r);
+ }
+}
+
+static float cdDM_getFaceNo(DerivedMesh *dm, int index, float no_r[3])
+{
+ float * nors = dm->getFaceDataArray(dm, CD_NORMAL);
+ float len;
+
+ if(nors)
+ {
+ VECCOPY(no_r, &nors[3*index]);
+ len = len_v3(no_r);
+ }
+ else
+ {
+ CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+ float * p0, * p1, * p2;
+ const int iGetNrVerts = cddm->mface[index].v4!=0 ? 4 : 3;
+ unsigned int indices[] = { cddm->mface[index].v1, cddm->mface[index].v2,
+ cddm->mface[index].v3, cddm->mface[index].v4 };
+ p0 = cddm->mvert[indices[0]].co; p1 = cddm->mvert[indices[1]].co; p2 = cddm->mvert[indices[2]].co;
+ if(iGetNrVerts==4)
+ {
+ float * p3 = cddm->mvert[indices[3]].co;
+ len = normal_quad_v3( no_r, p0, p1, p2, p3);
+ }
+ else {
+ len = normal_tri_v3(no_r, p0, p1, p2);
+ }
+
+ }
+ return len;
+}
+
static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -1480,6 +1528,8 @@
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
dm->getVertNo = cdDM_getVertNo;
+ dm->getRealVertNo = cdDM_getRealVertNo;
+ dm->getFaceNo = cdDM_getFaceNo;
dm->getPBVH = cdDM_getPBVH;
dm->getFaceMap = cdDM_getFaceMap;
@@ -1798,7 +1848,7 @@
int i;
int numVerts = dm->numVertData;
int numFaces = dm->numFaceData;
- MFace *mf;
+ MFace *mfaces;
MVert *mv;
if(numVerts == 0) return;
@@ -1817,22 +1867,41 @@
NULL, dm->numFaceData);
/* calculate face normals and add to vertex normals */
- mf = CDDM_get_faces(dm);
- for(i = 0; i < numFaces; i++, mf++) {
- float *f_no = face_nors[i];
+ mfaces = CDDM_get_faces(dm);
+ for(i = 0; i < numFaces; i++) {
+ MFace * mf = &mfaces[i];
+ if((mf->flag&ME_SMOOTH)!=0)
+ {
+ 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);
- else
- normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
+ if(mf->v4)
+ 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);
- 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);
+ 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);
+ }
}
+ for(i = 0; i < numFaces; i++) {
+ MFace * mf = &mfaces[i];
+ if((mf->flag&ME_SMOOTH)!=0)
+ {
+ float *f_no = face_nors[i];
+
+ if(temp_nors[mf->v1][0]==0 && temp_nors[mf->v1][1]==0 && temp_nors[mf->v1][2]==0) VECCOPY(temp_nors[mf->v1], f_no);
+ if(temp_nors[mf->v2][0]==0 && temp_nors[mf->v2][1]==0 && temp_nors[mf->v2][2]==0) VECCOPY(temp_nors[mf->v2], f_no);
+ if(temp_nors[mf->v3][0]==0 && temp_nors[mf->v3][1]==0 && temp_nors[mf->v3][2]==0) VECCOPY(temp_nors[mf->v3], f_no);
+ if(mf->v4)
+ if(temp_nors[mf->v4][0]==0 && temp_nors[mf->v4][1]==0 && temp_nors[mf->v4][2]==0) VECCOPY(temp_nors[mf->v4], f_no);
+ }
+ }
+
+
/* normalize vertex normals and assign */
for(i = 0; i < numVerts; i++, mv++) {
float *no = temp_nors[i];
Index: blenkernel/intern/mesh.c
===================================================================
--- blenkernel/intern/mesh.c (revision 35505)
+++ blenkernel/intern/mesh.c (working copy)
@@ -1280,19 +1280,35 @@
for (i=0; i<numFaces; i++) {
MFace *mf= &mfaces[i];
- float *f_no= &fnors[i*3];
+ if((mf->flag&ME_SMOOTH)!=0)
+ {
+ 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);
- else
- normal_tri_v3( f_no,mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].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);
+ 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);
+ }
}
+ for (i=0; i<numFaces; i++) {
+ MFace *mf= &mfaces[i];
+ if((mf->flag&ME_SMOOTH)==0)
+ {
+ float *f_no= &fnors[i*3];
+ if(tnorms[mf->v1][0]==0 && tnorms[mf->v1][1]==0 && tnorms[mf->v1][2]==0) VECCOPY(tnorms[mf->v1], f_no);
+ if(tnorms[mf->v2][0]==0 && tnorms[mf->v2][1]==0 && tnorms[mf->v2][2]==0) VECCOPY(tnorms[mf->v2], f_no);
+ if(tnorms[mf->v3][0]==0 && tnorms[mf->v3][1]==0 && tnorms[mf->v3][2]==0) VECCOPY(tnorms[mf->v3], f_no);
+ if(mf->v4)
+ if(tnorms[mf->v4][0]==0 && tnorms[mf->v4][1]==0 && tnorms[mf->v4][2]==0) VECCOPY(tnorms[mf->v4], f_no);
+ }
+ }
+
for (i=0; i<numVerts; i++) {
MVert *mv= &mverts[i];
float *no= tnorms[i];
Index: blenkernel/BKE_DerivedMesh.h
===================================================================
--- blenkernel/BKE_DerivedMesh.h (revision 35505)
+++ blenkernel/BKE_DerivedMesh.h (working copy)
@@ -206,9 +206,15 @@
/* 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 real vertex normal, takes faces set to hard into account */
+ void (*getRealVertNo)(DerivedMesh *dm, int face_index, int vert_num, float no_r[3]);
+
+ /* Get face normal, returns the length before normalization */
+ float (*getFaceNo)(DerivedMesh *dm, int index, float no_r[3]);
+
/* Get a map of vertices to faces
*/
struct ListBase *(*getFaceMap)(struct Object *ob, DerivedMesh *dm);
Index: editors/mesh/editmesh_lib.c
===================================================================
--- editors/mesh/editmesh_lib.c (revision 35505)
+++ editors/mesh/editmesh_lib.c (working copy)
@@ -2007,18 +2007,32 @@
}
for(efa= em->faces.first; efa; efa=efa->next) {
- 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);
+ if((efa->flag&ME_SMOOTH)!=0)
+ {
+ 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);
}
- 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);
+ }
+
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ if((efa->flag&ME_SMOOTH)==0)
+ {
+ if(efa->v1->no[0]==0 && efa->v1->no[1]==0 && efa->v1->no[2]==0) VECCOPY(efa->v1->no, efa->n);
+ if(efa->v2->no[0]==0 && efa->v2->no[1]==0 && efa->v2->no[2]==0) VECCOPY(efa->v2->no, efa->n);
+ if(efa->v3->no[0]==0 && efa->v3->no[1]==0 && efa->v3->no[2]==0) VECCOPY(efa->v3->no, efa->n);
+ if(efa->v4)
+ if(efa->v4->no[0]==0 && efa->v4->no[1]==0 && efa->v4->no[2]==0) VECCOPY(efa->v4->no, efa->n);
}
- add_v3_v3(efa->v1->no, efa->n);
- add_v3_v3(efa->v2->no, efa->n);
- add_v3_v3(efa->v3->no, efa->n);
}
/* following Mesh convention; we use vertex coordinate itself for normal in this case */
More information about the Bf-codereview
mailing list