三维模型顶点法向量和偏导数的计算方法

三角网格的边界条件是指三角网格顶点处的型值,法矢及顶点处沿边界方向的两个切矢。而除顶点处的型值外,其它条件一般都通过估算得到。这就要对顶点处的偏导数做出估计,估计的好坏直接影响到最终生成曲面的好坏,下面介绍一些常用的偏导估计方法。 1、凸组合方法 实际这种方法是通过与某一点相邻的三角形或全体三角形(空间)所在平面的法矢(或偏微商)作凸组合,来近似代替该点的法矢(或偏微商)。

CSDN的烂服务器啊!!!贴图贴不上!郁闷

详细的公式见   图片-》“我收藏的美女” 中的公式图片

我采用little法的源代码如下

 //这里的渲染三角网 是计算三角网各个顶点的法向量
//顶点法向量是使用该顶点所有三角形法向量平均值 或者凸组合方法中的little法
 //平均值法就是计算各个三角面的法向量的平均值
 //little法就是按照三角形各个点的距离来加权

 //另外还要计算顶点的偏导数 同样用little法
 
 C3DdVector cur_normal, normal, total_normal;      //计算后的法向量
 int index1,index2,index3;                   //当前三角形的邻接三角形
 int i,j;
 C3DdVector *p_Normal = new C3DdVector[n_ptcount];   // 点的法向量
 double * p_fx = new double[n_ptcount];              // 点的偏导数
 double * p_fy = new double[n_ptcount];              // 点的偏导数
 double * p_count = new double[n_ptcount];           //临时存放每一点的权值
 double  w, l1,l2;                                   //little法中的权值
   
    //计算顶点法向量
 for( i=0; i<n_ptcount; i++)
 {
      p_Normal[i].SetVector(0,0,0);
   p_count[i] = 0;
   p_fx[i] = 0;
   p_fy[i] = 0;
 }
  
     for( j=0; j<n_tricount; j++ )
  {
       m_trinet[j].CalcNormal();
    index1 = m_trinet[j].x;
    index2 = m_trinet[j].y;
    index3 = m_trinet[j].z;
      
    l1 = m_trinet[j].m_pVertex[0].Distance(m_trinet[j].m_pVertex[1]);
    l2 = m_trinet[j].m_pVertex[0].Distance(m_trinet[j].m_pVertex[2]);
    w = l1*l1*l2*l2;
  
   
    if(w>1.0e-8)
    {
    p_Normal[index1].vx += m_trinet[j].normal.vx/w;
    p_Normal[index1].vy += m_trinet[j].normal.vy/w;
    p_Normal[index1].vz += m_trinet[j].normal.vz/w;
    p_count[index1] += 1.0/w ;
    p_fx[index1] += -m_trinet[j].normal.vx/(m_trinet[j].normal.vz*w);
    p_fy[index1] += -m_trinet[j].normal.vy/(m_trinet[j].normal.vz*w);
    }

    l1 = m_trinet[j].m_pVertex[1].Distance(m_trinet[j].m_pVertex[0]);
    l2 = m_trinet[j].m_pVertex[1].Distance(m_trinet[j].m_pVertex[2]);
    w = l1*l1*l2*l2;
   
    if(w>1.0e-8)
    {
    p_Normal[index2].vx += m_trinet[j].normal.vx/w;
    p_Normal[index2].vy += m_trinet[j].normal.vy/w;
    p_Normal[index2].vz += m_trinet[j].normal.vz/w;
    p_count[index2] += 1.0/w;
    p_fx[index2] += -m_trinet[j].normal.vx/(m_trinet[j].normal.vz*w);
    p_fy[index2] += -m_trinet[j].normal.vy/(m_trinet[j].normal.vz*w);
    }

    l1 = m_trinet[j].m_pVertex[2].Distance(m_trinet[j].m_pVertex[0]);
    l2 = m_trinet[j].m_pVertex[2].Distance(m_trinet[j].m_pVertex[1]);
    w = l1*l1 + l2*l2;
  
    if(w>1.0e-8)
    {
      p_Normal[index3].vx += m_trinet[j].normal.vx/w;
      p_Normal[index3].vy += m_trinet[j].normal.vy/w;
      p_Normal[index3].vz += m_trinet[j].normal.vz/w;
      p_count[index3] += 1.0/w;
      p_fx[index3] += -m_trinet[j].normal.vx/(m_trinet[j].normal.vz*w);
      p_fy[index3] += -m_trinet[j].normal.vy/(m_trinet[j].normal.vz*w);
  
    }
   }

// CStdioFile fp;
// CFileException e;
// fp.Open("computer_normal.txt", CFile::modeCreate|CFile::modeWrite,&e);
// CString aline;
    p_Normal[0].SetVector(0,0,-p_count[0]);
 p_fx[0] = 0;
    p_fy[0] = 0;
 for(i=0; i<n_ptcount; i++)
 {
  if(p_count[i])
  {
   p_Normal[i].vx /= p_count[i];
      p_Normal[i].vy /= p_count[i];
      p_Normal[i].vz /= p_count[i];
   p_fx[i] /= p_count[i];
            p_fy[i] /= p_count[i];
      p_Normal[i].Normalize(1.0);
   m_sPoint[i].normal = p_Normal[i];
   m_sPoint[i].fx = p_fx[i];
   m_sPoint[i].fy = p_fy[i];
  // C3DdPoint tttt = m_sPoint[i].GetPoint();
   TRACE("/nPoint:%f %f %f ",m_sPoint[i].GetPoint().x, (m_sPoint[i].GetPoint()).y, (m_sPoint[i].GetPoint()).z );
         TRACE("/nfxy:  %f %f",    m_sPoint[i].fx,m_sPoint[i].fy);
  }
       
      //  aline.Format("point %d %f %f %f Normal %f %f %f/n",i,m_sPoint[i].x, m_sPoint[i].y, m_sPoint[i].z,
      //   p_Normal[i].vx, p_Normal[i].vy, p_Normal[i].vz );
      //        fp.WriteString(aline);
     
  /*TRACE("/npoint %d %f %f %f /nNormal %f %f %f",i,
     m_sPoint[i].x, m_sPoint[i].y, m_sPoint[i].z,
     p_Normal[i].vx, p_Normal[i].vy, p_Normal[i].vz );*/
 }
  //   fp.Close();

 //把顶点法向量赋予三角形中的顶点
 for(j=0; j<n_tricount; j++)
 {
       index1 = m_trinet[j].x;
    m_trinet[j].m_pNormal[0] = p_Normal[index1];
    m_trinet[j].m_fXYZ[0].x  = p_fx[index1];
    m_trinet[j].m_fXYZ[0].y  = p_fy[index1];


    index2 = m_trinet[j].y;
    m_trinet[j].m_pNormal[1] = p_Normal[index2];
    m_trinet[j].m_fXYZ[1].x  = p_fx[index2];
    m_trinet[j].m_fXYZ[1].y  = p_fy[index2];

    index3 = m_trinet[j].z;
    m_trinet[j].m_pNormal[2] = p_Normal[index3];
    m_trinet[j].m_fXYZ[2].x  = p_fx[index3];
    m_trinet[j].m_fXYZ[2].y  = p_fy[index3];
 }
 delete p_Normal;

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值