Graphics processing (d) Graphic processing of grid editing-siggraph 2004_ based on gradient field

Source: Internet
Author: User
Tags scalar

Based on the gradient field of grid editing, the corresponding paper is "mesh Editing with poisson-based gradient field manipulation", Siggraph 2004, a paper, This paper and Laplace-based mesh deformation method, collectively known as the mesh deformation algorithm based on the differential domain, paper in essence the Final Solution formula is the same as the Laplace mesh deformation method, because it is deduced by the principle of the Poisson gradient field, The ingenious part of the algorithm is that it takes each dimension of the vertex (x,y,z) as a scalar field.

This article paper related to the concept: divergence, gradient field, scalar field, vector field, and so looks very difficult things, to tell the truth, for this article paper because the Internet can not find the source code, I put this paper read many times, before the code written out. Learning this paper is the first time I learned the relevant knowledge of vector field, vector field in three-dimensional algorithm is very important, at the same time give me the feeling is not generally difficult, I read a lot about the scalar field, vector field related knowledge theory, just feel slowly understanding.

I. Related theories

Mathematical Poisson's equation:


where F represents a scalar field, W represents a gradient field.

Discretization of differential operators on triangular mesh surfaces (referenced from sketched Poisson grid editor):

Given a piecewise linear scalar field F (v) =fi*φi (v) defined on a mesh surface, where V is any point on the mesh surface, FI is the function value of the scalar field at the Vertex VI of the mesh surface, and the φi (*) is a piecewise linear basis function, which takes a value of 1 at the Vertex vi and a value of 0 at the remaining vertices. We have a scalar field F corresponding to the gradient operator


The ▽φi (*) has a value of not 0 on the adjacent triangle of the vertex only, and because the φi (*) is piecewise linear, ▽φi (*) is a piecewise constant function on each adjacent triangle. From a geometric point of view, you can easily give
The definition of a ▽φi (*) on a triangle T = (VI,VJ, VK):

Wherein, the R90 represents the round triangle vector NT rotation 90 degrees, at is the area of the triangle. Similarly, given the vector field W of piecewise constant defined on a triangular mesh surface, we define the divergence of W at Vertex VI to be:

According to the definition of gradient operator and divergence operator, the Laplace operator of the scalar field F at vertex VI can be deduced at the end of the mesh surface:



This article is paper by the cattle of Zhejiang Zhou Kun, finally, the algorithm is the same as the final formula of the Laplace grid editor, but its scalar field gives me a great revelation, this paper directly to the (x,y,z) of the x,y,z as a scalar field, and then the scalar field to obtain the gradient field, Finally, the divergence is obtained, then the mesh model is reconstructed by Poisson equation, and the mesh deformation is realized. To get a deeper understanding of Poisson's reconstruction, look at my other blog post. Image processing (12) image fusion (1) Seamless cloning clone-siggraph 2004

Second, the implementation of the algorithm

1, the gradient field of the source mesh surface is obtained, and the divergence of the gradient field is finally obtained.

