More work on porting.

This commit is contained in:
Relintai 2020-01-20 11:45:46 +01:00
parent 7a35337367
commit 83806f4bc1
2 changed files with 139 additions and 43 deletions

View File

@ -404,9 +404,9 @@ void VoxelMesher::UpdateMesh(int iteration) {
for (int i = 0; i < _mu_triangles.size(); ++i) { for (int i = 0; i < _mu_triangles.size(); ++i) {
// Calc Edge Error // Calc Edge Error
MUTriangle triangle = _mu_triangles[i]; MUTriangle triangle = _mu_triangles[i];
_mu_triangles[i].err0 = CalculateError(_mu_vertices[triangle.v0], _mu_vertices[triangle.v1], out dummy); _mu_triangles[i].err0 = CalculateError(_mu_vertices[triangle.v0], _mu_vertices[triangle.v1], &dummy);
_mu_triangles[i].err1 = CalculateError(_mu_vertices[triangle.v1], _mu_vertices[triangle.v2], out dummy); _mu_triangles[i].err1 = CalculateError(_mu_vertices[triangle.v1], _mu_vertices[triangle.v2], &dummy);
_mu_triangles[i].err2 = CalculateError(_mu_vertices[triangle.v2], _mu_vertices[triangle.v0], out dummy); _mu_triangles[i].err2 = CalculateError(_mu_vertices[triangle.v2], _mu_vertices[triangle.v0], &dummy);
_mu_triangles[i].err3 = VoxelMesher::Min3(_mu_triangles[i].err0, _mu_triangles[i].err1, _mu_triangles[i].err2); _mu_triangles[i].err3 = VoxelMesher::Min3(_mu_triangles[i].err0, _mu_triangles[i].err1, _mu_triangles[i].err2);
} }
} }
@ -470,6 +470,7 @@ void VoxelMesher::CompactMesh() {
for (int i = 0; i < _mu_triangles.size(); i++) { for (int i = 0; i < _mu_triangles.size(); i++) {
MUTriangle triangle = _mu_triangles[i]; MUTriangle triangle = _mu_triangles[i];
if (!triangle.deleted) { if (!triangle.deleted) {
if (triangle.va0 != triangle.v0) { if (triangle.va0 != triangle.v0) {
int iDest = triangle.va0; int iDest = triangle.va0;
@ -508,22 +509,22 @@ void VoxelMesher::CompactMesh() {
_mu_vertices[triangle.v1].tcount = 1; _mu_vertices[triangle.v1].tcount = 1;
_mu_vertices[triangle.v2].tcount = 1; _mu_vertices[triangle.v2].tcount = 1;
if (triangle.subMeshIndex > lastSubMeshIndex) { //if (triangle.subMeshIndex > lastSubMeshIndex) {
for (int j = lastSubMeshIndex + 1; j < triangle.subMeshIndex; j++) { // for (int j = lastSubMeshIndex + 1; j < triangle.subMeshIndex; j++) {
subMeshOffsets[j] = newTriangleIndex; // subMeshOffsets[j] = newTriangleIndex;
} // }
subMeshOffsets[triangle.subMeshIndex] = newTriangleIndex; // subMeshOffsets[triangle.subMeshIndex] = newTriangleIndex;
lastSubMeshIndex = triangle.subMeshIndex; // lastSubMeshIndex = triangle.subMeshIndex;
} //}
} }
} }
triangleCount = dst; //triangleCount = dst;
for (int i = lastSubMeshIndex + 1; i < subMeshCount; i++) { //for (int i = lastSubMeshIndex + 1; i < subMeshCount; i++) {
subMeshOffsets[i] = triangleCount; // subMeshOffsets[i] = triangleCount;
} //}
this.triangles.Resize(triangleCount); _mu_triangles.resize(dst);
dst = 0; dst = 0;
for (int i = 0; i < vertexCount; i++) { for (int i = 0; i < vertexCount; i++) {
@ -573,16 +574,16 @@ void VoxelMesher::CompactMesh() {
} }
} }
for (int i = 0; i < triangleCount; i++) { for (int i = 0; i < _mu_triangles.size(); i++) {
var triangle = triangles[i]; MUTriangle triangle = _mu_triangles[i];
triangle.v0 = vertices[triangle.v0].tstart; triangle.v0 = _mu_vertices[triangle.v0].tstart;
triangle.v1 = vertices[triangle.v1].tstart; triangle.v1 = _mu_vertices[triangle.v1].tstart;
triangle.v2 = vertices[triangle.v2].tstart; triangle.v2 = _mu_vertices[triangle.v2].tstart;
triangles[i] = triangle; _mu_triangles[i] = triangle;
} }
vertexCount = dst; //vertexCount = dst;
this.vertices.Resize(vertexCount); this.vertices.Resize(dst);
if (vertNormals != null) this.vertNormals.Resize(vertexCount, true); if (vertNormals != null) this.vertNormals.Resize(vertexCount, true);
if (vertTangents != null) this.vertTangents.Resize(vertexCount, true); if (vertTangents != null) this.vertTangents.Resize(vertexCount, true);
if (vertUV2D != null) this.vertUV2D.Resize(vertexCount, true); if (vertUV2D != null) this.vertUV2D.Resize(vertexCount, true);
@ -649,20 +650,20 @@ int VoxelMesher::RemoveVertexPass(int startTrisCount, int targetTrisCount, doubl
continue; continue;
// Compute vertex to collapse to // Compute vertex to collapse to
CalculateError(_mu_vertices[i0], ref _mu_vertices[i1], out p); CalculateError(_mu_vertices[i0], _mu_vertices[i1], &p);
deleted0.Resize(_mu_vertices[i0].tcount); // normals temporarily deleted0.resize(_mu_vertices[i0].tcount); // normals temporarily
deleted1.Resize(_mu_vertices[i1].tcount); // normals temporarily deleted1.resize(_mu_vertices[i1].tcount); // normals temporarily
// Don't remove if flipped // Don't remove if flipped
if (Flipped(ref p, i0, i1, ref _mu_vertices[i0], deleted0.Data)) if (Flipped(&p, i0, i1, &(_mu_vertices[i0]), deleted0))
continue; continue;
if (Flipped(ref p, i1, i0, ref _mu_vertices[i1], deleted1.Data)) if (Flipped(&p, i1, i0, &(_mu_vertices[i1]), deleted1))
continue; continue;
// Calculate the barycentric coordinates within the triangle // Calculate the barycentric coordinates within the triangle
int nextNextEdgeIndex = ((edgeIndex + 2) % 3); int nextNextEdgeIndex = ((edgeIndex + 2) % 3);
int i2 = _mu_triangles[tid].get(nextNextEdgeIndex); int i2 = _mu_triangles[tid].get(nextNextEdgeIndex);
CalculateBarycentricCoords(ref p, ref _mu_vertices[i0].p, ref _mu_vertices[i1].p, ref _mu_vertices[i2].p, out barycentricCoord); barycentricCoord = CalculateBarycentricCoords(p, _mu_vertices[i0].p, _mu_vertices[i1].p, _mu_vertices[i2].p);
// Not flipped, so remove edge // Not flipped, so remove edge
_mu_vertices[i0].p = p; _mu_vertices[i0].p = p;
@ -672,17 +673,17 @@ int VoxelMesher::RemoveVertexPass(int startTrisCount, int targetTrisCount, doubl
int ia0 = attrib_indices[edgeIndex]; int ia0 = attrib_indices[edgeIndex];
int ia1 = attrib_indices[nextEdgeIndex]; int ia1 = attrib_indices[nextEdgeIndex];
int ia2 = attrib_indices[nextNextEdgeIndex]; int ia2 = attrib_indices[nextNextEdgeIndex];
InterpolateVertexAttributes(ia0, ia0, ia1, ia2, ref barycentricCoord); InterpolateVertexAttributes(ia0, ia0, ia1, ia2, barycentricCoord);
if (_mu_vertices[i0].uvSeamEdge) { if (_mu_vertices[i0].uvSeamEdge) {
ia0 = -1; ia0 = -1;
} }
int tstart = refs.Length; int tstart = _mu_refs.size();
deletedTris = UpdateTriangles(i0, ia0, _mu_vertices[i0], deleted0, deletedTris); deletedTris = UpdateTriangles(i0, ia0, &(_mu_vertices[i0]), deleted0, deletedTris);
deletedTris = UpdateTriangles(i0, ia0, _mu_vertices[i1], deleted1, deletedTris); deletedTris = UpdateTriangles(i0, ia0, &(_mu_vertices[i1]), deleted1, deletedTris);
int tcount = refs.Length - tstart; int tcount = _mu_refs.size() - tstart;
if (tcount <= _mu_vertices[i0].tcount) { if (tcount <= _mu_vertices[i0].tcount) {
// save ram // save ram
if (tcount > 0) { if (tcount > 0) {
@ -734,20 +735,29 @@ double VoxelMesher::CalculateError(MUVertex vert0, MUVertex vert1, Vector3 *resu
error = VoxelMesher::Min3(error1, error2, error3); error = VoxelMesher::Min3(error1, error2, error3);
if (error == error3) { if (error == error3) {
result = p3; result->x = p3.x;
result->y = p3.y;
result->z = p3.z;
} else if (error == error2) { } else if (error == error2) {
result = p2; result->x = p2.x;
result->y = p2.y;
result->z = p2.z;
} else if (error == error1) { } else if (error == error1) {
result = p1; result->x = p1.x;
result->y = p1.y;
result->z = p1.z;
} else { } else {
result = p3; result->x = p3.x;
result->y = p3.y;
result->z = p3.z;
} }
} }
return error; return error;
} }
void VoxelMesher::UpdateTriangles(int i0, int ia0, MUVertex *v, PoolVector<bool> deleted, int *deletedTriangles) { int VoxelMesher::UpdateTriangles(int i0, int ia0, MUVertex *v, PoolVector<bool> deleted, int p_deletedTriangles) {
Vector3 p; Vector3 p;
int deletedTriangles = p_deletedTriangles;
int tcount = v->tcount; int tcount = v->tcount;
for (int k = 0; k < tcount; k++) { for (int k = 0; k < tcount; k++) {
@ -769,14 +779,97 @@ void VoxelMesher::UpdateTriangles(int i0, int ia0, MUVertex *v, PoolVector<bool>
} }
t.dirty = true; t.dirty = true;
t.err0 = CalculateError(_mu_vertices[t.v0], _mu_vertices[t.v1], p); t.err0 = CalculateError(_mu_vertices[t.v0], _mu_vertices[t.v1], &p);
t.err1 = CalculateError(_mu_vertices[t.v1], _mu_vertices[t.v2], p); t.err1 = CalculateError(_mu_vertices[t.v1], _mu_vertices[t.v2], &p);
t.err2 = CalculateError(_mu_vertices[t.v2], _mu_vertices[t.v0], p); t.err2 = CalculateError(_mu_vertices[t.v2], _mu_vertices[t.v0], &p);
t.err3 = VoxelMesher::Min3(t.err0, t.err1, t.err2); t.err3 = VoxelMesher::Min3(t.err0, t.err1, t.err2);
_mu_triangles[tid] = t; _mu_triangles[tid] = t;
_mu_refs.push_back(r); _mu_refs.push_back(r);
} }
return deletedTriangles;
}
bool VoxelMesher::Flipped(Vector3 *p, int i0, int i1, MUVertex *v0, PoolVector<bool> &deleted) {
int tcount = v0->tcount;
for (int k = 0; k < tcount; k++) {
MURef r = _mu_refs[v0->tstart + k];
if (_mu_triangles[r.tid].deleted)
continue;
int s = r.tvertex;
int id1 = _mu_triangles[r.tid].get((s + 1) % 3);
int id2 = _mu_triangles[r.tid].get((s + 2) % 3);
if (id1 == i1 || id2 == i1) {
deleted.set(k, true);
continue;
}
Vector3 d1 = _mu_vertices[id1].p - (*p);
d1.normalize();
Vector3 d2 = _mu_vertices[id2].p - (*p);
d2.normalize();
double dot = d1.dot(d2);
if (Math::abs(dot) > 0.999)
return true;
Vector3 n = d1.cross(d2);
n.normalize();
deleted.set(k, false);
dot = n.dot(_mu_triangles[r.tid].n);
if (dot < 0.2)
return true;
}
return false;
}
Vector3 VoxelMesher::CalculateBarycentricCoords(Vector3 const &point, Vector3 const &a, Vector3 const &b, Vector3 const &c) {
Vector3 v0 = (Vector3)(b - a), v1 = (Vector3)(c - a), v2 = (Vector3)(point - a);
float d00 = v0.dot(v0);
float d01 = v0.dot(v1);
float d11 = v1.dot(v1);
float d20 = v2.dot(v0);
float d21 = v2.dot(v1);
float denom = d00 * d11 - d01 * d01;
float v = (d11 * d20 - d01 * d21) / denom;
float w = (d00 * d21 - d01 * d20) / denom;
float u = 1.0 - v - w;
return Vector3(u, v, w);
}
void VoxelMesher::InterpolateVertexAttributes(int dst, int i0, int i1, int i2, Vector3 &barycentricCoord) {
if (vertNormals != null) {
vertNormals[dst] = Vector3.Normalize((vertNormals[i0] * barycentricCoord.x) + (vertNormals[i1] * barycentricCoord.y) + (vertNormals[i2] * barycentricCoord.z));
}
if (vertTangents != null) {
vertTangents[dst] = NormalizeTangent((vertTangents[i0] * barycentricCoord.x) + (vertTangents[i1] * barycentricCoord.y) + (vertTangents[i2] * barycentricCoord.z));
}
if (vertUV2D != null) {
for (int i = 0; i < UVChannelCount; i++) {
var vertUV = vertUV2D[i];
if (vertUV != null) {
vertUV[dst] = (vertUV[i0] * barycentricCoord.x) + (vertUV[i1] * barycentricCoord.y) + (vertUV[i2] * barycentricCoord.z);
}
}
}
if (vertColors != null) {
vertColors[dst] = (vertColors[i0] * barycentricCoord.x) + (vertColors[i1] * barycentricCoord.y) + (vertColors[i2] * barycentricCoord.z);
}
if (blendShapes != null) {
for (int i = 0; i < blendShapes.Length; i++) {
blendShapes[i].InterpolateVertexAttributes(dst, i0, i1, i2, barycentricCoord);
}
}
// TODO: How do we interpolate the bone weights? Do we have to?
} }
void VoxelMesher::reset() { void VoxelMesher::reset() {

View File

@ -88,7 +88,10 @@ public:
bool AreUVsTheSame(int channel, int indexA, int indexB); bool AreUVsTheSame(int channel, int indexA, int indexB);
double VertexError(SymmetricMatrix q, double x, double y, double z); double VertexError(SymmetricMatrix q, double x, double y, double z);
double CalculateError(MUVertex vert0, MUVertex vert1, Vector3 *result); double CalculateError(MUVertex vert0, MUVertex vert1, Vector3 *result);
void UpdateTriangles(int i0, int ia0, MUVertex *v, PoolVector<bool> deleted, int *deletedTriangles); int UpdateTriangles(int i0, int ia0, MUVertex *v, PoolVector<bool> deleted, int deletedTriangles);
bool Flipped(Vector3 *p, int i0, int i1, MUVertex *v0, PoolVector<bool> &deleted);
static Vector3 CalculateBarycentricCoords(Vector3 const &point, Vector3 const &a, Vector3 const &b, Vector3 const &c);
void InterpolateVertexAttributes(int dst, int i0, int i1, int i2, Vector3 &barycentricCoord);
static double Min3(double val1, double val2, double val3) { static double Min3(double val1, double val2, double val3) {
return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3)); return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3));