zoukankan      html  css  js  c++  java
  • 解决地形生成各方块边界法线不统一的问题

    如图所示,未处理边界法线的效果,法线不统一生成类似分界线的效果,需要统一相邻方块边界相接处的法线。

    处理过后效果如图所示:

    假设地图为4x4的方格,每格的分段为3(每条边4个顶点)

    (a).为地图四角的小格的某些参考顶点赋值

    if (size_z >= 2)
    {
    mapdata[0, 0].normals[ul] += mapdata[0, 1].normals[bl];//左下小格提供其左上和左下的点做参考,之所以是2个,是按照数组遍历顺序
    mapdata[size_x - 1, 0].normals[ur] += mapdata[size_x - 1, 1].normals[br];//右下小格提供右上的点
    }
    if (size_x >= 2)
    {
    mapdata[0, 0].normals[br] += mapdata[1, 0].normals[bl];
    mapdata[0, size_z - 1].normals[ur] += mapdata[1, size_z - 1].normals[ul];//左上小格提供右上的点
    }

    根据这些格子的参考顶点向上,向右延伸

     1  for (int i = 0; i < size_z; i++)
     2             for (int j = 0; j < size_x; j++)
     3             {
     4                 if (i == 0 && j > 0)//下面一行
     5                 {
     6                     if (j < size_x - 1)
     7                         mapdata[j, i].normals[br] += mapdata[j + 1, i].normals[bl];//右下
     8 
     9                     mapdata[j, i].normals[bl] = mapdata[j - 1, i].normals[br];//左下
    10                 }
    11 
    12                 if (j == 0 && i > 0)//左面一行
    13                 {
    14                     if (i < size_z - 1)
    15                         mapdata[j, i].normals[ul] += mapdata[j, i + 1].normals[bl];//左上
    16 
    17                     mapdata[j, i].normals[bl] = mapdata[j, i - 1].normals[ul];//左下
    18                 }
    19 
    20                 if (j == size_x - 1 && i > 0)//右面一行
    21                 {
    22                     if (i < size_z - 1)
    23                         mapdata[j, i].normals[ur] += mapdata[j, i + 1].normals[br];//右上
    24                     mapdata[j, i].normals[br] = mapdata[j, i - 1].normals[ur];//右下
    25                 }
    26 
    27                 if (i == size_z - 1 && j > 0)//上面一行
    28                 {
    29                     if (j < size_x - 1)
    30                         mapdata[j, i].normals[ur] += mapdata[j + 1, i].normals[ul];//右上
    31                     mapdata[j, i].normals[ul] += mapdata[j - 1, i].normals[ur];//左上
    32                 }
    33 }
    34 }
    边界最外侧顶点延伸

     (b).为空余的中间部分各小格边角顶点法线赋值

    如图所示,依次赋值。

     1 for (int i = 0; i < size_z; i++)
     2  for (int j = 0; j < size_x; j++){
    3   if (j < size_x - 1 && i < size_z - 1)//右上角赋值,作为底下其他赋值的基础 4   mapdata[j, i].normals[ur] = (mapdata[j, i].normals[ur] + mapdata[j + 1, i].normals[ul] + mapdata[j, i + 1].normals[br] + mapdata[j + 1, i + 1].normals[bl]).normalized;//四个三角面的法线向量归一化 5   if (j >=1 && i >=1)//左下角赋值,取前,必须按照数组顺序来初始化 6   mapdata[j, i].normals[bl] = mapdata[j - 1, i - 1].normals[ur]; 7   if (j < size_x - 1 && i >=1)//右下角赋值,取前一行 8   mapdata[j, i].normals[br] = mapdata[j, i - 1].normals[ur]; 9   if (j >=1 && i < size_z - 1)//左上角赋值,取前一个 10   mapdata[j, i].normals[ul] = mapdata[j - 1, i].normals[ur]; 11 }

    (c).初始化每格非四角处的顶点。数组的遍历顺序是从左往右,从底部往上,边界的各对应方向的顶点等于原值

    若AB左右相邻:A格的右法线=A格右法线+B格左法线,B格左法线=A格右法线(已初始化)

    若AB下上相接:A格的上法线=A格上法线+B格下法线,B格下法线=A格上法线(已初始化)

    代码如下:

     1 for (int i = 0; i < size_z; i++)
     2   for (int j = 0; j < size_x; j++)
     3 {
     4     for (int m = 1; m < cell_segment; m++)//cell_segment是分段数,边上顶点数为cell_segment+1,这里实际是边上顶点数-1
     5     {
     6        up = ((cell_segment + 1) * (cell_segment) + m);
     7        bottom = m;
     8        left = m * (cell_segment + 1);
     9        right = (m + 1) * (cell_segment + 1) - 1;
    10 
    11        mapdata[j, i].normals[left] = j - 1 < 0 ? mapdata[j, i].normals[left] : mapdata[j - 1, i].normals[right].normalized;//
    12        mapdata[j, i].normals[bottom] = i - 1 < 0 ? mapdata[j, i].normals[bottom] : mapdata[j, i - 1].normals[up].normalized;//
    13        mapdata[j, i].normals[right] = j + 1 >= size_x ? mapdata[j, i].normals[right] : (mapdata[j, i].normals[right] + mapdata[j + 1, i].normals[left]).normalized;//
    14         mapdata[j, i].normals[up] = i + 1 >= size_z ? mapdata[j, i].normals[up] : (mapdata[j, i].normals[up] + mapdata[j, i + 1].normals[bottom]).normalized;//
    15     }
    16 }

    经历a,b,c步骤,所有格子的边界法线统一,以下是函数完整代码:

     1 public void SetNormals()
     2     {
     3         int size_x = Mathf.FloorToInt((float)terrain_size.x / cell_size);
     4         int size_z = Mathf.FloorToInt((float)terrain_size.y / cell_size);
     5         int bl, br, ul, ur;//左下,右下,左上,右上
     6         int up, bottom, right, left;
     7 
     8         bl = 0;
     9         br = cell_segment;
    10         ul = (cell_segment + 1) * (cell_segment);
    11         ur = (cell_segment + 1) * (cell_segment + 1) - 1;
    12 
    13         if (size_z >= 2)
    14         {
    15             mapdata[0, 0].normals[ul] += mapdata[0, 1].normals[bl];//左下小格提供其左上和左下的点做参考,之所以是2个,是按照数组遍历顺序
    16             mapdata[size_x - 1, 0].normals[ur] += mapdata[size_x - 1, 1].normals[br];//右下小格提供右上的点
    17         }
    18         if (size_x >= 2)
    19         {
    20             mapdata[0, 0].normals[br] += mapdata[1, 0].normals[bl];
    21             mapdata[0, size_z - 1].normals[ur] += mapdata[1, size_z - 1].normals[ul];//左上小格提供右上的点
    22         }
    23 
    24         for (int i = 0; i < size_z; i++)
    25             for (int j = 0; j < size_x; j++)
    26             {
    27                 if (i == 0 && j > 0)//下面一行
    28                 {
    29                     if (j < size_x - 1)
    30                         mapdata[j, i].normals[br] += mapdata[j + 1, i].normals[bl];//右下
    31 
    32                     mapdata[j, i].normals[bl] = mapdata[j - 1, i].normals[br];//左下
    33                 }
    34 
    35                 if (j == 0 && i > 0)//左面一行
    36                 {
    37                     if (i < size_z - 1)
    38                         mapdata[j, i].normals[ul] += mapdata[j, i + 1].normals[bl];//左上
    39 
    40                     mapdata[j, i].normals[bl] = mapdata[j, i - 1].normals[ul];//左下
    41                 }
    42 
    43                 if (j == size_x - 1 && i > 0)//右面一行
    44                 {
    45                     if (i < size_z - 1)
    46                         mapdata[j, i].normals[ur] += mapdata[j, i + 1].normals[br];//右上
    47                     mapdata[j, i].normals[br] = mapdata[j, i - 1].normals[ur];//右下
    48                 }
    49 
    50                 if (i == size_z - 1 && j > 0)//上面一行
    51                 {
    52                     if (j < size_x - 1)
    53                         mapdata[j, i].normals[ur] += mapdata[j + 1, i].normals[ul];//右上
    54                     mapdata[j, i].normals[ul] += mapdata[j - 1, i].normals[ur];//左上
    55                 }
    56 
    57                 if (j < size_x - 1 && i < size_z - 1)//右上角赋值,作为底下其他赋值的基础
    58                     mapdata[j, i].normals[ur] = (mapdata[j, i].normals[ur] + mapdata[j + 1, i].normals[ul] + mapdata[j, i + 1].normals[br] + mapdata[j + 1, i + 1].normals[bl]).normalized;//四个三角面的法线向量归一化
    59                 if (j >= 1 && i >= 1)//左下角赋值,取前,必须按照数组顺序来初始化
    60                     mapdata[j, i].normals[bl] = mapdata[j - 1, i - 1].normals[ur];
    61                 if (j < size_x - 1 && i >= 1)//右下角赋值,取前一行
    62                     mapdata[j, i].normals[br] = mapdata[j, i - 1].normals[ur];
    63                 if (j >= 1 && i < size_z - 1)//左上角赋值,取前一个
    64                     mapdata[j, i].normals[ul] = mapdata[j - 1, i].normals[ur];
    65 
    66                 for (int m = 1; m < cell_segment; m++)//cell_segment是分段数,边上顶点数为cell_segment+1,这里实际是边上顶点数-1
    67                 {
    68                     up = ((cell_segment + 1) * (cell_segment) + m);
    69                     bottom = m;
    70                     left = m * (cell_segment + 1);
    71                     right = (m + 1) * (cell_segment + 1) - 1;
    72 
    73                     mapdata[j, i].normals[left] = j - 1 < 0 ? mapdata[j, i].normals[left] : mapdata[j - 1, i].normals[right].normalized;//
    74                     mapdata[j, i].normals[bottom] = i - 1 < 0 ? mapdata[j, i].normals[bottom] : mapdata[j, i - 1].normals[up].normalized;//
    75                     mapdata[j, i].normals[right] = j + 1 >= size_x ? mapdata[j, i].normals[right] : (mapdata[j, i].normals[right] + mapdata[j + 1, i].normals[left]).normalized;//
    76                     mapdata[j, i].normals[up] = i + 1 >= size_z ? mapdata[j, i].normals[up] : (mapdata[j, i].normals[up] + mapdata[j, i + 1].normals[bottom]).normalized;//
    77                 }
    78                 mapdata[j, i].ReviseNormals();//将该格法线重新赋值
    79             }
    80     }
    完整函数

     工程文件:http://files.cnblogs.com/files/luxishi/BuildMap_mesh.zip(地图为1x1时有bug,在上面a处已修正)

  • 相关阅读:
    在Salesforce中实现对Object的增删改查操作
    在Salesforce中通过编写C#程序调用dataloadercliq的bat文件取触发调用data loader来批量处理数据
    在Salesforce中通过dataloadercliq调用data loader来批量处理数据
    【LeetCode】189. Rotate Array
    【LeetCode】190. Reverse Bits
    【LeetCode】191. Number of 1 Bits
    【C++】不要想当然使用resize
    【LeetCode】174. Dungeon Game
    【LeetCode】Largest Number
    【DeepLearning】Exercise:Convolution and Pooling
  • 原文地址:https://www.cnblogs.com/luxishi/p/6518518.html
Copyright © 2011-2022 走看看