Init
This commit is contained in:
235
Assets/MindPowerSdk/Map/MPMap.cs
Normal file
235
Assets/MindPowerSdk/Map/MPMap.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
public partial class MPMap
|
||||
{
|
||||
public const float SEA_LEVEL = 0.0f;
|
||||
|
||||
private static readonly int[,] Offset =
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 1 }
|
||||
};
|
||||
|
||||
private MPTile GetGroupTile(int x, int y, int no)
|
||||
{
|
||||
return GetTile(x + Offset[no, 0], y + Offset[no, 1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取地形的高度
|
||||
/// </summary>
|
||||
/// <param name="fX"></param>
|
||||
/// <param name="fY"></param>
|
||||
/// <returns></returns>
|
||||
public float GetHeight(float fX, float fY)
|
||||
{
|
||||
// 将浮点坐标转换为整数坐标(取整)
|
||||
int nX = (int)fX;
|
||||
int nY = (int)fY;
|
||||
|
||||
// 计算四个角点的坐标(构成一个单位矩形)
|
||||
float fx1 = (float)nX;
|
||||
float fx2 = (float)nX + 1;
|
||||
float fy1 = (float)nY;
|
||||
float fy2 = (float)nY + 1;
|
||||
|
||||
// 初始化四个顶点的高度(默认海平面)
|
||||
float[] fHeight = new float[4] { SEA_LEVEL, SEA_LEVEL, SEA_LEVEL, SEA_LEVEL };
|
||||
|
||||
// 获取基准瓦片
|
||||
MPTile pTile = GetTile(nX, nY);
|
||||
// 遍历四个顶点获取实际高度
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
MPTile pCurTile = GetGroupTile(nX, nY, i);
|
||||
fHeight[i] = pCurTile.Height;
|
||||
}
|
||||
|
||||
// 构建四个三维顶点
|
||||
Vector3 v0 = new Vector3(fx1, fy1, fHeight[0]);
|
||||
Vector3 v1 = new Vector3(fx2, fy1, fHeight[1]);
|
||||
Vector3 v2 = new Vector3(fx1, fy2, fHeight[2]);
|
||||
Vector3 v3 = new Vector3(fx2, fy2, fHeight[3]);
|
||||
|
||||
// 创建射线(从高处垂直向下)
|
||||
Vector3 vOrig = new Vector3(fX, fY, 20.0f); // 起点
|
||||
Vector3 vDir = new Vector3(0, 0, -1); // 方向向下
|
||||
float u, v; // 用于存储交点参数
|
||||
|
||||
Vector3 vPickPos;
|
||||
// 检测与第一个三角形(v0-v1-v2)的相交
|
||||
if (IntersectTri(v0, v1, v2, vOrig, vDir, out u, out v))
|
||||
{
|
||||
vPickPos = v0 + u * (v1 - v0) + v * (v2 - v0);
|
||||
return vPickPos.z; // 返回交点的Z值(高度)
|
||||
}
|
||||
|
||||
// 检测与第二个三角形(v2-v1-v3)的相交
|
||||
if (IntersectTri(v2, v1, v3, vOrig, vDir, out u, out v))
|
||||
{
|
||||
vPickPos = v2 + u * (v1 - v2) + v * (v3 - v2);
|
||||
return vPickPos.z;
|
||||
}
|
||||
|
||||
// 无交点返回0
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Unity版本的三角形射线相交检测
|
||||
bool IntersectTri(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 origin, Vector3 direction, out float u, out float v)
|
||||
{
|
||||
u = v = 0;
|
||||
Vector3 edge1 = v1 - v0;
|
||||
Vector3 edge2 = v2 - v0;
|
||||
|
||||
// 计算行列式
|
||||
Vector3 pvec = Vector3.Cross(direction, edge2);
|
||||
float det = Vector3.Dot(edge1, pvec);
|
||||
|
||||
// 背面剔除(det > 0 可改为 det < 0 如果需要双面检测)
|
||||
if (det < Mathf.Epsilon)
|
||||
return false;
|
||||
|
||||
// 计算U参数并测试范围
|
||||
Vector3 tvec = origin - v0;
|
||||
u = Vector3.Dot(tvec, pvec);
|
||||
if (u < 0 || u > det) return false;
|
||||
|
||||
// 计算V参数并测试范围
|
||||
Vector3 qvec = Vector3.Cross(tvec, edge1);
|
||||
v = Vector3.Dot(direction, qvec);
|
||||
if (v < 0 || u + v > det) return false;
|
||||
|
||||
// 归一化参数
|
||||
float invDet = 1.0f / det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回结束位置与矩形大小
|
||||
/// </summary>
|
||||
/// <param name="startX"></param>
|
||||
/// <param name="startY"></param>
|
||||
/// <param name="showSize"></param>
|
||||
/// <returns></returns>
|
||||
public RectInt GetRect(short startX, short startY, int showSize)
|
||||
{
|
||||
int endX = Mathf.Min(startX + showSize, Width);
|
||||
int endY = Mathf.Min(startY + showSize, Height);
|
||||
|
||||
// 本次宽高
|
||||
int width = endX - startX;
|
||||
int height = endY - startY;
|
||||
|
||||
return new RectInt(endX, endY, width, height);
|
||||
}
|
||||
|
||||
public Mesh GenMesh(short startX, short startY, int showSize)
|
||||
{
|
||||
RectInt rect = GetRect(startX, startY, showSize);
|
||||
|
||||
// 顶点
|
||||
int verticesNum = (rect.width) * (rect.height) * 4;
|
||||
Vector3[] vertices = new Vector3[verticesNum];
|
||||
int[] triangles = new int[verticesNum * 6];
|
||||
Vector2[] uv0 = new Vector2[verticesNum];
|
||||
Vector2[] uv2 = new Vector2[verticesNum];
|
||||
int vertIdx = 0;
|
||||
int triIdx = 0;
|
||||
|
||||
for (short y = startY; y < rect.y; y++)
|
||||
{
|
||||
for (short x = startX; x < rect.x; x++)
|
||||
{
|
||||
// 添加4个顶点
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
MPTile tile = GetGroupTile(x, y, i);
|
||||
vertices[vertIdx + i] = new Vector3(x + Offset[i, 0], tile.Height, (y + Offset[i, 1]) * -1);
|
||||
// Debug.Log($"{x},{y}");
|
||||
|
||||
// uv 整个mesh映射到一张贴图上
|
||||
int rx = x - startX;
|
||||
// int ry = rect.y - y - 2;
|
||||
int ry = y - startY + 1;
|
||||
uv0[vertIdx + i] = new Vector2((rx + Offset[i, 0]) / (float)rect.width, (ry + Offset[i, 1]) * -1 / (float)rect.height);
|
||||
uv2[vertIdx + i] = new Vector2(Offset[i, 0], Offset[i, 1] * -1);
|
||||
}
|
||||
|
||||
triangles[triIdx + 0] = vertIdx + 2;
|
||||
triangles[triIdx + 1] = vertIdx + 0;
|
||||
triangles[triIdx + 2] = vertIdx + 3;
|
||||
|
||||
triangles[triIdx + 3] = vertIdx + 0;
|
||||
triangles[triIdx + 4] = vertIdx + 1;
|
||||
triangles[triIdx + 5] = vertIdx + 3;
|
||||
|
||||
vertIdx += 4;
|
||||
triIdx += 6;
|
||||
}
|
||||
}
|
||||
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetTriangles(triangles, 0);
|
||||
mesh.SetUVs(0, uv0);
|
||||
mesh.SetUVs(2, uv2);
|
||||
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public (Texture2D, Texture2D) GenTxtNoTexture(short startX, short startY, int showSize)
|
||||
{
|
||||
RectInt rect = GetRect(startX, startY, showSize);
|
||||
|
||||
Texture2D texture1 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 贴图值: texNo
|
||||
texture1.filterMode = FilterMode.Point;
|
||||
|
||||
Texture2D texture2 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 遮罩值:alphaNo
|
||||
texture2.filterMode = FilterMode.Point;
|
||||
|
||||
for (short y = startY; y < rect.y; y++)
|
||||
{
|
||||
for (short x = startX; x < rect.x; x++)
|
||||
{
|
||||
MPTile tile = GetTile(x, y);
|
||||
|
||||
// 4层数据
|
||||
float r = (tile.TexLayer[0].TexNo - 1) / 64f;
|
||||
float g = (tile.TexLayer[1].TexNo - 1) / 64f;
|
||||
float b = (tile.TexLayer[2].TexNo - 1) / 64f;
|
||||
float a = (tile.TexLayer[3].TexNo - 1) / 64f;
|
||||
|
||||
int rx = x - startX;
|
||||
int ry = rect.y - 1 - y;
|
||||
texture1.SetPixel(rx, ry, new Color(r, g, b, a));
|
||||
|
||||
var alphaNo = new Color(
|
||||
(tile.TexLayer[0].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[1].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[2].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[3].AlphaNo - 1) / 16f);
|
||||
texture2.SetPixel(rx, ry, alphaNo);
|
||||
|
||||
if (alphaNo.r > 48 || alphaNo.g > 48 || alphaNo.b > 48 || alphaNo.a > 48)
|
||||
{
|
||||
Debug.LogError($"{rx},{ry}|{alphaNo}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texture1.Apply();
|
||||
texture2.Apply();
|
||||
|
||||
return (texture1, texture2);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user