Нашел на гитхабе самый простой пример кода Marching squares с интерполяцией. Без интерполяции всё вообще просто, даже пример не нужен.
Отрефакторил код (выпилил всё лишнее) и получилось вот что:
private List<Vector3> GetTriangles(int state, int x, int y)
{
float t = 0.5f;
float lerpAB = Mathf.InverseLerp(aEdgeValue, bEdgeValue, t);
float lerpBC = Mathf.InverseLerp(bEdgeValue, cEdgeValue, t);
float lerpCD = Mathf.InverseLerp(cEdgeValue, dEdgeValue, t);
float lerpDA = Mathf.InverseLerp(dEdgeValue, aEdgeValue, t);
float a = 0.5f;
Vector3 v0 = new Vector3(x - a, 0, y + a);
Vector3 v1 = new Vector3(x + a, 0, y + a);
Vector3 v2 = new Vector3(x - a, 0, y - a);
Vector3 v3 = new Vector3(x + a, 0, y - a);
Vector3 v4 = new Vector3(x - a + lerpAB, 0, y + a);
Vector3 v5 = new Vector3(x + a, 0, y + a - lerpBC);
Vector3 v6 = new Vector3(x + a - lerpCD, 0, y - a);
Vector3 v7 = new Vector3(x - a, 0, y - a + lerpDA);
.....
}
Проблема: квадрат рисуется от центра [x,y], а мне надо чтобы точка [x,y] была в углу квадрата. Не могу натыкать, чтобы оно сместилось.
Можно, конечно, сделать так:
С размером квадрата разобрался. Осталось только сместить. Я уже и так и эдак пробовал, но получается хрень.
x,y - центр квадрата a - половина размера квадрата v0,v1,v2,v3 - координаты углов квадрата v4,v5,v6,v7 - координаты точек между углами
этого не достаточно?
Ну без всего кода непонятно ж как оно работает и с чем могут быть проблемы.
Чтобы рисовать от точки по идее надо просто сдвинуть всё на а.
drawRectByPoints(
[x - a, y + a],
[x + a, y + a],
[x + a, y - a],
[x - a, y - a],
'red'
);
drawRectByPoints(
[x, y + 2 * a],
[x + 2 * a, y + 2 * a],
[x + 2 * a, y],
[x, y],
'green'
);
Проблема была в том, что координаты точек были не там, где я ожидал. По-этому, не было понятно, где какие углы находятся.
Сейчас я, вроде, разобрался. Позже выложу весь код (когда допилю).
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MarchingSquareInterpolation : MonoBehaviour
{
private int fieldSizeX = 2; //must be 2
private int fieldSizeZ = 2; //must be 2
private float resolution = 1.0f; //size of the square
private float halfResolution;
private float[,] cornerValues;
private float aCornerValue;
private float bCornerValue;
private float cCornerValue;
private float dCornerValue;
[Range(0.0f, 1.0f)]
public float aSliderValue = 1.0f;
[Range(0.0f, 1.0f)]
public float bSliderValue = 0.0f;
[Range(0.0f, 1.0f)]
public float cSliderValue = 0.0f;
[Range(0.0f, 1.0f)]
public float dSliderValue = 0.0f;
private MeshFilter meshFilter;
private void Start()
{
cornerValues = new float[fieldSizeX, fieldSizeZ];
halfResolution = resolution / 2.0f;
meshFilter = GetComponent<MeshFilter>();
}
private void LateUpdate()
{
cornerValues[0, 1] = aSliderValue;
cornerValues[1, 1] = bSliderValue;
cornerValues[1, 0] = cSliderValue;
cornerValues[0, 0] = dSliderValue;
UpdateMesh();
}
private void UpdateMesh()
{
if (meshFilter == null)
{
return;
}
List<Vector3> verts = new List<Vector3>();
List<int> tris = new List<int>();
for (int x = 0; x < fieldSizeX - 1; x++)
{
for (int z = 0; z < fieldSizeZ - 1; z++)
{
aCornerValue = cornerValues[x, z ];
bCornerValue = cornerValues[x + 1, z ];
cCornerValue = cornerValues[x + 1, z + 1];
dCornerValue = cornerValues[x, z + 1];
int aCornerEnabled = IsEdgeEnabled(aCornerValue);
int bCornerEnabled = IsEdgeEnabled(bCornerValue);
int cCornerEnabled = IsEdgeEnabled(cCornerValue);
int dCornerEnabled = IsEdgeEnabled(dCornerValue);
int state = GetState(aCornerEnabled, bCornerEnabled, cCornerEnabled, dCornerEnabled);
Debug.Log(state);
if (state > 0)
{
List<Vector3> triangles = GetTriangles(state, (float)x * resolution, (float)z * resolution);
for (int i = 0; i < triangles.Count; i += 3)
{
AddTriangle(triangles[i], triangles[i + 1], triangles[i + 2]);
}
}
}
}
meshFilter.mesh = new Mesh()
{
vertices = verts.ToArray(),
triangles = tris.ToArray()
};
void AddTriangle(Vector3 v1, Vector3 v2, Vector3 v3)
{
tris.Add(verts.Count);
tris.Add(verts.Count + 1);
tris.Add(verts.Count + 2);
verts.Add(v1);
verts.Add(v2);
verts.Add(v3);
}
}
private List<Vector3> GetTriangles(int state, float xPos, float zPos)
{
/*
D---G---C
| |
H F
| |
A---E---B
*/
float t = 0.5f;
float lerpAB = Mathf.InverseLerp(aCornerValue, bCornerValue, t) * resolution;
float lerpBC = Mathf.InverseLerp(bCornerValue, cCornerValue, t) * resolution;
float lerpCD = Mathf.InverseLerp(cCornerValue, dCornerValue, t) * resolution;
float lerpDA = Mathf.InverseLerp(dCornerValue, aCornerValue, t) * resolution;
Vector3 aPoint = new Vector3(xPos, 0, zPos + resolution);
Vector3 bPoint = new Vector3(xPos + resolution, 0, zPos + resolution);
Vector3 cPoint = new Vector3(xPos + resolution, 0, zPos );
Vector3 dPoint = new Vector3(xPos, 0, zPos );
Vector3 ePoint = new Vector3(aPoint.x + lerpAB, 0, aPoint.z );
Vector3 fPoint = new Vector3(bPoint.x, 0, bPoint.z - lerpBC);
Vector3 gPoint = new Vector3(cPoint.x - lerpCD, 0, cPoint.z );
Vector3 hPoint = new Vector3(aPoint.x, 0, dPoint.z + lerpDA);
List<Vector3> res = new List<Vector3>();
switch (state)
{
case 1:
res.Add(hPoint);
res.Add(gPoint);
res.Add(dPoint);
break;
case 2:
res.Add(gPoint);
res.Add(fPoint);
res.Add(cPoint);
break;
case 3:
res.Add(hPoint);
res.Add(cPoint);
res.Add(dPoint);
res.Add(hPoint);
res.Add(fPoint);
res.Add(cPoint);
break;
case 4:
res.Add(fPoint);
res.Add(ePoint);
res.Add(bPoint);
break;
case 5:
res.Add(bPoint);
res.Add(fPoint);
res.Add(ePoint);
res.Add(ePoint);
res.Add(fPoint);
res.Add(hPoint);
res.Add(dPoint);
res.Add(hPoint);
res.Add(gPoint);
res.Add(gPoint);
res.Add(hPoint);
res.Add(fPoint);
break;
case 6:
res.Add(gPoint);
res.Add(ePoint);
res.Add(cPoint);
res.Add(cPoint);
res.Add(ePoint);
res.Add(bPoint);
break;
case 7:
res.Add(dPoint);
res.Add(hPoint);
res.Add(gPoint);
res.Add(gPoint);
res.Add(hPoint);
res.Add(ePoint);
res.Add(gPoint);
res.Add(ePoint);
res.Add(bPoint);
res.Add(gPoint);
res.Add(bPoint);
res.Add(cPoint);
break;
case 8:
res.Add(ePoint);
res.Add(hPoint);
res.Add(aPoint);
break;
case 9:
res.Add(dPoint);
res.Add(aPoint);
res.Add(gPoint);
res.Add(gPoint);
res.Add(aPoint);
res.Add(ePoint);
break;
case 10:
res.Add(gPoint);
res.Add(hPoint);
res.Add(cPoint);
res.Add(cPoint);
res.Add(hPoint);
res.Add(aPoint);
res.Add(cPoint);
res.Add(aPoint);
res.Add(ePoint);
res.Add(cPoint);
res.Add(ePoint);
res.Add(fPoint);
break;
case 11:
res.Add(dPoint);
res.Add(aPoint);
res.Add(cPoint);
res.Add(cPoint);
res.Add(aPoint);
res.Add(ePoint);
res.Add(cPoint);
res.Add(ePoint);
res.Add(fPoint);
break;
case 12:
res.Add(fPoint);
res.Add(hPoint);
res.Add(aPoint);
res.Add(fPoint);
res.Add(aPoint);
res.Add(bPoint);
break;
case 13:
res.Add(aPoint);
res.Add(bPoint);
res.Add(dPoint);
res.Add(dPoint);
res.Add(bPoint);
res.Add(gPoint);
res.Add(gPoint);
res.Add(bPoint);
res.Add(fPoint);
break;
case 14:
res.Add(gPoint);
res.Add(hPoint);
res.Add(cPoint);
res.Add(cPoint);
res.Add(hPoint);
res.Add(aPoint);
res.Add(cPoint);
res.Add(aPoint);
res.Add(bPoint);
break;
case 15:
res.Add(dPoint);
res.Add(aPoint);
res.Add(cPoint);
res.Add(cPoint);
res.Add(aPoint);
res.Add(bPoint);
break;
}
return res;
}
private int GetState(int a, int b, int c, int d)
{
return a * 8 + b * 4 + c * 2 + d;
}
private int IsEdgeEnabled(float cornerValue)
{
return cornerValue * resolution > halfResolution ? 1 : 0;
}
}
Однако, есть проблема. Перепутаны местами верх и низ квадрата. Надо как-то отзеркалить вычисления, но у меня пока не получается
И ещё надо было массив cornerValues переименовать в field.