[cpp]  View plain  copy//compute gradients for each vertex    void cscaledeformbrush::get_faces_gradient ()     {       int fn=m_basemesh->faces.size ();        m_basemesh->need_adjacentfaces ();           #pragma   omp parallel for       for  (int i=0;i<fn;i++)        {           trimesh::face &f =m_basemesh->faces[i];           vec vij=m_basemesh- >vertices[f[1]]-m_BaseMesh->vertices[f[0]];            vec vik=m_basemesh->vertices[f[2]]-m_basemesh->vertices[f[0]];            vec normalf=vij CROSS vik;        & nbsp;   float areaf=0.5f*len (normalf);            Normalize (normalf);           for  (int k=0;k<3;k + +)            {               m_face_gradient[i][k]=vec (0,0,0);               for  (int j=0;j<3;j++)                {                vec ei=m_basemesh->vertices[f[(j+2)%3]]-m_basemesh->vertices[f[(j+1)%3]];                vec gradient=float (m_ Basemesh->vertices[f[j]][k]*0.5f/areaf) * (Normalf cross ei);                m_face_gradient[i][k]=m_face_gradient[i][k]+gradient;                }               }       }     }   void  Cscaledeformbrush::compute_divergence ()    {            //compute vertex divergence        m_basemesh->need_adjacentfaces ();        int vn=m_basemesh->vertices.size ();        #pragma   omp parallel for       for  (int i=0;i<vn;i++)        {              for   (int j=0;j<3;j++)            {       &nbSp;        m_vertices[i]. vdivergence[j]=0.0f;           }            vector<int>&adjacentface=m_BaseMesh->adjacentfaces[i];            for  (Int j=0;j<adjacentface.size (); j + +)            {                TriMesh::Face &f=m_BaseMesh->faces[adjacentface[j]];                for  (int k=0;k<3;k+ +)                {                    if  (f[k]==i)    &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBsp;      {                        vec ei=m_basemesh->vertices[f[(k+2)% 3]]-m_basemesh->vertices[f[(k+1)%3]];                        vec e1=m_basemesh->vertices[f[(k+1)% 3]]-m_basemesh->vertices[f[k]];                        vec e2=m_basemesh->vertices[f[(k+2)%3]]-m_ basemesh->vertices[f[k]];                        double cot_angle1=cot_angle (E2,ei);                        double cot_angle2=cot_angle ( -1.0f*e1,ei);                        for  (int xyz=0;xyz<3;xyz++)                         {                            m_vertices[i]. vdivergence[xyz]+=0.5* (cot_angle1* (E1&NBSP;DOT&NBSP;M_FACE_GRADIENT[ADJACENTFACE[J]][XYZ)) +cot_angle2* (E2 &NBSP;DOT&NBSP;M_FACE_GRADIENT[ADJACENTFACE[J]][XYZ]);                        }                        break;    &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBsp;        }                }           }           }     }  //To calculate the cotangent value of the angle between v1 v2     Double cscaledeformbrush::cot_angle (vec v1,vec v2)    {        vec vivo=v1;       vec vjvo=v2;        double dotvector=vivo DOT vjvo;       dotvector=dotvector/ sqrt (Len2 (Vivo) *len2 (VJVO)-dotvector*dotvector);       return dotvector;   }  

2. To construct the coefficient of Poisson equation, matrix A, that is to calculate the Laplace matrix

[cpp]  View Plain  copy//adjacency vertex cotangent weight calculation    void cscaledeformbrush::cotangentweights (trimesh* Tmesh,int vindex,vector<double>&vweight,double &weightsum,bool bnormalize)// Calculate the respective Cottan weights    {          int neighbornumber= of the first order neighboring points Tmesh->neighbors[vindex].size ();       vweight.resize (NeighborNumber);        WeightSum=0;       vector<int>&neiv= tmesh->neighbors[vindex];       for  (int i=0;i<neighbornumber;i++ )        {           int j_ nei=neiv[i];           vector<int>tempnei;           co_neighbor (tmesh,vindex,j_nei,tempnei);            double cotsum=0.0;            for  (Int j=0;j<tempnei.size (); j + +)             {               vec vivo= tmesh->vertices[vindex]-tmesh->vertices[tempnei[j]];                vec vjvo=TMesh->vertices[j_nei]-TMesh->vertices[tempnei[j]];                double dotvector=vivo  DOT vjvo;                Dotvector=dotvector/sqrt (Len2 (Vivo) *len2 (VJVO)-dotvector*dotvector);                cotsum+=dotvector;            }   &NBsp;       vweight[i]=cotsum/2.0;            WeightSum+=vweight[i];       }           if  ( bNormalize )         {           for  (int k=0;k<neighbornumber;++k)            {                vweight[k]/=WeightSum;           }            WeightSum=1.0;        }  }     //Get the common adjacency vertex    Void cscaledeformbrush::co_neighbor of two vertices ( TRIMESH&NBSP;*TMESH,INT&NBSP;U_ID,INT&NBSP;V_ID,VECTOR&LT;INT&GT;&AMP;CO_NEIV)    {       &nbSp Tmesh->need_adjacentedges ();       vector<int>&u_id_ae=Tmesh-> adjancetedge[u_id];        int en=u_id_ae.size ();        Tedge Co_Edge;       for  (int i=0;i<en;i++)        {           Tedge  &ae=Tmesh->m_edges[u_id_ae[i]];           int  Opsi=ae.opposite_vertex (u_id);           if  (opsi==v_id)            {                Co_Edge=ae;                break;           }        }        for  (Int i=0;i<co_edge.m_adjacent_faces.size () i++)         {           TriMesh::Face  af=tmesh->faces[co_edge.m_adjacent_faces[i]];            for  (int j=0;j<3;j++)            {               if (af[j]!=u_id) && (af[j]!=v_id )                {                    co_neiv.push_back (AF [j]);                }            }       }  }  //Calculation of Laplace Matrix & Nbsp;  Void cscaledeformbrush::get_laplace_matrix ()    {        Int vn=m_basemesh->vertices.size ();       int count0=0;       vector<int>begin_n (VN);       for  (int i= 0;i<vn;i++)        {               begin_N[i]=count0;           count0+= M_basemesh->neighbors[i].size () +1;       }        typedef eigen::triplet<double> t;       std::vector<T>  tripletlist (count0);       for (int i=0;i<vn;i++)         {           vproperty & vi  = m_vertices[i];           tripletlist[begin_n[i]]=t (I,i,-vi. Vsumweight);           int nnbrs = vi. Vneighbors.size ();           for  (int k = &NBSP;0;K&LT;NNBRS;++K)             {                tripletlist[begin_n[i]+k+1]=t (vi. Vneighbors[k],i,vi. Vneiweight[k]);           }        }       m_laplace_matrix.resize (VN,VN);         m_laplace_matrix.setfromtriplets (Tripletlist.begin (),  tripletlist.end ());     }   
3, add the boundary constraint condition, and solve the Poisson equation, update the deformation result.

