private MeshTriangle(MeshTriangle other, Vector3 translate) { Id = other.Id; P0 = other.P0 + translate; P1 = other.P1 + translate; P2 = other.P2 + translate; Points = new List<Vector3>{P0, P1, P2}; U = other.U; V = other.V; Normal = other.Normal; Direction = other.Direction; UU = other.UU; VV = other.VV; UV = other.UV; D = other.D; }
private bool SplitPoints(MeshTriangle[] triangles, out List<Vector3> lineA, out List<Vector3> lineB) { var gradients = new Vector3[4][]; lineA = lineB = null; for (var i = 0; i < 4; ++i) { gradients[i] = new Vector3[3]; for (var j = 0; j < 3; ++j) { gradients[i][j] = (triangles[i].Points[j] - triangles[i].Points[(j + 1)%3]).NormalizeRet(); } } var lines = new List<List<Vector3>>(); // now find the gradients that are the same on different triangles & where // the start & end points are the same... for (var triangleAIndex = 0; triangleAIndex < 4; ++triangleAIndex) { for (var triangleBIndex = 0; triangleBIndex < 4; ++triangleBIndex) { for (var lineAIndex = 0; lineAIndex < 3; ++lineAIndex) { for (var lineBIndex = 0; lineBIndex < 3; ++lineBIndex) { if (gradients[triangleAIndex][lineAIndex] == gradients[triangleBIndex][lineBIndex] && (triangles[triangleAIndex].Points[(lineAIndex + 1)%3] == triangles[triangleBIndex].Points[lineBIndex])) { lines.Add(new List<Vector3> { triangles[triangleAIndex].Points[lineAIndex], triangles[triangleAIndex].Points[(lineAIndex + 1)%3], triangles[triangleBIndex].Points[(lineBIndex + 1)%3] }); } } } } } if (lines.Count != 2) return false; lineA = lines[0]; lineB = lines[1]; return true; }
// attempt to merge the (4) given triangles. if they can be merged then the result is populated private bool AttemptMergeTriangles(MeshTriangle[] toTryToMerge, out MeshTriangle[] result) { // for 4 triangles to merge - then between the 4 triangles there should be only 6 unique points result = null; var points = new HashSet<Vector3>(); foreach (var triangle in toTryToMerge) { points.Add(triangle.P0); points.Add(triangle.P1); points.Add(triangle.P2); } if (points.Count != 6) return false; // we need 2 lots of 3 sets of points to be able to merge, so the 6 points are to be split // and the 2 lines can be merged into new triangles. List<Vector3> lineA; List<Vector3> lineB; if (SplitPoints(toTryToMerge, out lineA, out lineB)) { result = new MeshTriangle[2]; result[0] = new MeshTriangle(toTryToMerge[0].Id, lineA[0], lineA[2], lineB[2]); result[1] = new MeshTriangle(toTryToMerge[0].Id, lineB[0], lineB[2], lineA[2]); return true; } return false; }
private void MergeTriangles(List<MeshTriangle> triangles) { var startCount = triangles.Count; //Logger.Write("Attempting to merge triangles in mesh - starting with " + startCount, LoggerLevel.Trace); var toExamine = new MeshTriangle[4]; var newTriangles = new List<MeshTriangle>(); var position = 0; for (; position < triangles.Count - 4; ++position) { for (var count = 0; count < 4; ++count) { toExamine[count] = triangles[position + count]; } MeshTriangle[] result; if (!AttemptMergeTriangles(toExamine, out result)) { newTriangles.Add(triangles[position]); continue; } position += 3; newTriangles.AddRange(result); } for (; position < triangles.Count; ++position) newTriangles.Add(triangles[position]); triangles.Clear(); triangles.AddRange(newTriangles); var endCount = triangles.Count; if (endCount != startCount) MergeTriangles(triangles); //Logger.Write("Completed merge triangles in mesh - finished with " + endCount, LoggerLevel.Trace); }
public virtual void AddTriangle(MeshTriangle meshTriangle) { Triangles.Add(new MeshTriangle(meshTriangle.Id, meshTriangle.P0, meshTriangle.P1, meshTriangle.P2)); _maxX = _maxY = _maxZ = _minX = _minY = _minZ = null; }
public override void AddTriangle(MeshTriangle meshTriangle) { Triangles.Add(new MeshTriangle(meshTriangle.Id, meshTriangle.P0, meshTriangle.P1, meshTriangle.P2).Rotate(_actualRotation)); }
private void UpdateCollisionData(MeshCollisionData data, float distance, CollisionResult result, MeshTriangle triangle) { if (!data.HasCollided || distance < data.CollisionDistance) { data.CollisionDistance = distance; data.CollisionResult = result; data.CollisionId = triangle.Id; data.Triangle = triangle; data.HasCollided = true; } }
public MeshCollisionResult(CollisionResult rayCollisionResult, byte triangleId = 0, MeshTriangle hit = null) { RayCollisionResult = rayCollisionResult; TriangleId = triangleId; Triangle = hit; }
private CollisionResult CollideTriangleWithRay(MeshTriangle triangle, Vector3 point, Vector3 direction) { var n = triangle.Normal; var b = n.Dot(direction); if (b >= 0.00000) return new CollisionResult { HasCollided = false }; var w0 = point - triangle.P0; var a = -n.Dot(w0); var r = a / b; if (r < 0) return new CollisionResult { HasCollided = false }; var I = point + r * direction; var w = I - triangle.P0; var wu = w.Dot(triangle.U); var wv = w.Dot(triangle.V); var s = (triangle.UV * wv - triangle.VV * wu) / triangle.D; if (s < 0 || s > 1) return new CollisionResult { HasCollided = false }; var t = (triangle.UV * wu - triangle.UU * wv) / triangle.D; if (t < 0 || (s + t) > 1) return new CollisionResult { HasCollided = false }; return new CollisionResult { HasCollided = true, CollisionPoint = I }; }