Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,635 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Windows;
|
||||
namespace XGame
|
||||
{
|
||||
class TerrainBlock
|
||||
{
|
||||
public Color32 m_BaseMapIndex;
|
||||
public Color32[] m_MapIndex;
|
||||
public Color[] m_MapMix;
|
||||
public float[] m_Height;
|
||||
|
||||
}
|
||||
class TerrainObject
|
||||
{
|
||||
//m_BlockGridSize = 32
|
||||
//lv0 512*512 = (32*32单块) * 16 * 16 (总共256块)
|
||||
//lv1 256*256 = (32*32单块) * 8 * 8 (64块)
|
||||
//lv2 128*128 = (32*32单块) * 4 * 4 (16块)
|
||||
//lv3 64*64 = (32*32单块) * 2 * 2 (4块)
|
||||
class MeshObj
|
||||
{
|
||||
public GameObject m_Object;
|
||||
public Mesh m_Mesh;
|
||||
|
||||
public MeshObj[] m_MeshSubObj;//四叉分割 32*32 64*64 128*128 256*256 512*512 (1024*1024)
|
||||
}
|
||||
|
||||
string[] m_strBaseMapList;
|
||||
// 预先定义 16 种颜色
|
||||
static Color[] m_Colors = new Color[]
|
||||
{
|
||||
new Color(255, 0, 0), // 红色
|
||||
new Color(255, 128, 0), // 橙色
|
||||
new Color(255, 255, 0), // 黄色
|
||||
new Color(128, 255, 0), // 淡绿色
|
||||
new Color(0, 255, 0), // 绿色
|
||||
new Color(0, 255, 128), // 青色
|
||||
new Color(0, 255, 255), // 蓝绿色
|
||||
new Color(0, 128, 255), // 淡蓝色
|
||||
new Color(0, 0, 255), // 蓝色
|
||||
new Color(128, 0, 255), // 紫色
|
||||
new Color(255, 0, 255), // 粉红色
|
||||
new Color(255, 0, 128), // 桃红色
|
||||
new Color(128, 128, 128), // 灰色
|
||||
new Color(192, 192, 192), // 淡灰色
|
||||
new Color(255, 255, 255), // 白色
|
||||
new Color(0, 0, 0), // 黑色
|
||||
};
|
||||
|
||||
GameObject m_GameObject;
|
||||
Transform m_Transform;
|
||||
MeshObj m_Top;
|
||||
MeshObj[] m_BlockMeshObjList;
|
||||
|
||||
TerrainBlock[] m_TerrainBlock;
|
||||
Texture2D[] m_BaseMapTexture;
|
||||
Texture2D[] m_NormalMapTexture;
|
||||
Texture2D m_ControlTexture;
|
||||
|
||||
Material m_mtlTerrain;
|
||||
|
||||
string m_Name;//xxxzzz.grd
|
||||
|
||||
static Color32 m_Index;// = new int[4];
|
||||
static Color m_Degreed;// = new float[4];
|
||||
static Color[] m_nearestColors = new Color[4];
|
||||
|
||||
public static float m_HeightScale = 20.0f;
|
||||
public static float m_UVScale = 4.0f;//1-32-贴图大小
|
||||
public static int m_BlockGridSize = 32;//32*32
|
||||
|
||||
|
||||
void SetCorlorBase(Color[] colors)
|
||||
{
|
||||
m_Colors = colors;
|
||||
}
|
||||
|
||||
//通过heightMap生成
|
||||
public IEnumerator CreateGroundObjectFromPic(int xPos, int zPos, string heightMap, string mixMap, string[] baseMap, string[] normalMap, Transform trParent )
|
||||
{
|
||||
Debug.Log("CreateGroundObjectFromPic");
|
||||
if (baseMap.Length != normalMap.Length)
|
||||
{
|
||||
Debug.Log("baseMap Count Must = normalMap Count");
|
||||
yield break;
|
||||
}
|
||||
if (baseMap.Length < 4)
|
||||
{
|
||||
Debug.Log("baseMap Must >= 4");
|
||||
yield break;
|
||||
}
|
||||
DateTime oriTime = DateTime.Now;
|
||||
yield return XResLoader.coLoadAllRes(new string[] { "res/scene/ground/mat/Terrain.mat" }, typeof(Material), objs =>
|
||||
{
|
||||
Debug.Log("coLoadAllRes Terrain.mat finish");
|
||||
if (objs != null && objs[0] != null)
|
||||
{
|
||||
m_mtlTerrain = objs[0] as Material;
|
||||
}
|
||||
|
||||
});
|
||||
if(m_mtlTerrain == null)
|
||||
{
|
||||
Debug.Log("Terrian Mtl Load Failed : res/scene/ground/mat/Terrain.mat");
|
||||
yield break;
|
||||
}
|
||||
m_BaseMapTexture = new Texture2D[baseMap.Length];
|
||||
m_NormalMapTexture = new Texture2D[normalMap.Length];
|
||||
Texture2D texture = null;
|
||||
Texture2D mixTexture = null;
|
||||
//byte[] imageData;
|
||||
//texture = new Texture2D(2, 2);
|
||||
//imageData = File.ReadAllBytes(mixMap);
|
||||
//yield return XResLoader.LoadRes(mixMap, typeof(Texture2D), objs =>
|
||||
yield return XResLoader.coLoadAllRes(new string[] { mixMap }, typeof(Texture2D), objs =>
|
||||
{
|
||||
if (objs != null)
|
||||
{
|
||||
mixTexture = objs[0] as Texture2D;
|
||||
if (mixTexture.width != mixTexture.height)
|
||||
{
|
||||
Debug.Log("Height Must == Width");
|
||||
}
|
||||
if (!mixTexture.isReadable)
|
||||
{
|
||||
Debug.Log("mixTexture.isReadable false");
|
||||
#if UNITY_EDITOR
|
||||
string texturePath = UnityEditor.AssetDatabase.GetAssetPath(mixTexture);
|
||||
UnityEditor.TextureImporter textureImporter = (UnityEditor.TextureImporter)UnityEditor.AssetImporter.GetAtPath(texturePath);
|
||||
textureImporter.isReadable = true;
|
||||
UnityEditor.AssetDatabase.ImportAsset(texturePath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
});
|
||||
if(mixTexture == null)
|
||||
yield break;
|
||||
|
||||
//texture.LoadImage(imageData);
|
||||
Texture2D texHeight = null;// = new Texture2D(2, 2);
|
||||
//imageData = File.ReadAllBytes(heightMap);
|
||||
//texHeight.LoadImage(imageData);
|
||||
//yield return XResLoader.LoadRes(heightMap, typeof(Texture2D), objs =>
|
||||
yield return XResLoader.coLoadAllRes(new string[] { heightMap }, typeof(Texture2D), objs =>
|
||||
{
|
||||
if (objs != null)
|
||||
{
|
||||
texHeight = objs[0] as Texture2D;
|
||||
if (texHeight.width != mixTexture.width || texHeight.height != mixTexture.height)
|
||||
{//比较两个图的大小
|
||||
Debug.Log("HeightMap Size != MixMap Size");
|
||||
}
|
||||
if (!texHeight.isReadable)
|
||||
{
|
||||
Debug.Log("texHeight.isReadable false");
|
||||
#if UNITY_EDITOR
|
||||
string texturePath = UnityEditor.AssetDatabase.GetAssetPath(texHeight);
|
||||
UnityEditor.TextureImporter textureImporter = (UnityEditor.TextureImporter)UnityEditor.AssetImporter.GetAtPath(texturePath);
|
||||
textureImporter.isReadable = true;
|
||||
UnityEditor.AssetDatabase.ImportAsset(texturePath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
});
|
||||
if (texHeight == null)
|
||||
yield break;
|
||||
|
||||
m_GameObject = new GameObject($"Terrain{xPos}{zPos}");
|
||||
m_Transform = m_GameObject.transform;
|
||||
m_Transform.SetParent(trParent);
|
||||
m_Transform.position = new Vector3(xPos, 0, zPos);
|
||||
m_strBaseMapList = baseMap;
|
||||
|
||||
//baseMap列表生成m_Colors列表
|
||||
m_Colors = new Color[baseMap.Length];
|
||||
Color totalColor = Color.black;
|
||||
int pixelCount = 0;
|
||||
Debug.Log("baseMap Load");
|
||||
//XResLoader.LoadRes(baseMap, typeof(Texture2D), objs=>
|
||||
yield return XResLoader.coLoadAllRes(baseMap, typeof(Texture2D), objs =>
|
||||
{
|
||||
Debug.Log($"baseMap load {objs.Length} ");
|
||||
for (int i = 0; i < objs.Length; ++i)
|
||||
{
|
||||
if (objs[i] != null)
|
||||
m_BaseMapTexture[i] = objs[i] as Texture2D;
|
||||
else
|
||||
{
|
||||
Debug.Log($"m_BaseMapTexture {normalMap[i]} Failed");
|
||||
}
|
||||
}
|
||||
});
|
||||
Debug.Log("normalMap Load");
|
||||
yield return XResLoader.coLoadAllRes(normalMap, typeof(Texture2D), objs =>
|
||||
{
|
||||
Debug.Log($"normalMap load {objs.Length} ");
|
||||
for (int i = 0; i < objs.Length; ++i)
|
||||
{
|
||||
if (objs[i] != null)
|
||||
m_NormalMapTexture[i] = objs[i] as Texture2D;
|
||||
else
|
||||
{
|
||||
Debug.Log($"normalMap {normalMap[i]} Failed");
|
||||
}
|
||||
}
|
||||
});
|
||||
Debug.Log($"m_BaseMapTexture Color {m_BaseMapTexture.Length}");
|
||||
for (int i = 0; i < m_BaseMapTexture.Length; ++i)
|
||||
{
|
||||
texture = m_BaseMapTexture[i];
|
||||
if (texture == null)
|
||||
{
|
||||
Debug.Log($"texture {i} == null");
|
||||
continue;
|
||||
}
|
||||
if (!texture.isReadable)
|
||||
{
|
||||
Debug.Log($"texture.isReadable {texture.name} Failed");
|
||||
#if UNITY_EDITOR
|
||||
string texturePath = UnityEditor.AssetDatabase.GetAssetPath(texture);
|
||||
UnityEditor.TextureImporter textureImporter = (UnityEditor.TextureImporter)UnityEditor.AssetImporter.GetAtPath(texturePath);
|
||||
textureImporter.isReadable = true;
|
||||
UnityEditor.AssetDatabase.ImportAsset(texturePath);
|
||||
#endif
|
||||
}
|
||||
for (int j = 0; j < texture.width; j = j + 4)
|
||||
{
|
||||
for (int k = 0; k < texture.height; k = k + 4)
|
||||
{
|
||||
Color pixelColor = texture.GetPixel(j, k);
|
||||
totalColor += pixelColor;
|
||||
pixelCount++;
|
||||
}
|
||||
}
|
||||
// 计算平均颜色
|
||||
m_Colors[i] = totalColor / pixelCount;
|
||||
}
|
||||
Debug.Log($"Color List OK {(DateTime.Now - oriTime).TotalMilliseconds}");
|
||||
|
||||
//mixMap rgba决定此点是哪四个basemap且分别是多少混合比例
|
||||
//mix[513*513][4](index, alpha), 32 * 32 缩减到4种地形(g1 g2 g3 g4),
|
||||
//0-32 33-64 (33列需要特殊处理)
|
||||
//相邻区块如果没有相同的就把最小那个改为主块的g1
|
||||
//读取32*32格子关联边的数据提取两个最大的(g1 g2),然后强设置进去只有两种alpha,
|
||||
//中心点设置为唯一颜色(最大g1)
|
||||
//边界混合问题
|
||||
|
||||
int BlockWidth = mixTexture.width / m_BlockGridSize;
|
||||
int BlockHeight = mixTexture.height / m_BlockGridSize;
|
||||
int[] BaseMapCount = new int[baseMap.Length];
|
||||
m_TerrainBlock = new TerrainBlock[BlockWidth* BlockHeight];
|
||||
for (int j = 0; j < BlockHeight; j++)
|
||||
{
|
||||
for (int i = 0; i < BlockWidth; ++i)
|
||||
{
|
||||
Color32[] BaseMapIndex = new Color32[m_BlockGridSize * m_BlockGridSize];
|
||||
Color[] BaseMapMix = new Color[m_BlockGridSize * m_BlockGridSize];
|
||||
TerrainBlock tBlock = new TerrainBlock();
|
||||
tBlock.m_MapIndex = BaseMapIndex;
|
||||
tBlock.m_MapMix = BaseMapMix;
|
||||
Array.Clear(BaseMapCount, 0, BaseMapCount.Length);
|
||||
int l, k;
|
||||
for (k = 0; k < m_BlockGridSize; k++)
|
||||
{
|
||||
for (l = 0; l < m_BlockGridSize; l++)
|
||||
{
|
||||
Color pixelColor = mixTexture.GetPixel(i* m_BlockGridSize+k, j* m_BlockGridSize+l);
|
||||
GetNearColorIndex(pixelColor, ref BaseMapIndex[l * m_BlockGridSize + k], ref BaseMapMix[l * m_BlockGridSize + k]);
|
||||
BaseMapCount[BaseMapIndex[l * m_BlockGridSize + k][0]]++;
|
||||
BaseMapCount[BaseMapIndex[l * m_BlockGridSize + k][1]]++;
|
||||
BaseMapCount[BaseMapIndex[l * m_BlockGridSize + k][2]]++;
|
||||
BaseMapCount[BaseMapIndex[l * m_BlockGridSize + k][3]]++;
|
||||
}
|
||||
}
|
||||
//留下最高数量的四个BaseMapCount[0-3]
|
||||
Color32 BaseMapIndexMax = new Color32(0,0,0,0);
|
||||
int[] BaseMapCountMax = new int[4];
|
||||
|
||||
for ( k = 0; k < 4; k++)
|
||||
{
|
||||
for ( l = 0; l < BaseMapCount.Length; l++)
|
||||
{
|
||||
if (BaseMapCountMax[k] < BaseMapCount[l])
|
||||
{
|
||||
BaseMapCountMax[k] = BaseMapCount[l];
|
||||
BaseMapIndexMax[k] = (byte)l; //(byte)l;
|
||||
}
|
||||
}
|
||||
BaseMapCount[BaseMapIndexMax[k]] = 0;//最终选定的最大数位置
|
||||
}
|
||||
//全部混合顺序要变为四个统一
|
||||
byte temp = 0;
|
||||
float fMix;
|
||||
for ( k = 0; k < m_BlockGridSize * m_BlockGridSize; k++)
|
||||
{
|
||||
for( l = 0; l < 4; ++l)
|
||||
{
|
||||
bool bfound = false;
|
||||
|
||||
if (BaseMapIndexMax[l] != BaseMapIndex[k][l])
|
||||
{
|
||||
if (l == 3)
|
||||
{
|
||||
bfound = false;
|
||||
}
|
||||
else
|
||||
for (int m = l+1; m < 4; m++)
|
||||
{
|
||||
if (BaseMapIndex[k][m] == BaseMapIndexMax[l])
|
||||
{//替换
|
||||
if (l != m)
|
||||
{
|
||||
fMix = BaseMapMix[k][m];
|
||||
BaseMapMix[k][m] = BaseMapMix[k][l];
|
||||
BaseMapMix[k][l] = fMix;
|
||||
temp = BaseMapIndex[k][m];
|
||||
BaseMapIndex[k][m] = BaseMapIndex[k][l];
|
||||
BaseMapIndex[k][l] = temp;
|
||||
}
|
||||
bfound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bfound)
|
||||
{
|
||||
for (int m = l+1; m < 4; m++)
|
||||
{
|
||||
if (BaseMapIndexMax[m] == BaseMapIndex[k][l])
|
||||
{//顺序错了而已
|
||||
bfound = true;
|
||||
fMix = BaseMapMix[k][m];
|
||||
BaseMapMix[k][m] = BaseMapMix[k][l];
|
||||
BaseMapMix[k][l] = fMix;
|
||||
temp = BaseMapIndex[k][m];
|
||||
BaseMapIndex[k][m] = BaseMapIndex[k][l];
|
||||
BaseMapIndex[k][l] = temp;
|
||||
if (BaseMapIndexMax[l] != BaseMapIndex[k][l])
|
||||
{//如果换了后仍然不同,则需要重新判断一遍
|
||||
m = l;//再判断一遍
|
||||
bfound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bfound)
|
||||
{//完全找不到直接替换(不是最大的四个),混合参数BaseMapMix不用改
|
||||
BaseMapIndex[k][l] = BaseMapIndexMax[l];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
tBlock.m_BaseMapIndex = BaseMapIndexMax;
|
||||
m_TerrainBlock[j * BlockWidth + i] = tBlock;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Block Create OK{(DateTime.Now - oriTime).TotalMilliseconds}");
|
||||
//所有区块都初始化好了,但是边缘是可能对不上的,需要修正
|
||||
|
||||
//组合出混合控制贴图
|
||||
m_ControlTexture = new Texture2D(mixTexture.width, mixTexture.height);
|
||||
for (int j = 0; j < BlockHeight; j++)
|
||||
{
|
||||
for (int i = 0; i < BlockWidth; ++i)
|
||||
{
|
||||
TerrainBlock tBlock = m_TerrainBlock[j * BlockWidth + i];
|
||||
int beginX = i * m_BlockGridSize;
|
||||
int beginY = j * m_BlockGridSize;
|
||||
for (int y = 0; y < m_BlockGridSize; y++)
|
||||
{
|
||||
for (int x = 0; x < m_BlockGridSize; x++)
|
||||
{
|
||||
m_ControlTexture.SetPixel(beginX + x, beginY + y, ChangeColor(tBlock.m_MapMix[x + y * m_BlockGridSize]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ControlTexture.Apply();
|
||||
Debug.Log($"ControlTexture Create OK{(DateTime.Now - oriTime).TotalMilliseconds}");
|
||||
|
||||
//height map 决定地表多边形的高度值
|
||||
float[] mapHeight = new float[texHeight.width * texHeight.height];
|
||||
for (int j = 0; j < texHeight.height; ++j)
|
||||
{
|
||||
for (int i = 0; i < texHeight.width; ++i)
|
||||
{
|
||||
Color pixelColor = texHeight.GetPixel(i, j);
|
||||
mapHeight[i + j * texHeight.width] = GetHeight(pixelColor, m_HeightScale);
|
||||
}
|
||||
}
|
||||
Debug.Log($"height map Create OK{(DateTime.Now - oriTime).TotalMilliseconds}");
|
||||
//构造真正的Mesh
|
||||
m_BlockMeshObjList = new MeshObj[BlockWidth * BlockHeight];
|
||||
//修改uv缩放为贴图大小,适应control图,其他图按照缩放比例
|
||||
m_UVScale = mixTexture.width;
|
||||
#if !UNITY_WEBGL
|
||||
Task<int>[] task = new Task<int>[BlockWidth];
|
||||
for (int i = 0; i < BlockWidth; ++i)
|
||||
{
|
||||
task[i] = Task.Run(() => CalMeshTask(m_TerrainBlock, mapHeight, m_BlockMeshObjList, i, BlockWidth));
|
||||
|
||||
}
|
||||
for (int i = 0; i < BlockWidth; ++i)
|
||||
{
|
||||
task[i].Wait();
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < BlockWidth; ++i)// //test
|
||||
{
|
||||
CalMeshTask(m_TerrainBlock, mapHeight, m_BlockMeshObjList, i, BlockWidth);
|
||||
|
||||
}
|
||||
#endif
|
||||
Debug.Log($"Mesh Create OK{(DateTime.Now - oriTime).TotalMilliseconds}");
|
||||
//区块生成后把所有节点放到总对象下
|
||||
for (int i = 0; i < m_BlockMeshObjList.Length; ++i)
|
||||
{
|
||||
if(m_BlockMeshObjList[i] != null)
|
||||
m_BlockMeshObjList[i].m_Object.transform.SetParent(m_Transform);
|
||||
}
|
||||
}
|
||||
|
||||
static float ColorScale = 3f;
|
||||
Color ChangeColor(Color color)
|
||||
{ //超过0.66的设置为全色, 0.5以上为增比例,0.5一下为减比例
|
||||
Color rc = color;
|
||||
int i = 0, index = -1;
|
||||
float cmax = 0;
|
||||
for ( i = 0; i < 4; ++i)
|
||||
{
|
||||
if (color[i] > cmax)
|
||||
{
|
||||
cmax = color[i];
|
||||
index = i;
|
||||
}
|
||||
//if (color[i] > 0.5f)
|
||||
//{
|
||||
// rc[i] = (color[i] - 0.5f) * ColorScale + 0.5f;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// rc[i] = color[i] / ColorScale;
|
||||
//}
|
||||
}
|
||||
rc[index] = rc[index] * ColorScale;
|
||||
|
||||
Vector4 v4 = rc;
|
||||
v4.Normalize();
|
||||
|
||||
return v4;
|
||||
}
|
||||
|
||||
//方便大部分平台分线程计算
|
||||
int CalMeshTask(TerrainBlock[] BlockList, float[] mapHeight, MeshObj[] BlockMeshObjList, int WidthIndex, int BlockWidth)
|
||||
{
|
||||
int BlockHeight = BlockWidth;
|
||||
int mapWidth = BlockWidth * m_BlockGridSize;
|
||||
for (int j = 0; j < BlockHeight; j++)
|
||||
{
|
||||
TerrainBlock tBlock = BlockList[j * BlockWidth + WidthIndex];
|
||||
MeshObj mObj = new MeshObj();//需要填充的模型对象
|
||||
BlockMeshObjList[j * BlockWidth + WidthIndex] = mObj;
|
||||
// 创建一个新的游戏对象
|
||||
mObj.m_Object = new GameObject($"T{WidthIndex}_{j}");
|
||||
|
||||
// 添加MeshFilter组件
|
||||
MeshFilter meshFilter = mObj.m_Object.AddComponent<MeshFilter>();
|
||||
|
||||
// 创建Mesh
|
||||
Mesh mesh = new Mesh();
|
||||
mObj.m_Mesh = mesh;
|
||||
|
||||
// 设置顶点和三角形数据
|
||||
Vector3[] vertices = new Vector3[(m_BlockGridSize+1)*(m_BlockGridSize+1)];
|
||||
Vector3[] normals;// = new Vector3[(m_BlockGridSize + 1) * (m_BlockGridSize + 1)];
|
||||
Vector2[] uvs = new Vector2[(m_BlockGridSize + 1) * (m_BlockGridSize + 1)];
|
||||
//Vector2[] uvs2 = new Vector2[(m_BlockGridSize + 1) * (m_BlockGridSize + 1)];
|
||||
int[] triangles = new int[6* m_BlockGridSize* m_BlockGridSize];
|
||||
float height = 0;
|
||||
int x, y;
|
||||
int beginPos = j * m_BlockGridSize * mapWidth + WidthIndex * m_BlockGridSize;
|
||||
//顶点 uv
|
||||
for (int k = 0; k < m_BlockGridSize+1; ++k)
|
||||
{
|
||||
for (int l = 0; l < m_BlockGridSize+1; ++l)
|
||||
{//每个格子是两个三角形
|
||||
if (WidthIndex == BlockWidth - 1 && l == m_BlockGridSize)
|
||||
x = l - 1;
|
||||
else
|
||||
x = l;
|
||||
if (j == BlockHeight - 1 && k == m_BlockGridSize)
|
||||
y = k - 1;
|
||||
else
|
||||
y = k;
|
||||
|
||||
height = mapHeight[beginPos + mapWidth * y + x];
|
||||
vertices[k * (m_BlockGridSize+1) + l] = new Vector3(l, height, k);
|
||||
//normals[k * (m_BlockGridSize + 1) + l] = Vector3.up;//简化
|
||||
//Control uv
|
||||
uvs[k * (m_BlockGridSize + 1) + l].x = ((float)l + WidthIndex*m_BlockGridSize) / m_UVScale;
|
||||
uvs[k * (m_BlockGridSize + 1) + l].y = ((float)k + j*m_BlockGridSize) / m_UVScale;
|
||||
//Control uv 不需要, 都用比例
|
||||
//uvs2[k * (m_BlockGridSize + 1) + l] = new Vector2((float)(WidthIndex* BlockWidth+l) / (float)mapWidth, (float)(j * BlockWidth + k)/ (float)mapWidth);
|
||||
}
|
||||
}
|
||||
//法线
|
||||
|
||||
//三角形
|
||||
for (int k = 0; k < m_BlockGridSize; ++k)
|
||||
{
|
||||
for (int m = 0; m < m_BlockGridSize; ++m)
|
||||
{
|
||||
triangles[6 * (k * m_BlockGridSize + m)] = k * (m_BlockGridSize+1) + m;
|
||||
triangles[6 * (k * m_BlockGridSize + m)+2] = k * (m_BlockGridSize + 1) + m+1;
|
||||
triangles[6 * (k * m_BlockGridSize + m)+1] = (k+1) * (m_BlockGridSize + 1) + m;
|
||||
triangles[6 * (k * m_BlockGridSize + m)+3] = k * (m_BlockGridSize + 1) + m +1;
|
||||
triangles[6 * (k * m_BlockGridSize + m)+4] = (k+1) * (m_BlockGridSize + 1) + m;
|
||||
triangles[6 * (k * m_BlockGridSize + m)+5] = (k+1) * (m_BlockGridSize + 1) + m+1;
|
||||
}
|
||||
}
|
||||
// 这里假设已经按照上面的方法设置了顶点和三角形数据
|
||||
mesh.vertices = vertices;
|
||||
//mesh.normals = normals;
|
||||
mesh.triangles = triangles;
|
||||
mesh.uv = uvs;
|
||||
//mesh.uv2 = uvs2;//control uv
|
||||
|
||||
mesh.RecalculateNormals();
|
||||
normals = mesh.normals;
|
||||
|
||||
for (int k = 0; k < m_BlockGridSize + 1; ++k)
|
||||
{
|
||||
normals[k] = Vector3.up;//第一行
|
||||
normals[m_BlockGridSize * (m_BlockGridSize + 1) + k] = Vector3.up;//最后一行
|
||||
}
|
||||
for (int k = 1; k < m_BlockGridSize; ++k)
|
||||
{
|
||||
normals[k * (m_BlockGridSize+1)] = Vector3.up;//第一列
|
||||
normals[(k+1) * (m_BlockGridSize + 1) - 1] = Vector3.up;//最后一列
|
||||
}
|
||||
mesh.normals = normals;
|
||||
// 将Mesh赋值给MeshFilter
|
||||
meshFilter.mesh = mesh;
|
||||
|
||||
// 添加MeshRenderer组件
|
||||
MeshRenderer meshRenderer = mObj.m_Object.AddComponent<MeshRenderer>();
|
||||
meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
||||
// 设置材质和渲染模式
|
||||
// 这里假设已经有一个名为"Material"的材质
|
||||
//meshRenderer.material = Resources.Load<Material>("Material");
|
||||
meshRenderer.material = new Material(m_mtlTerrain);
|
||||
meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
|
||||
meshRenderer.receiveShadows = true;
|
||||
meshRenderer.material.SetTexture("_Splat0", m_BaseMapTexture[tBlock.m_MapIndex[0][0]]);
|
||||
meshRenderer.material.SetTexture("_Normal0", m_NormalMapTexture[tBlock.m_MapIndex[0][0]]);
|
||||
meshRenderer.material.SetTexture("_Splat1", m_BaseMapTexture[tBlock.m_MapIndex[0][1]]);
|
||||
meshRenderer.material.SetTexture("_Normal1", m_NormalMapTexture[tBlock.m_MapIndex[0][1]]);
|
||||
meshRenderer.material.SetTexture("_Splat2", m_BaseMapTexture[tBlock.m_MapIndex[0][2]]);
|
||||
meshRenderer.material.SetTexture("_Normal2", m_NormalMapTexture[tBlock.m_MapIndex[0][2]]);
|
||||
meshRenderer.material.SetTexture("_Splat3", m_BaseMapTexture[tBlock.m_MapIndex[0][3]]);
|
||||
|
||||
meshRenderer.material.SetTexture("_Control", m_ControlTexture);
|
||||
Vector4 uvScale = new Vector4(48f, 64f, 48f, 48f); // 假设要设置的值是(1.0, 1.0, 0.0, 0.0)
|
||||
meshRenderer.material.SetVector("_UvScale0", uvScale);
|
||||
//位置
|
||||
mObj.m_Object.transform.position = new Vector3(WidthIndex * m_BlockGridSize, 0, j * m_BlockGridSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float GetHeight(Color color, float HeightScale = 1.0f)
|
||||
{
|
||||
return HeightScale > 0 ? GetGrayScale(color) * HeightScale : GetGrayScale(color) * HeightScale;
|
||||
}
|
||||
static float GetGrayScale(Color color)
|
||||
{
|
||||
return 0.299f * color.r + 0.587f * color.g + 0.114f * color.b;
|
||||
}
|
||||
|
||||
static void GetNearColorIndex(Color color, ref Color32 index, ref Color degreed)
|
||||
{
|
||||
// 找到与输入颜色最接近的四个颜色
|
||||
//
|
||||
//double[] distances = new double[4];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
m_nearestColors[i] = m_Colors[0];
|
||||
m_Degreed[i] = 1000;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Colors.Length; i++)
|
||||
{
|
||||
float distance = GetDistance(color, m_Colors[i]);
|
||||
// 将当前颜色与已知的最近的四个颜色进行比较
|
||||
for (int j = 0; j < m_nearestColors.Length; j++)
|
||||
{
|
||||
if (m_nearestColors[j] == null || distance < m_Degreed[j])
|
||||
{
|
||||
// 将当前颜色插入到最近的四个颜色中,其他颜色推后
|
||||
for (int k = m_nearestColors.Length - 2; k >= j; k--)
|
||||
{
|
||||
m_nearestColors[k + 1] = m_nearestColors[k];
|
||||
m_Degreed[k + 1] = m_Degreed[k];
|
||||
m_Index[k + 1] = m_Index[k];
|
||||
}
|
||||
m_nearestColors[j] = m_Colors[i];
|
||||
m_Degreed[j] = distance;
|
||||
m_Index[j] = (byte)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
index = m_Index;
|
||||
degreed = m_Degreed;
|
||||
}
|
||||
|
||||
// 计算两个颜色之间的距离
|
||||
static float GetDistance(Color color1, Color color2)
|
||||
{
|
||||
// 使用欧几里得距离公式计算两个颜色在 RGB 空间中的距离
|
||||
float r = color1.r - color2.r;
|
||||
float g = color1.g - color2.g;
|
||||
float b = color1.b - color2.b;
|
||||
return (float)Math.Sqrt(r * r + g * g + b * b);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user