|
|
|
|
|
|
for(var i = 0; i < boatTris.Length; i++) |
|
|
|
boatTris[i] = mesh.triangles[i]; |
|
|
|
|
|
|
|
boatTransformMatrix = boatObj.transform.localToWorldMatrix; |
|
|
|
boatTransformMatrix = boatTrans.localToWorldMatrix; |
|
|
|
} |
|
|
|
|
|
|
|
void OnDisable() |
|
|
|
|
|
|
NativeArray<int> boatTris; |
|
|
|
Matrix4x4 boatTransformMatrix; |
|
|
|
|
|
|
|
IEnumerator ModifyBoatData() |
|
|
|
public IEnumerator ModifyBoatData() |
|
|
|
{ |
|
|
|
///setup jobs
|
|
|
|
///Waves specfic
|
|
|
|
|
|
|
NativeArray<Vector3> wavePos = new NativeArray<Vector3>(128, Allocator.Temp); // To store the waves between calcs
|
|
|
|
|
|
|
|
///ModifyBoatMesh specific
|
|
|
|
//Triangledata array
|
|
|
|
//Triangledata array, finalDatapoint
|
|
|
|
boatTransformMatrix = boatTrans.localToWorldMatrix; |
|
|
|
|
|
|
|
//Triangledatabase array, intermediate point
|
|
|
|
NativeArray<TriangleDataBase> triDataBase = new NativeArray<TriangleDataBase>(128, Allocator.TempJob); |
|
|
|
int triDataBaseCount = 0; |
|
|
|
|
|
|
|
//VertexData for both one above and two above
|
|
|
|
NativeArray<VertexDataSet> oneAbove = new NativeArray<VertexDataSet>(32, Allocator.TempJob); |
|
|
|
int oneAboveCount = 0; |
|
|
|
NativeArray<VertexDataSet> twoAbove = new NativeArray<VertexDataSet>(32, Allocator.TempJob); |
|
|
|
int twoAboveCount = 0; |
|
|
|
|
|
|
|
var localToWorld = new GlobalVertConversion() |
|
|
|
{ |
|
|
|
inPos = boatVerts, |
|
|
|
outPos = globalVertChecklist |
|
|
|
}; |
|
|
|
//>>pass data to job2
|
|
|
|
var localToWorld = new GlobalVertConversion(){inPos = boatVerts, outPos = globalVertChecklist, matrix = boatTransformMatrix}; |
|
|
|
//>>pass globalVertChecklist data to job2 for distance
|
|
|
|
var localToWorldHandle = localToWorld.Schedule(boatVerts.Length, 32); |
|
|
|
|
|
|
|
// ///JOB02 - dependant on job1
|
|
|
|
// //Height of all global verts
|
|
|
|
|
|
|
time = Time.time, |
|
|
|
outPosition = wavePos |
|
|
|
}; |
|
|
|
//>>pass wavePos to job2
|
|
|
|
var heightPass1Handle = heightPass1.Schedule(globalVertChecklist.Length, 4, localToWorldHandle); |
|
|
|
var addTris = new AddTriangles() |
|
|
|
{ |
|
|
|
wavePositions = wavePos, |
|
|
|
globalVertexPos = globalVertChecklist, |
|
|
|
boatTris = boatTris, |
|
|
|
triDataBase = triDataBase, |
|
|
|
triDataBaseCount = triDataBaseCount, |
|
|
|
OneAbove = oneAbove, |
|
|
|
OneAboveCount = oneAboveCount, |
|
|
|
TwoAbove = twoAbove, |
|
|
|
TwoAboveCount = twoAboveCount |
|
|
|
}; |
|
|
|
var addTrisHandle = addTris.Schedule(heightPass1Handle); |
|
|
|
var addOne = new OneAbove() |
|
|
|
{ |
|
|
|
input = oneAbove, |
|
|
|
inputCount = oneAboveCount, |
|
|
|
output = triDataBase |
|
|
|
}; |
|
|
|
var addOneHandle = addOne.Schedule(addTrisHandle); |
|
|
|
///Mini job - add triangles 2 above
|
|
|
|
var addTwo = new TwoAbove() |
|
|
|
{ |
|
|
|
input = twoAbove, |
|
|
|
inputCount = twoAboveCount, |
|
|
|
output = triDataBase |
|
|
|
}; |
|
|
|
var addTwoHandle = addTwo.Schedule(addOneHandle); |
|
|
|
///Mini job - add triangles 2 above
|
|
|
|
var triDataSorting = new TriangleDataSorting() |
|
|
|
{ |
|
|
|
input = triDataBase, |
|
|
|
output = triData |
|
|
|
}; |
|
|
|
var dependancy = JobHandle.CombineDependencies(addTrisHandle, addOneHandle, addTwoHandle); |
|
|
|
var triDataSortingHandle = triDataSorting.Schedule(triDataBase.Length, 4, dependancy); |
|
|
|
while(!triDataSortingHandle.IsCompleted) yield return new WaitForEndOfFrame(); |
|
|
|
|
|
|
|
triDataSortingHandle.Complete(); |
|
|
|
///JOB04 - dependant on job3/minijob1/minijob2
|
|
|
|
//Height of all add tirangles
|
|
|
|
// var heightPass2 = new GerstnerWavesJobs.HeightJob()
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
//Schedule all jobs
|
|
|
|
|
|
|
|
|
|
|
|
underWaterTriangleData.Clear(); |
|
|
|
|
|
|
|
int len = addTris.triDataBaseCount + (addTris.OneAboveCount * 2) + addTris.TwoAboveCount; |
|
|
|
Debug.Log("Triangles to process " + len + " Datasample=" + addTris.boatTris[0]); |
|
|
|
NativeSlice<TriangleData> triSlice = new NativeSlice<TriangleData>(triData, 0, len); |
|
|
|
underWaterTriangleData.AddRange(triSlice.ToArray()); |
|
|
|
return null; |
|
|
|
waveData.Dispose(); |
|
|
|
wavePos.Dispose(); |
|
|
|
triData.Dispose(); |
|
|
|
triDataBase.Dispose(); |
|
|
|
oneAbove.Dispose(); |
|
|
|
twoAbove.Dispose(); |
|
|
|
globalVertChecklist.Dispose(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//Job Get global positions to check
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//Generate the underwater mesh
|
|
|
|
public void GenerateUnderwaterMesh() |
|
|
|
{ |
|
|
|
//Reset
|
|
|
|
underWaterTriangleData.Clear(); |
|
|
|
//Find all the distances to water once because some triangles share vertices, so reuse
|
|
|
|
for (int j = 0; j < boatVertices.Length; j++) |
|
|
|
{ |
|
|
|
//The coordinate should be in global position
|
|
|
|
Vector3 globalPos = boatTrans.TransformPoint(boatVertices[j]); |
|
|
|
// public void GenerateUnderwaterMesh()
|
|
|
|
// {
|
|
|
|
// //Reset
|
|
|
|
// underWaterTriangleData.Clear();
|
|
|
|
// //Find all the distances to water once because some triangles share vertices, so reuse
|
|
|
|
// for (int j = 0; j < boatVertices.Length; j++)
|
|
|
|
// {
|
|
|
|
// //The coordinate should be in global position
|
|
|
|
// Vector3 globalPos = boatTrans.TransformPoint(boatVertices[j]);
|
|
|
|
//Save the global position so we only need to calculate it once here
|
|
|
|
//And if we want to debug we can convert it back to local
|
|
|
|
boatVerticesGlobal[j] = globalPos; |
|
|
|
if(j%2==0) |
|
|
|
{ |
|
|
|
allDistancesToWater[j] = -Water.Instance.GetWaterHeight(globalPos); |
|
|
|
// //Save the global position so we only need to calculate it once here
|
|
|
|
// //And if we want to debug we can convert it back to local
|
|
|
|
// boatVerticesGlobal[j] = globalPos;
|
|
|
|
// if(j%2==0)
|
|
|
|
// {
|
|
|
|
// allDistancesToWater[j] = -Water.Instance.GetWaterHeight(globalPos);
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
allDistancesToWater[j] = allDistancesToWater[j-1]; |
|
|
|
} |
|
|
|
} |
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// allDistancesToWater[j] = allDistancesToWater[j-1];
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// //Add the triangles that are below the water
|
|
|
|
// Profiler.BeginSample("AddTriangles");
|
|
|
|
// AddTriangles();
|
|
|
|
// Profiler.EndSample();
|
|
|
|
// }
|
|
|
|
//Add the triangles that are below the water
|
|
|
|
Profiler.BeginSample("AddTriangles"); |
|
|
|
AddTriangles(); |
|
|
|
Profiler.EndSample(); |
|
|
|
} |
|
|
|
/* |
|
|
|
struct AddTriangles : IJobParallelFor |
|
|
|
struct AddTriangles : IJob |
|
|
|
{ |
|
|
|
[ReadOnly] |
|
|
|
public NativeArray<Vector3> wavePositions; |
|
|
|
|
|
|
public NativeArray<int> boatTris; |
|
|
|
public NativeArray<TriangleData> triData; |
|
|
|
public int index; |
|
|
|
public NativeArray<TriangleDataBase> triDataBase; |
|
|
|
public int triDataBaseCount; |
|
|
|
public void Execute(int i) // this has to process 3 verts at a time to make a tri calculation
|
|
|
|
{ |
|
|
|
VertexData[] vertData = new VertexData[3]; |
|
|
|
TriangleData triangle = new TriangleData(); |
|
|
|
int countAboveWater = 3; |
|
|
|
int id = i; |
|
|
|
//Two vert data out, one for add1 above and one for add two above
|
|
|
|
public NativeArray<VertexDataSet> OneAbove; |
|
|
|
public int OneAboveCount; |
|
|
|
public NativeArray<VertexDataSet> TwoAbove; |
|
|
|
public int TwoAboveCount; |
|
|
|
public float skipped; |
|
|
|
for (int x = 0; x < 3; x++) |
|
|
|
public void Execute() // this has to process 3 verts at a time to make a tri calculation
|
|
|
|
{ |
|
|
|
skipped += 1; |
|
|
|
for(var i = 0; i < boatTris.Length; i += 3) |
|
|
|
//Save the data we need
|
|
|
|
vertData[x].distance = globalVertexPos[id].y - wavePositions[id].y; |
|
|
|
VertexData[] vertData = new VertexData[3]; |
|
|
|
TriangleDataBase triangle = new TriangleDataBase(); |
|
|
|
int countAboveWater = 3; |
|
|
|
int id = i; |
|
|
|
if(vertData[x].distance < 0f) |
|
|
|
countAboveWater--; |
|
|
|
for (int x = 0; x < 3; x++) |
|
|
|
{ |
|
|
|
//Save the data we need
|
|
|
|
vertData[x].distance = globalVertexPos[boatTris[id]].y - wavePositions[boatTris[id]].y; |
|
|
|
vertData[x].index = x; |
|
|
|
if(vertData[x].distance < 0f) |
|
|
|
countAboveWater--; |
|
|
|
vertData[x].globalVertexPos = globalVertexPos[boatTris[id]]; |
|
|
|
id++; |
|
|
|
} |
|
|
|
vertData[x].index = x; |
|
|
|
switch(countAboveWater) |
|
|
|
{ |
|
|
|
case 3: |
|
|
|
break; |
|
|
|
case 0: |
|
|
|
{ |
|
|
|
Vector3 p1 = vertData[0].globalVertexPos; |
|
|
|
Vector3 p2 = vertData[1].globalVertexPos; |
|
|
|
Vector3 p3 = vertData[2].globalVertexPos; |
|
|
|
Vector3 d = new Vector3(vertData[0].distance, vertData[1].distance, vertData[2].distance); |
|
|
|
//Save the triangle
|
|
|
|
triangle.p1 = p1; |
|
|
|
triangle.p2 = p2; |
|
|
|
triangle.p3 = p3; |
|
|
|
triData[index].Add(new TriangleData(p1, p2, p3, d, true)); |
|
|
|
index++; |
|
|
|
vertData[x].globalVertexPos = globalVertexPos[boatTris[id]]; |
|
|
|
id++; |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
|
|
|
|
switch(countAboveWater) |
|
|
|
Array.Sort(vertData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
Profiler.BeginSample("AddTrianglesOneAboveWater"); |
|
|
|
AddTrianglesOneAboveWater(); |
|
|
|
Profiler.EndSample(); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
{ |
|
|
|
Array.Sort(vertexData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
Profiler.BeginSample("AddTrianglesTwoAboveWater"); |
|
|
|
AddTrianglesTwoAboveWater(); |
|
|
|
Profiler.EndSample(); |
|
|
|
case 3: |
|
|
|
break; |
|
|
|
case 0: |
|
|
|
{ |
|
|
|
Vector3 p1 = vertData[0].globalVertexPos; |
|
|
|
Vector3 p2 = vertData[1].globalVertexPos; |
|
|
|
Vector3 p3 = vertData[2].globalVertexPos; |
|
|
|
Vector3 d = new Vector3(vertData[0].distance, vertData[1].distance, vertData[2].distance); |
|
|
|
//Save the triangle
|
|
|
|
triangle.p1 = p1; |
|
|
|
triangle.p2 = p2; |
|
|
|
triangle.p3 = p3; |
|
|
|
triangle.distance = d; |
|
|
|
triangle.full = 1; |
|
|
|
triDataBase[triDataBaseCount] = triangle; |
|
|
|
triDataBaseCount++; |
|
|
|
} |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
{ |
|
|
|
Array.Sort(vertData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
VertexDataSet vs = new VertexDataSet(); |
|
|
|
vs.v1 = vertData[0]; |
|
|
|
vs.v2 = vertData[1]; |
|
|
|
vs.v3 = vertData[2]; |
|
|
|
OneAbove[OneAboveCount] = vs; |
|
|
|
OneAboveCount++; |
|
|
|
} |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
{ |
|
|
|
Array.Sort(vertData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
VertexDataSet vs = new VertexDataSet(); |
|
|
|
vs.v1 = vertData[0]; |
|
|
|
vs.v2 = vertData[1]; |
|
|
|
vs.v3 = vertData[2]; |
|
|
|
TwoAbove[TwoAboveCount] = vs; |
|
|
|
TwoAboveCount++; |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
}*/ |
|
|
|
} |
|
|
|
private void AddTriangles() |
|
|
|
// private void AddTriangles()
|
|
|
|
// {
|
|
|
|
// //Loop through all the triangles (3 vertices at a time = 1 triangle)
|
|
|
|
// int i = 0;
|
|
|
|
// while(i < boatTriangles.Length)
|
|
|
|
// {
|
|
|
|
// int countAboveWater = 3;
|
|
|
|
// //Loop through the 3 vertices
|
|
|
|
// for (int x = 0; x < 3; x++)
|
|
|
|
// {
|
|
|
|
// //Save the data we need
|
|
|
|
// vertexData[x].distance = allDistancesToWater[boatTriangles[i]];
|
|
|
|
|
|
|
|
// if(vertexData[x].distance < 0f)
|
|
|
|
// countAboveWater--;
|
|
|
|
|
|
|
|
// vertexData[x].index = x;
|
|
|
|
|
|
|
|
// vertexData[x].globalVertexPos = boatVerticesGlobal[boatTriangles[i]];
|
|
|
|
// i++;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// switch(countAboveWater)
|
|
|
|
// {
|
|
|
|
// case 3:
|
|
|
|
// break;
|
|
|
|
// case 0:
|
|
|
|
// {
|
|
|
|
// Vector3 p1 = vertexData[0].globalVertexPos;
|
|
|
|
// Vector3 p2 = vertexData[1].globalVertexPos;
|
|
|
|
// Vector3 p3 = vertexData[2].globalVertexPos;
|
|
|
|
// Vector3 d = new Vector3(vertexData[0].distance, vertexData[1].distance, vertexData[2].distance);
|
|
|
|
// //Save the triangle
|
|
|
|
// underWaterTriangleData.Add(new TriangleData(p1, p2, p3, d, true));
|
|
|
|
// }
|
|
|
|
// break;
|
|
|
|
// case 1:
|
|
|
|
// {
|
|
|
|
// Array.Sort(vertexData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);});
|
|
|
|
// Profiler.BeginSample("AddTrianglesOneAboveWater");
|
|
|
|
// AddTrianglesOneAboveWater();
|
|
|
|
// Profiler.EndSample();
|
|
|
|
// }
|
|
|
|
// break;
|
|
|
|
// case 2:
|
|
|
|
// {
|
|
|
|
// Array.Sort(vertexData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);});
|
|
|
|
// Profiler.BeginSample("AddTrianglesTwoAboveWater");
|
|
|
|
// AddTrianglesTwoAboveWater();
|
|
|
|
// Profiler.EndSample();
|
|
|
|
// }
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
struct OneAbove : IJob |
|
|
|
//Loop through all the triangles (3 vertices at a time = 1 triangle)
|
|
|
|
int i = 0; |
|
|
|
while(i < boatTriangles.Length) |
|
|
|
[ReadOnly] |
|
|
|
public NativeArray<VertexDataSet> input; |
|
|
|
[ReadOnly] |
|
|
|
public int inputCount; |
|
|
|
|
|
|
|
public NativeArray<TriangleDataBase> output; |
|
|
|
|
|
|
|
public void Execute() |
|
|
|
int countAboveWater = 3; |
|
|
|
//Loop through the 3 vertices
|
|
|
|
for (int x = 0; x < 3; x++) |
|
|
|
for(var i = 0; i < input.Length; i++) |
|
|
|
{ |
|
|
|
VertexDataSet vds = input[i]; |
|
|
|
//H is always at position 0
|
|
|
|
Vector3 H = vds.v1.globalVertexPos; |
|
|
|
|
|
|
|
//Left of H is M
|
|
|
|
//Right of H is L
|
|
|
|
|
|
|
|
//Find the index of M
|
|
|
|
int M_index = vds.v1.index - 1; |
|
|
|
if (M_index < 0) |
|
|
|
//Save the data we need
|
|
|
|
vertexData[x].distance = allDistancesToWater[boatTriangles[i]]; |
|
|
|
M_index = 2; |
|
|
|
} |
|
|
|
|
|
|
|
//We also need the heights to water
|
|
|
|
float h_H = vds.v1.distance; |
|
|
|
float h_M = 0f; |
|
|
|
float h_L = 0f; |
|
|
|
if(vertexData[x].distance < 0f) |
|
|
|
countAboveWater--; |
|
|
|
Vector3 M = Vector3.zero; |
|
|
|
Vector3 L = Vector3.zero; |
|
|
|
vertexData[x].index = x; |
|
|
|
//This means M is at position 1 in the List
|
|
|
|
if (vds.v2.index == M_index) |
|
|
|
{ |
|
|
|
M = vds.v2.globalVertexPos; |
|
|
|
L = vds.v3.globalVertexPos; |
|
|
|
vertexData[x].globalVertexPos = boatVerticesGlobal[boatTriangles[i]]; |
|
|
|
i++; |
|
|
|
h_M = vds.v2.distance; |
|
|
|
h_L = vds.v3.distance; |
|
|
|
else |
|
|
|
{ |
|
|
|
M = vds.v3.globalVertexPos; |
|
|
|
L = vds.v2.globalVertexPos; |
|
|
|
// if(countAboveWater < 2)
|
|
|
|
// {
|
|
|
|
// Vector3 p1 = vertexData[0].globalVertexPos;
|
|
|
|
// Vector3 p2 = vertexData[1].globalVertexPos;
|
|
|
|
// Vector3 p3 = vertexData[2].globalVertexPos;
|
|
|
|
// //Save the triangle
|
|
|
|
// underWaterTriangleData.Add(new TriangleData(p1, p2, p3));
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
//Debug.Log(countAboveWater);
|
|
|
|
switch(countAboveWater) |
|
|
|
{ |
|
|
|
case 3: |
|
|
|
break; |
|
|
|
case 0: |
|
|
|
{ |
|
|
|
Vector3 p1 = vertexData[0].globalVertexPos; |
|
|
|
Vector3 p2 = vertexData[1].globalVertexPos; |
|
|
|
Vector3 p3 = vertexData[2].globalVertexPos; |
|
|
|
Vector3 d = new Vector3(vertexData[0].distance, vertexData[1].distance, vertexData[2].distance); |
|
|
|
//Save the triangle
|
|
|
|
underWaterTriangleData.Add(new TriangleData(p1, p2, p3, d, true)); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
{ |
|
|
|
Array.Sort(vertexData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
Profiler.BeginSample("AddTrianglesOneAboveWater"); |
|
|
|
AddTrianglesOneAboveWater(); |
|
|
|
Profiler.EndSample(); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
{ |
|
|
|
Array.Sort(vertexData, delegate(VertexData v1, VertexData v2){return v2.distance.CompareTo(v1.distance);}); |
|
|
|
Profiler.BeginSample("AddTrianglesTwoAboveWater"); |
|
|
|
AddTrianglesTwoAboveWater(); |
|
|
|
Profiler.EndSample(); |
|
|
|
} |
|
|
|
break; |
|
|
|
h_M = vds.v3.distance; |
|
|
|
h_L = vds.v2.distance; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Now we can calculate where we should cut the triangle to form 2 new triangles
|
|
|
|
//because the resulting area will always form a square
|
|
|
|
|
|
|
|
//Point I_M
|
|
|
|
Vector3 MH = H - M; |
|
|
|
|
|
|
|
float t_M = -h_M / (h_H - h_M); |
|
|
|
|
|
|
|
Vector3 MI_M = t_M * MH; |
|
|
|
|
|
|
|
Vector3 I_M = MI_M + M; |
|
|
|
|
|
|
|
|
|
|
|
//Point I_L
|
|
|
|
Vector3 LH = H - L; |
|
|
|
|
|
|
|
float t_L = -h_L / (h_H - h_L); |
|
|
|
|
|
|
|
Vector3 LI_L = t_L * LH; |
|
|
|
|
|
|
|
Vector3 I_L = LI_L + L; |
|
|
|
|
|
|
|
//Save the data, such as normal, area, etc
|
|
|
|
//2 triangles below the water
|
|
|
|
TriangleDataBase tri1 = new TriangleDataBase(); |
|
|
|
tri1.p1 = M; |
|
|
|
tri1.p2 = I_M; |
|
|
|
tri1.p2 = I_L; |
|
|
|
tri1.distance = Vector3.zero; |
|
|
|
tri1.full = 0; |
|
|
|
output[inputCount + i*2] = tri1; |
|
|
|
TriangleDataBase tri2 = new TriangleDataBase(); |
|
|
|
tri2.p1 = M; |
|
|
|
tri2.p2 = I_L; |
|
|
|
tri2.p2 = L; |
|
|
|
tri2.distance = Vector3.zero; |
|
|
|
tri2.full = 0; |
|
|
|
output[inputCount + i*2 + 1] = tri2; |
|
|
|
//Build the new triangles where one of the old vertices is above the water
|
|
|
|
private void AddTrianglesOneAboveWater() |
|
|
|
struct TwoAbove : IJob |
|
|
|
//H is always at position 0
|
|
|
|
Vector3 H = vertexData[0].globalVertexPos; |
|
|
|
[ReadOnly] |
|
|
|
public NativeArray<VertexDataSet> input; |
|
|
|
[ReadOnly] |
|
|
|
public int inputCount; |
|
|
|
public int oneAboveCount; |
|
|
|
//Left of H is M
|
|
|
|
//Right of H is L
|
|
|
|
public NativeArray<TriangleDataBase> output; |
|
|
|
//Find the index of M
|
|
|
|
int M_index = vertexData[0].index - 1; |
|
|
|
if (M_index < 0) |
|
|
|
public void Execute() |
|
|
|
M_index = 2; |
|
|
|
} |
|
|
|
for(var i = 0; i < input.Length; i++) |
|
|
|
{ |
|
|
|
VertexDataSet vds = input[i]; |
|
|
|
//H and M are above the water
|
|
|
|
//H is after the vertice that's below water, which is L
|
|
|
|
//So we know which one is L because it is last in the sorted list
|
|
|
|
Vector3 L = vds.v3.globalVertexPos; |
|
|
|
//We also need the heights to water
|
|
|
|
float h_H = vertexData[0].distance; |
|
|
|
float h_M = 0f; |
|
|
|
float h_L = 0f; |
|
|
|
//Find the index of H
|
|
|
|
int H_index = vds.v3.index + 1; |
|
|
|
if (H_index > 2) |
|
|
|
{ |
|
|
|
H_index = 0; |
|
|
|
} |
|
|
|
Vector3 M = Vector3.zero; |
|
|
|
Vector3 L = Vector3.zero; |
|
|
|
//This means M is at position 1 in the List
|
|
|
|
if (vertexData[1].index == M_index) |
|
|
|
{ |
|
|
|
M = vertexData[1].globalVertexPos; |
|
|
|
L = vertexData[2].globalVertexPos; |
|
|
|
//We also need the heights to water
|
|
|
|
float h_L = vds.v3.distance; |
|
|
|
float h_H = 0f; |
|
|
|
float h_M = 0f; |
|
|
|
h_M = vertexData[1].distance; |
|
|
|
h_L = vertexData[2].distance; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
M = vertexData[2].globalVertexPos; |
|
|
|
L = vertexData[1].globalVertexPos; |
|
|
|
Vector3 H = Vector3.zero; |
|
|
|
Vector3 M = Vector3.zero; |
|
|
|
h_M = vertexData[2].distance; |
|
|
|
h_L = vertexData[1].distance; |
|
|
|
} |
|
|
|
//This means that H is at position 1 in the list
|
|
|
|
if (vds.v2.index == H_index) |
|
|
|
{ |
|
|
|
H = vds.v2.globalVertexPos; |
|
|
|
M = vds.v1.globalVertexPos; |
|
|
|
|
|
|
|
//Now we can calculate where we should cut the triangle to form 2 new triangles
|
|
|
|
//because the resulting area will always form a square
|
|
|
|
h_H = vds.v2.distance; |
|
|
|
h_M = vds.v1.distance; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
H = vds.v1.globalVertexPos; |
|
|
|
M = vds.v2.globalVertexPos; |
|
|
|
//Point I_M
|
|
|
|
Vector3 MH = H - M; |
|
|
|
h_H = vds.v1.distance; |
|
|
|
h_M = vds.v2.distance; |
|
|
|
} |
|
|
|
float t_M = -h_M / (h_H - h_M); |
|
|
|
Vector3 MI_M = t_M * MH; |
|
|
|
//Now we can find where to cut the triangle
|
|
|
|
Vector3 I_M = MI_M + M; |
|
|
|
//Point J_M
|
|
|
|
Vector3 LM = M - L; |
|
|
|
|
|
|
|
float t_M = -h_L / (h_M - h_L); |
|
|
|
|
|
|
|
Vector3 LJ_M = t_M * LM; |
|
|
|
|
|
|
|
Vector3 J_M = LJ_M + L; |
|
|
|
//Point I_L
|
|
|
|
Vector3 LH = H - L; |
|
|
|
//Point J_H
|
|
|
|
Vector3 LH = H - L; |
|
|
|
float t_L = -h_L / (h_H - h_L); |
|
|
|
float t_H = -h_L / (h_H - h_L); |
|
|
|
Vector3 LI_L = t_L * LH; |
|
|
|
Vector3 LJ_H = t_H * LH; |
|
|
|
Vector3 I_L = LI_L + L; |
|
|
|
Vector3 J_H = LJ_H + L; |
|
|
|
//Save the data, such as normal, area, etc
|
|
|
|
//2 triangles below the water
|
|
|
|
underWaterTriangleData.Add(new TriangleData(M, I_M, I_L, Vector3.zero, false)); |
|
|
|
underWaterTriangleData.Add(new TriangleData(M, I_L, L, Vector3.zero, false)); |
|
|
|
//Save the data, such as normal, area, etc
|
|
|
|
//1 triangles below the water
|
|
|
|
TriangleDataBase tri1 = new TriangleDataBase(); |
|
|
|
tri1.p1 = L; |
|
|
|
tri1.p2 = J_H; |
|
|
|
tri1.p2 = J_M; |
|
|
|
tri1.distance = Vector3.zero; |
|
|
|
tri1.full = 0; |
|
|
|
output[inputCount + oneAboveCount * 2 + i] = tri1; |
|
|
|
} |
|
|
|
} |
|
|
|
//Build the new triangles where two of the old vertices are above the water
|
|
|
|
private void AddTrianglesTwoAboveWater() |
|
|
|
struct TriangleDataSorting : IJobParallelFor |
|
|
|
//H and M are above the water
|
|
|
|
//H is after the vertice that's below water, which is L
|
|
|
|
//So we know which one is L because it is last in the sorted list
|
|
|
|
Vector3 L = vertexData[2].globalVertexPos; |
|
|
|
[ReadOnly] |
|
|
|
public NativeArray<TriangleDataBase> input; |
|
|
|
public NativeArray<TriangleData> output; |
|
|
|
//Find the index of H
|
|
|
|
int H_index = vertexData[2].index + 1; |
|
|
|
if (H_index > 2) |
|
|
|
public void Execute(int i) |
|
|
|
H_index = 0; |
|
|
|
} |
|
|
|
TriangleData triangleData = new TriangleData(); |
|
|
|
triangleData.p1 = input[i].p1; |
|
|
|
triangleData.p2 = input[i].p2; |
|
|
|
triangleData.p3 = input[i].p3; |
|
|
|
//Center of the triangle
|
|
|
|
triangleData.center = (input[i].p1 + input[i].p2 + input[i].p3) * 0.3333f; |
|
|
|
//We also need the heights to water
|
|
|
|
float h_L = vertexData[2].distance; |
|
|
|
float h_H = 0f; |
|
|
|
float h_M = 0f; |
|
|
|
//Distance to the surface from the center of the triangle, we average it if triangle uncut
|
|
|
|
if(input[i].full == 1) |
|
|
|
triangleData.distanceToSurface = Math.Abs((input[i].distance.x + input[i].distance.y + input[i].distance.z) * 0.3333f); |
|
|
|
else |
|
|
|
triangleData.distanceToSurface = 1234; |
|
|
|
Vector3 H = Vector3.zero; |
|
|
|
Vector3 M = Vector3.zero; |
|
|
|
//Normal to the triangle
|
|
|
|
triangleData.normal = Vector3.Cross(input[i].p2 - input[i].p1, input[i].p3 - input[i].p1).normalized; |
|
|
|
//This means that H is at position 1 in the list
|
|
|
|
if (vertexData[1].index == H_index) |
|
|
|
{ |
|
|
|
H = vertexData[1].globalVertexPos; |
|
|
|
M = vertexData[0].globalVertexPos; |
|
|
|
//Area of the triangle
|
|
|
|
float a = Vector3.Distance(input[i].p1, input[i].p2); |
|
|
|
h_H = vertexData[1].distance; |
|
|
|
h_M = vertexData[0].distance; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
H = vertexData[0].globalVertexPos; |
|
|
|
M = vertexData[1].globalVertexPos; |
|
|
|
float c = Vector3.Distance(input[i].p3, input[i].p1); |
|
|
|
h_H = vertexData[0].distance; |
|
|
|
h_M = vertexData[1].distance; |
|
|
|
triangleData.area = (a * c * Mathf.Sin(Vector3.Angle(input[i].p2 - input[i].p1, input[i].p3 - input[i].p1) * Mathf.Deg2Rad)) * 0.5f; |
|
|
|
triangleData.underWater = 1; |
|
|
|
output[i] = triangleData; |
|
|
|
} |
|
|
|
//Build the new triangles where one of the old vertices is above the water
|
|
|
|
// private void AddTrianglesOneAboveWater()
|
|
|
|
// {
|
|
|
|
// //H is always at position 0
|
|
|
|
// Vector3 H = vertexData[0].globalVertexPos;
|
|
|
|
//Now we can find where to cut the triangle
|
|
|
|
// //Left of H is M
|
|
|
|
// //Right of H is L
|
|
|
|
//Point J_M
|
|
|
|
Vector3 LM = M - L; |
|
|
|
// //Find the index of M
|
|
|
|
// int M_index = vertexData[0].index - 1;
|
|
|
|
// if (M_index < 0)
|
|
|
|
// {
|
|
|
|
// M_index = 2;
|
|
|
|
// }
|
|
|
|
float t_M = -h_L / (h_M - h_L); |
|
|
|
// //We also need the heights to water
|
|
|
|
// float h_H = vertexData[0].distance;
|
|
|
|
// float h_M = 0f;
|
|
|
|
// float h_L = 0f;
|
|
|
|
|
|
|
|
// Vector3 M = Vector3.zero;
|
|
|
|
// Vector3 L = Vector3.zero;
|
|
|
|
|
|
|
|
// //This means M is at position 1 in the List
|
|
|
|
// if (vertexData[1].index == M_index)
|
|
|
|
// {
|
|
|
|
// M = vertexData[1].globalVertexPos;
|
|
|
|
// L = vertexData[2].globalVertexPos;
|
|
|
|
|
|
|
|
// h_M = vertexData[1].distance;
|
|
|
|
// h_L = vertexData[2].distance;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// M = vertexData[2].globalVertexPos;
|
|
|
|
// L = vertexData[1].globalVertexPos;
|
|
|
|
Vector3 LJ_M = t_M * LM; |
|
|
|
// h_M = vertexData[2].distance;
|
|
|
|
// h_L = vertexData[1].distance;
|
|
|
|
// }
|
|
|
|
Vector3 J_M = LJ_M + L; |
|
|
|
|
|
|
|
// //Now we can calculate where we should cut the triangle to form 2 new triangles
|
|
|
|
// //because the resulting area will always form a square
|
|
|
|
// //Point I_M
|
|
|
|
// Vector3 MH = H - M;
|
|
|
|
//Point J_H
|
|
|
|
Vector3 LH = H - L; |
|
|
|
// float t_M = -h_M / (h_H - h_M);
|
|
|
|
float t_H = -h_L / (h_H - h_L); |
|
|
|
// Vector3 MI_M = t_M * MH;
|
|
|
|
Vector3 LJ_H = t_H * LH; |
|
|
|
// Vector3 I_M = MI_M + M;
|
|
|
|
Vector3 J_H = LJ_H + L; |
|
|
|
// //Point I_L
|
|
|
|
// Vector3 LH = H - L;
|
|
|
|
//Save the data, such as normal, area, etc
|
|
|
|
//1 triangle below the water
|
|
|
|
underWaterTriangleData.Add(new TriangleData(L, J_H, J_M, Vector3.zero, false)); |
|
|
|
} |
|
|
|
// float t_L = -h_L / (h_H - h_L);
|
|
|
|
|
|
|
|
// Vector3 LI_L = t_L * LH;
|
|
|
|
|
|
|
|
// Vector3 I_L = LI_L + L;
|
|
|
|
|
|
|
|
// //Save the data, such as normal, area, etc
|
|
|
|
// //2 triangles below the water
|
|
|
|
// underWaterTriangleData.Add(new TriangleData(M, I_M, I_L, Vector3.zero, false));
|
|
|
|
// underWaterTriangleData.Add(new TriangleData(M, I_L, L, Vector3.zero, false));
|
|
|
|
// }
|
|
|
|
|
|
|
|
// //Build the new triangles where two of the old vertices are above the water
|
|
|
|
// private void AddTrianglesTwoAboveWater()
|
|
|
|
// {
|
|
|
|
// //H and M are above the water
|
|
|
|
// //H is after the vertice that's below water, which is L
|
|
|
|
// //So we know which one is L because it is last in the sorted list
|
|
|
|
// Vector3 L = vertexData[2].globalVertexPos;
|
|
|
|
|
|
|
|
// //Find the index of H
|
|
|
|
// int H_index = vertexData[2].index + 1;
|
|
|
|
// if (H_index > 2)
|
|
|
|
// {
|
|
|
|
// H_index = 0;
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// //We also need the heights to water
|
|
|
|
// float h_L = vertexData[2].distance;
|
|
|
|
// float h_H = 0f;
|
|
|
|
// float h_M = 0f;
|
|
|
|
|
|
|
|
// Vector3 H = Vector3.zero;
|
|
|
|
// Vector3 M = Vector3.zero;
|
|
|
|
|
|
|
|
// //This means that H is at position 1 in the list
|
|
|
|
// if (vertexData[1].index == H_index)
|
|
|
|
// {
|
|
|
|
// H = vertexData[1].globalVertexPos;
|
|
|
|
// M = vertexData[0].globalVertexPos;
|
|
|
|
|
|
|
|
// h_H = vertexData[1].distance;
|
|
|
|
// h_M = vertexData[0].distance;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// H = vertexData[0].globalVertexPos;
|
|
|
|
// M = vertexData[1].globalVertexPos;
|
|
|
|
|
|
|
|
// h_H = vertexData[0].distance;
|
|
|
|
// h_M = vertexData[1].distance;
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// //Now we can find where to cut the triangle
|
|
|
|
|
|
|
|
// //Point J_M
|
|
|
|
// Vector3 LM = M - L;
|
|
|
|
|
|
|
|
// float t_M = -h_L / (h_M - h_L);
|
|
|
|
|
|
|
|
// Vector3 LJ_M = t_M * LM;
|
|
|
|
|
|
|
|
// Vector3 J_M = LJ_M + L;
|
|
|
|
|
|
|
|
|
|
|
|
// //Point J_H
|
|
|
|
// Vector3 LH = H - L;
|
|
|
|
|
|
|
|
// float t_H = -h_L / (h_H - h_L);
|
|
|
|
|
|
|
|
// Vector3 LJ_H = t_H * LH;
|
|
|
|
|
|
|
|
// Vector3 J_H = LJ_H + L;
|
|
|
|
|
|
|
|
|
|
|
|
// //Save the data, such as normal, area, etc
|
|
|
|
// //1 triangle below the water
|
|
|
|
// underWaterTriangleData.Add(new TriangleData(L, J_H, J_M, Vector3.zero, false));
|
|
|
|
// }
|
|
|
|
|
|
|
|
//Help class to store triangle data so we can sort the distances
|
|
|
|
private struct VertexData |
|
|
|
|
|
|
public Vector3 globalVertexPos; |
|
|
|
} |
|
|
|
|
|
|
|
private struct VertexDataSet |
|
|
|
{ |
|
|
|
//set of vertdata to make tri
|
|
|
|
public VertexData v1; |
|
|
|
public VertexData v2; |
|
|
|
public VertexData v3; |
|
|
|
} |
|
|
|
|
|
|
|
//Display the underwater mesh
|
|
|
|
public void DisplayMesh(Mesh mesh, string name, List<TriangleData> triangesData) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
mesh.RecalculateBounds(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//To save space so we don't have to send millions of parameters to each method
|
|
|
|
public struct TriangleData |
|
|
|
{ |
|
|
|
//The corners of this triangle in global coordinates
|
|
|
|
public Vector3 p1; |
|
|
|
public Vector3 p2; |
|
|
|
public Vector3 p3; |
|
|
|
|
|
|
|
//The center of the triangle
|
|
|
|
public Vector3 center; |
|
|
|
|
|
|
|
//The distance to the surface from the center of the triangle
|
|
|
|
public float distanceToSurface; |
|
|
|
|
|
|
|
//The normal to the triangle
|
|
|
|
public Vector3 normal; |
|
|
|
//The area of the triangle
|
|
|
|
public float area; |
|
|
|
//Intermediate TriangleDataBase
|
|
|
|
public struct TriangleDataBase |
|
|
|
{ |
|
|
|
public Vector3 p1; |
|
|
|
public Vector3 p2; |
|
|
|
public Vector3 p3; |
|
|
|
public Vector3 distance; |
|
|
|
public int full; |
|
|
|
} |
|
|
|
public bool underWater; |
|
|
|
|
|
|
|
public TriangleData(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 distances, bool full) |
|
|
|
//To save space so we don't have to send millions of parameters to each method
|
|
|
|
[System.Serializable] |
|
|
|
public struct TriangleData |
|
|
|
this.p1 = p1; |
|
|
|
this.p2 = p2; |
|
|
|
this.p3 = p3; |
|
|
|
|
|
|
|
//Center of the triangle
|
|
|
|
this.center = (p1 + p2 + p3) / 3f; |
|
|
|
|
|
|
|
//Distance to the surface from the center of the triangle, we average it if triangle uncut
|
|
|
|
if(full) |
|
|
|
this.distanceToSurface = Mathf.Abs((distances.x + distances.y + distances.z) / 3f); |
|
|
|
else |
|
|
|
this.distanceToSurface = Mathf.Abs(Water.Instance.GetWaterHeight(this.center)); |
|
|
|
|
|
|
|
//Normal to the triangle
|
|
|
|
this.normal = Vector3.Cross(p2 - p1, p3 - p1).normalized; |
|
|
|
|
|
|
|
//Area of the triangle
|
|
|
|
float a = Vector3.Distance(p1, p2); |
|
|
|
|
|
|
|
float c = Vector3.Distance(p3, p1); |
|
|
|
|
|
|
|
this.area = (a * c * Mathf.Sin(Vector3.Angle(p2 - p1, p3 - p1) * Mathf.Deg2Rad)) / 2f; |
|
|
|
this.underWater = true; |
|
|
|
//The corners of this triangle in global coordinates
|
|
|
|
public Vector3 p1; |
|
|
|
public Vector3 p2; |
|
|
|
public Vector3 p3; |
|
|
|
//The center of the triangle
|
|
|
|
public Vector3 center; |
|
|
|
//The distance to the surface from the center of the triangle
|
|
|
|
public float distanceToSurface; |
|
|
|
//The normal to the triangle
|
|
|
|
public Vector3 normal; |
|
|
|
//The area of the triangle
|
|
|
|
public float area; |
|
|
|
public int underWater; |
|
|
|
} |
|
|
|
} |
|
|
|
} |