Live Update Functions:

[cpp]  View plain  copy void cscaledeformbrush::update_v_position ()    {    & Nbsp;  get_faces_gradient ()/gradient        int fn=m_BaseMesh-> Faces.size ();       if (!m_scaleface.empty ())         for  (int i=0;i<fn;i++)        {            if (M_scaleface[i])            {                for  (int j=0;j<3;j+ +)                {                    m_face_gradient[i][j ]=1.1f*m_face_gradient[i][j];                }               m_basemesh->faces[i]. beselect=false;           }        }       compute_divergence ()//divergence degree        if (!m _matricescholesky)//Build Laplace matrix        {            double a=m_laplace_matrix.coeff (0,0)  +1;            m_laplace_matrix.coeffref (0,0) =a;            m_MatricesCholesky=new Eigen::SimplicialCholesky<SparseMatrixType> (M_laplace_matrix);//Matrix decomposition        }       int vn=m_BaseMesh-> Vertices.size ();       for  (int i=0;i<3;i++)         {   &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;EIGEN::VECTORXD&NBSP;RHS_XYZ (VN);            for  (int j=0;j<vn;j++)             {                RHS_XYZ[J]=M_VERTICES[J]. vdivergence[i];//Equation Group Right            }            rhs_xyz[0]=rhs_xyz[0]+1.0f*m_BaseMesh->vertices[0][i];           eigen::vectorxd xyz=m_matricescholesky->solve (RHS_XYZ) ;/Solution Equation            for  (int j=0;j<vn;j++)             {                m_basemesh->vertices[j][i]=xyz[j];//Update Results            }       }       m_ Scaleface.clear ();       m_scaleface.resize (fn,false);        m_basemesh->normals.clear ();       m_basemesh->facenormal.clear ();     }  

Then let's take a look at the results of simple local edits implemented with this algorithm:


The above real time local scaling algorithm I am through another article paper "Differential-based Geometry and texture Editing with brushes" The idea realizes, this paper basically is copies "the Mesh Editing with poisson-based gradient field manipulation's idea, the only innovation is its real-time interaction design, because I am in order to achieve real-time scaling brush, so the idea of scaling is based on the differential-based Geometry and texture Editing with brushes to write code.


Above is using the above algorithm for simple real-time editing.

After this paper, there are subsequent algorithm adjustments, such as gradient direction adjustment, and mesh fusion, geometric texture transfer. The gradient direction adjustment is necessary to realize the feature-preserving deformation, so if you want to implement the complete algorithm, you need to adjust the gradient direction, this can refer to my blog post "based on the rotation invariant grid deformation." Here, I do not speak in detail direction adjustment, the direction adjusts has the specialized algorithm, paper many.

Notice: The deformation method based on gradient domain and Laplace mesh deformation algorithm, differential coordinates do not have the characteristics of rotation, in the deformation, the distortion of the surface details, the need for differential coordinates, or gradient direction to adjust to achieve the feature-preserving deformation, to achieve rotation invariant deformation, You can refer to my other blog post "mesh deformation based on rotational invariants" to achieve the same rotation characteristics.

This article address: http://blog.csdn.net/hjimce/article/details/46415291 Author: hjimce Contact qq:1393852684 More resources please pay attention to my blog: http://blog.csdn. NET/HJIMCE original article, reprint please keep the bank information

Reference documents:

1, "Mesh Editing with poisson-based gradient Field manipulation"

2, Differential grid processing technology

3. Sketch-type Poisson grid editing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.