// Calculates the vertex normals corresponding to the smoothing group // settings for each face of a mesh. // // \param mesh A pointer to the mesh to calculate the normals for. // \param normals A pointer to a buffer to store the calculated // normals. The buffer must have the size: // 3*3*sizeof(float)*mesh.nfaces. // // To allocate the normal buffer do for example the following: // \code // Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh.nfaces); // \endcode // // To access the normal of the i-th vertex of the j-th face do the // following: // \code // normals[3*j+i] // \endcode public static void lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh mesh, float[][] normals) { if (mesh.nfaces == 0) { return; } Lib3dsFaces[] fl = new Lib3dsFaces[mesh.nvertices]; Lib3dsFaces[] fa = new Lib3dsFaces[3 * mesh.nfaces]; for (int i = 0; i < fa.Length; i++) { fa[i] = new Lib3dsFaces(); } for (int i = 0; i < mesh.nfaces; i++) { for (int j = 0; j < 3; j++) { Lib3dsFaces l = fa[3 * i + j]; float[] p = new float[3], q = new float[3], n = new float[3]; float len, weight; l.index = i; l.next = fl[mesh.faces[i].index[j]]; fl[mesh.faces[i].index[j]] = l; lib3ds_vector_sub(p, mesh.vertices[mesh.faces[i].index[j < 2?j + 1:0]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_sub(q, mesh.vertices[mesh.faces[i].index[j > 0?j - 1:2]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_cross(n, p, q); len = lib3ds_vector_length(n); if (len > 0) { weight = (float)Math.Atan2(len, lib3ds_vector_dot(p, q)); lib3ds_vector_scalar_mul(l.normal, n, weight / len); } else { lib3ds_vector_zero(l.normal); } } } for (int i = 0; i < mesh.nfaces; i++) { Lib3dsFace f = mesh.faces[i]; for (int j = 0; j < 3; j++) { float[] n = new float[3]; Lib3dsFaces p; Lib3dsFace pf; Debug.Assert(mesh.faces[i].index[j] < mesh.nvertices); if (f.smoothing_group != 0) { uint smoothing_group = f.smoothing_group; lib3ds_vector_zero(n); for (p = fl[mesh.faces[i].index[j]]; p != null; p = p.next) { pf = mesh.faces[p.index]; if ((pf.smoothing_group & f.smoothing_group) != 0) { smoothing_group |= pf.smoothing_group; } } for (p = fl[mesh.faces[i].index[j]]; p != null; p = p.next) { pf = mesh.faces[p.index]; if ((smoothing_group & pf.smoothing_group) != 0) { lib3ds_vector_add(n, n, p.normal); } } } else { lib3ds_vector_copy(n, fa[3 * i + j].normal); } lib3ds_vector_normalize(n); lib3ds_vector_copy(normals[3 * i + j], n); } } }
// Calculates the vertex normals corresponding to the smoothing group // settings for each face of a mesh. // // \param mesh A pointer to the mesh to calculate the normals for. // \param normals A pointer to a buffer to store the calculated // normals. The buffer must have the size: // 3*3*sizeof(float)*mesh.nfaces. // // To allocate the normal buffer do for example the following: // \code // Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh.nfaces); // \endcode // // To access the normal of the i-th vertex of the j-th face do the // following: // \code // normals[3*j+i] // \endcode public static void lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh mesh, float[][] normals) { if(mesh.nfaces==0) return; Lib3dsFaces[] fl=new Lib3dsFaces[mesh.nvertices]; Lib3dsFaces[] fa=new Lib3dsFaces[3*mesh.nfaces]; for(int i=0; i<fa.Length; i++) fa[i]=new Lib3dsFaces(); for(int i=0; i<mesh.nfaces; i++) { for(int j=0; j<3; j++) { Lib3dsFaces l=fa[3*i+j]; float[] p=new float[3], q=new float[3], n=new float[3]; float len, weight; l.index=i; l.next=fl[mesh.faces[i].index[j]]; fl[mesh.faces[i].index[j]]=l; lib3ds_vector_sub(p, mesh.vertices[mesh.faces[i].index[j<2?j+1:0]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_sub(q, mesh.vertices[mesh.faces[i].index[j>0?j-1:2]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_cross(n, p, q); len=lib3ds_vector_length(n); if(len>0) { weight=(float)Math.Atan2(len, lib3ds_vector_dot(p, q)); lib3ds_vector_scalar_mul(l.normal, n, weight/len); } else lib3ds_vector_zero(l.normal); } } for(int i=0; i<mesh.nfaces; i++) { Lib3dsFace f=mesh.faces[i]; for(int j=0; j<3; j++) { float[] n=new float[3]; Lib3dsFaces p; Lib3dsFace pf; Debug.Assert(mesh.faces[i].index[j]<mesh.nvertices); if(f.smoothing_group!=0) { uint smoothing_group=f.smoothing_group; lib3ds_vector_zero(n); for(p=fl[mesh.faces[i].index[j]]; p!=null; p=p.next) { pf=mesh.faces[p.index]; if((pf.smoothing_group&f.smoothing_group)!=0) smoothing_group|=pf.smoothing_group; } for(p=fl[mesh.faces[i].index[j]]; p!=null; p=p.next) { pf=mesh.faces[p.index]; if((smoothing_group&pf.smoothing_group)!=0) lib3ds_vector_add(n, n, p.normal); } } else lib3ds_vector_copy(n, fa[3*i+j].normal); lib3ds_vector_normalize(n); lib3ds_vector_copy(normals[3*i+j], n); } } }