public void PrepareCache(MyVoxelVertex[] vertices, int vertexCount, MyVoxelTriangle[] triangles, int triangleCount) { lock (m_syncRoot) { if (vertexCount == 0) { VoxelVerticesCount = 0; VoxelTrianglesCount = 0; m_octree = null; VoxelVertices = null; return; } MyCommonDebugUtils.AssertDebug(vertexCount <= Int16.MaxValue); MyRender.GetRenderProfiler().StartProfilingBlock("build octree"); if (m_octree == null) m_octree = new MyOctree(); m_octree.Init(ref vertices, ref vertexCount, ref triangles, ref triangleCount, out VoxelTriangles); MyRender.GetRenderProfiler().EndProfilingBlock(); // copy voxel vertices VoxelVertices = new MyVoxelVertex[vertexCount]; for (int i = 0; i < vertexCount; i++) VoxelVertices[i] = vertices[i]; // set size only after the arrays are fully allocated VoxelVerticesCount = vertexCount; VoxelTrianglesCount = triangleCount; } }
private void GetCellLineIntersectionOctree(ref MyIntersectionResultLineTriangle?result, ref Line modelSpaceLine, ref float?minDistanceUntilNow, CellData cachedDataCell, IntersectionFlags flags) { m_overlapElementCache.Clear(); if (cachedDataCell.Octree != null) { Vector3 packedStart; cachedDataCell.GetPackedPosition(ref modelSpaceLine.From, out packedStart); var ray = new Ray(packedStart, modelSpaceLine.Direction); cachedDataCell.Octree.GetIntersectionWithLine(ref ray, m_overlapElementCache); } for (int j = 0; j < m_overlapElementCache.Count; j++) { var i = m_overlapElementCache[j]; if (cachedDataCell.VoxelTriangles == null) //probably not calculated yet { continue; } // this should never happen if (i >= cachedDataCell.VoxelTriangles.Length) { Debug.Assert(i < cachedDataCell.VoxelTriangles.Length); continue; } MyVoxelTriangle voxelTriangle = cachedDataCell.VoxelTriangles[i]; MyTriangle_Vertexes triangleVertices; cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangleVertices.Vertex0); cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangleVertices.Vertex1); cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangleVertices.Vertex2); Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangleVertices); //We dont want backside intersections if (((int)(flags & IntersectionFlags.FLIPPED_TRIANGLES) == 0) && Vector3.Dot(modelSpaceLine.Direction, calculatedTriangleNormal) > 0) { continue; } // AABB intersection test removed, AABB is tested inside BVH float?distance = MyUtils.GetLineTriangleIntersection(ref modelSpaceLine, ref triangleVertices); // If intersection occured and if distance to intersection is closer to origin than any previous intersection if ((distance != null) && ((result == null) || (distance.Value < result.Value.Distance))) { minDistanceUntilNow = distance.Value; result = new MyIntersectionResultLineTriangle(ref triangleVertices, ref calculatedTriangleNormal, distance.Value); } } }
/// <summary> /// Returns true if triangle has very close to zero surface area. /// </summary> private bool HasZeroSurface(MyVoxelTriangle triangle) { var vertex0 = m_vertices[triangle.VertexIndex0]; var vertex1 = m_vertices[triangle.VertexIndex1]; var vertex2 = m_vertices[triangle.VertexIndex2]; var vector1 = vertex1.Position - vertex0.Position; vector1.Normalize(); var vector2 = vertex2.Position - vertex0.Position; vector2.Normalize(); var dot = Vector3.Dot(vector1, vector2); if (Math.Abs(dot) > 0.9999) { return(true); } return(false); }
// This method adds triangles from one data cell into this render cell. Single-texture triangles are added using indices (so we use m_notCompressedIndex buffer). // For this we need to find indices. We use lookup array for it. // Now we support only 16-bit indices, so vertex buffer can't have more then short.MaxValue vertices. public void AddTriangles(List <MyVoxelCacheCellData> cacheDataArray) { // MyPerformanceTimer.VoxelGpuBuffersBuild.Start(); //MyMwcVoxelMaterialsEnum? CurrentSingleMaterial = null; // bool triangleAdded = true; // while (triangleAdded) // { // triangleAdded = false; //CurrentSingleMaterial = null; foreach (var cacheData in cacheDataArray) { // Increase lookup count, so we will think that all vertexes in helper arrays are new for (int i = 0; i < MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount.Length; i++) { MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[i]++; } for (int i = 0; i < cacheData.VoxelTrianglesCount; i++) { MyVoxelTriangle triangle = cacheData.VoxelTriangles[i]; MyVoxelVertex vertex0 = cacheData.VoxelVertices[triangle.VertexIndex0]; MyVoxelVertex vertex1 = cacheData.VoxelVertices[triangle.VertexIndex1]; MyVoxelVertex vertex2 = cacheData.VoxelVertices[triangle.VertexIndex2]; if ((vertex0.Material == vertex1.Material) && (vertex0.Material == vertex2.Material)) { int matIndex = (int)vertex0.Material; // This is single-texture triangleVertexes, so we can choose material from any edge MySingleMaterialHelper materialHelper = MyVoxelCacheCellRenderHelper.GetForMaterial(vertex0.Material); // Add vertex0 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex0, matIndex, triangle.VertexIndex0); // Add vertex1 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex1, matIndex, triangle.VertexIndex1); // Add vertex2 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex2, matIndex, triangle.VertexIndex2); //triangleAdded = true; // Add indices int nextTriangleIndex = materialHelper.IndexCount; materialHelper.Indices[nextTriangleIndex + 0] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][triangle.VertexIndex0].VertexIndex; materialHelper.Indices[nextTriangleIndex + 1] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][triangle.VertexIndex1].VertexIndex; materialHelper.Indices[nextTriangleIndex + 2] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][triangle.VertexIndex2].VertexIndex; materialHelper.IndexCount += 3; if ((materialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP) || (materialHelper.IndexCount >= MyVoxelCacheCellRenderHelper.MAX_INDICES_COUNT_STOP)) { // If this batch is almost full (or is full), we end it and start with new one EndSingleMaterial(materialHelper); } } else { int id = GetMultimaterialId(vertex0.Material, vertex1.Material, vertex2.Material); // Assign current material MyMultiMaterialHelper multiMaterialHelper = MyVoxelCacheCellRenderHelper.GetForMultimaterial(vertex0.Material, vertex1.Material, vertex2.Material); //triangleAdded = true; #if PACKED_VERTEX_FORMAT // Copy packed normals multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 0].PackedNormal = vertex0.PackedNormal; multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 1].PackedNormal = vertex0.PackedNormal; multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 2].PackedNormal = vertex0.PackedNormal; #endif multiMaterialHelper.AddVertex(ref vertex0); multiMaterialHelper.AddVertex(ref vertex1); multiMaterialHelper.AddVertex(ref vertex2); if (multiMaterialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP) { EndMultiMaterial(multiMaterialHelper); } } } /* * if (multiMaterialHelper != null) * { * int id = GetMultimaterialId(multiMaterialHelper.Material0, multiMaterialHelper.Material1, multiMaterialHelper.Material2); * MyVoxelCacheCellRenderHelper.FinishedMultiMaterials[id] = true; * EndMultimaterial(multiMaterialHelper); * } * * if (singleMaterialHelper != null) * { * MyVoxelCacheCellRenderHelper.FinishedSingleMaterials[(int)singleMaterialHelper.Material] = true; * EndSingleMaterial(singleMaterialHelper); * } */ } // } //MyPerformanceTimer.VoxelGpuBuffersBuild.End(); }
public static void StitchDataCells(List<MyVoxelCacheCellData> dataCells) { Vertices.Clear(); Triangles.Clear(); m_verticesMap.Clear(); //int vertexCount = 0; //foreach (MyVoxelCacheCellData dataCell in dataCells) //{ // m_remapHelper.Clear(); // for (int vertexIndex = 0; vertexIndex < dataCell.VoxelVerticesCount; vertexIndex++) // { // var vertex = dataCell.VoxelVertexes[vertexIndex]; // Vertices.Add(vertex); // } // for (int triangleIndex = 0; triangleIndex < dataCell.VoxelTrianglesCount; triangleIndex++) // { // var triangle = dataCell.VoxelTriangles[triangleIndex]; // MyVoxelTriangle32 newTriangle = new MyVoxelTriangle32(); // for (int i = 0; i < 3; i++) // { // var index = triangle[i]; // newTriangle[i] = index + vertexCount; // } // Triangles.Add(newTriangle); // } // vertexCount = Vertices.Count; //} for (int dataCellIndex = 0; dataCellIndex < dataCells.Count; dataCellIndex++) { m_remapHelper.Clear(); var dataCell = dataCells[dataCellIndex]; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Stitch Data Cells - first cycle"); for (int vertexIndex = 0; vertexIndex < dataCell.VoxelVerticesCount; vertexIndex++) { var vertex = dataCell.VoxelVertices[vertexIndex]; short index; if (m_verticesMap.TryGetValue(vertex, out index)) { m_remapHelper.Add(index); } else { Debug.Assert(Vertices.Count < short.MaxValue); m_verticesMap.Add(vertex, (short) Vertices.Count); m_remapHelper.Add((short) Vertices.Count); Vertices.Add(vertex); } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Stitch Data Cells - second cycle"); for (int triangleIndex = 0; triangleIndex < dataCell.VoxelTrianglesCount; triangleIndex++) { var triangle = dataCell.VoxelTriangles[triangleIndex]; MyVoxelTriangle newTriangle = new MyVoxelTriangle(); for (int i = 0; i < 3; i++) { var index = triangle[i]; newTriangle[i] = m_remapHelper[index]; } Triangles.Add(newTriangle); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } }
/// <summary> /// Returns true if triangle has very close to zero surface area. /// </summary> private bool HasZeroSurface(MyVoxelTriangle triangle) { var vertex0 = m_vertices[triangle.VertexIndex0]; var vertex1 = m_vertices[triangle.VertexIndex1]; var vertex2 = m_vertices[triangle.VertexIndex2]; var vector1 = vertex1.Position - vertex0.Position; vector1.Normalize(); var vector2 = vertex2.Position - vertex0.Position; vector2.Normalize(); var dot = Vector3.Dot(vector1, vector2); if (Math.Abs(dot) > 0.9999) return true; return false; }
/// <summary> /// Returns true if the given triangle is defined by less than three distincs vertex indices. /// </summary> private bool IsDegenerated(MyVoxelTriangle triangle) { return triangle.VertexIndex0 == triangle.VertexIndex1 || triangle.VertexIndex0 == triangle.VertexIndex2 || triangle.VertexIndex1 == triangle.VertexIndex2; }
public static void StitchDataCells(List <MyVoxelCacheCellData> dataCells) { Vertices.Clear(); Triangles.Clear(); m_verticesMap.Clear(); //int vertexCount = 0; //foreach (MyVoxelCacheCellData dataCell in dataCells) //{ // m_remapHelper.Clear(); // for (int vertexIndex = 0; vertexIndex < dataCell.VoxelVerticesCount; vertexIndex++) // { // var vertex = dataCell.VoxelVertexes[vertexIndex]; // Vertices.Add(vertex); // } // for (int triangleIndex = 0; triangleIndex < dataCell.VoxelTrianglesCount; triangleIndex++) // { // var triangle = dataCell.VoxelTriangles[triangleIndex]; // MyVoxelTriangle32 newTriangle = new MyVoxelTriangle32(); // for (int i = 0; i < 3; i++) // { // var index = triangle[i]; // newTriangle[i] = index + vertexCount; // } // Triangles.Add(newTriangle); // } // vertexCount = Vertices.Count; //} for (int dataCellIndex = 0; dataCellIndex < dataCells.Count; dataCellIndex++) { m_remapHelper.Clear(); var dataCell = dataCells[dataCellIndex]; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Stitch Data Cells - first cycle"); for (int vertexIndex = 0; vertexIndex < dataCell.VoxelVerticesCount; vertexIndex++) { var vertex = dataCell.VoxelVertices[vertexIndex]; short index; if (m_verticesMap.TryGetValue(vertex, out index)) { m_remapHelper.Add(index); } else { Debug.Assert(Vertices.Count < short.MaxValue); m_verticesMap.Add(vertex, (short)Vertices.Count); m_remapHelper.Add((short)Vertices.Count); Vertices.Add(vertex); } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Stitch Data Cells - second cycle"); for (int triangleIndex = 0; triangleIndex < dataCell.VoxelTrianglesCount; triangleIndex++) { var triangle = dataCell.VoxelTriangles[triangleIndex]; MyVoxelTriangle newTriangle = new MyVoxelTriangle(); for (int i = 0; i < 3; i++) { var index = triangle[i]; newTriangle[i] = m_remapHelper[index]; } Triangles.Add(newTriangle); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } }
public static void WriteVoxelTriangle(MyVoxelTriangle voxelTriangle, BinaryWriter binaryWriter) { binaryWriter.Write(voxelTriangle.VertexIndex0); binaryWriter.Write(voxelTriangle.VertexIndex1); binaryWriter.Write(voxelTriangle.VertexIndex2); }
public void Init(ref MyVoxelVertex[] vertices, ref int vertexCount, ref MyVoxelTriangle[] triangles, ref int triangleCount, out MyVoxelTriangle[] sortedTriangles) { for (int i = 0; i < NODE_COUNT; i++) { m_firstTriangleIndex[i] = 0; m_triangleCount[i] = 0; } for (int i = 0; i < 9; i++) { m_childEmpty[i] = 0; } // compute bounding box { BoundingBox bbox = BoundingBoxHelper.InitialBox; for (int i = 0; i < vertexCount; i++) BoundingBoxHelper.AddPoint(vertices[i].Position, ref bbox); m_bbMin = bbox.Min; var scale = bbox.Max - bbox.Min; m_bbInvScale = Vector3.One; // minimum bounding box size = 1 (in each dimension) if (scale.X > 1) m_bbInvScale.X = 1 / scale.X; if (scale.Y > 1) m_bbInvScale.Y = 1 / scale.Y; if (scale.Z > 1) m_bbInvScale.Z = 1 / scale.Z; } // compute triangle counts for (int i = 0; i < triangleCount; i++) { var t = triangles[i]; BoundingBox bbox = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddTriangle(ref bbox, vertices[t.VertexIndex0].Position, vertices[t.VertexIndex1].Position, vertices[t.VertexIndex2].Position); short count = m_triangleCount[GetNode(ref bbox)]++; } // accumulate triangle counts m_firstTriangleIndex[0] = m_triangleCount[0]; for (int i = 1; i < NODE_COUNT; i++) { m_firstTriangleIndex[i] = (short)(m_firstTriangleIndex[i - 1] + m_triangleCount[i]); } // m_firstTriangleIndex[i] now contains the first index AFTER where the node's triangles will be, e.g.: // m_triangleCount: 2 0 4 3 // m_firstTriangleIndex: 2 2 6 9 // bucketsort triangles into the output array according to the nodes they're in var newSortedTriangles = new MyVoxelTriangle[triangleCount]; for (int i = 0; i < triangleCount; i++) { var t = triangles[i]; BoundingBox bbox = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddTriangle(ref bbox, vertices[t.VertexIndex0].Position, vertices[t.VertexIndex1].Position, vertices[t.VertexIndex2].Position); newSortedTriangles[--m_firstTriangleIndex[GetNode(ref bbox)]] = t; } sortedTriangles = newSortedTriangles; // "out sortedTriangles" may be the same as "triangles" // find empty children for (int i = NODE_COUNT - 1; i > 0; i--) if (m_triangleCount[i] == 0 && (i > 8 || m_childEmpty[i] == 0xFF)) // no triangles AND (no children OR all children empty) m_childEmpty[i - 1 >> 3] |= (byte)(1 << (i - 1 & 7)); }
// This method adds triangles from one data cell into this render cell. Single-texture triangles are added using indices (so we use m_notCompressedIndex buffer). // For this we need to find indices. We use lookup array for it. // Now we support only 16-bit indices, so vertex buffer can't have more then short.MaxValue vertices. public void AddTriangles(List <MyVoxelGeometry.CellData> cacheDataArray) { foreach (var cacheData in cacheDataArray) { // Increase lookup count, so we will think that all vertexes in helper arrays are new for (int i = 0; i < MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount.Length; i++) { MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[i]++; } for (int i = 0; i < cacheData.VoxelTrianglesCount; i++) { MyVoxelTriangle triangle = cacheData.VoxelTriangles[i]; MyVoxelVertex vertex0, vertex1, vertex2; cacheData.GetUnpackedVertex(triangle.VertexIndex0, out vertex0); cacheData.GetUnpackedVertex(triangle.VertexIndex1, out vertex1); cacheData.GetUnpackedVertex(triangle.VertexIndex2, out vertex2); vertex0.Position = (vertex0.Position - m_positionOffset) / m_positionScale; vertex1.Position = (vertex1.Position - m_positionOffset) / m_positionScale; vertex2.Position = (vertex2.Position - m_positionOffset) / m_positionScale; Debug.Assert(vertex0.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One)); Debug.Assert(vertex1.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One)); Debug.Assert(vertex2.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One)); if ((vertex0.Material == vertex1.Material) && (vertex0.Material == vertex2.Material)) { var matDef = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)vertex0.Material); // This is single-texture triangleVertexes, so we can choose material from any edge MySingleMaterialHelper materialHelper = MyVoxelCacheCellRenderHelper.GetForMaterial(matDef); // Add vertex0 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex0, matDef.Index, triangle.VertexIndex0); // Add vertex1 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex1, matDef.Index, triangle.VertexIndex1); // Add vertex2 to vertex buffer AddVertexToBuffer(materialHelper, ref vertex2, matDef.Index, triangle.VertexIndex2); MyVoxelCacheCellRenderHelper.CreateArrayIfNotExist(matDef.Index); // Add indices int nextTriangleIndex = materialHelper.IndexCount; materialHelper.Indices[nextTriangleIndex + 0] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex0].VertexIndex; materialHelper.Indices[nextTriangleIndex + 1] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex1].VertexIndex; materialHelper.Indices[nextTriangleIndex + 2] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex2].VertexIndex; materialHelper.IndexCount += 3; if ((materialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP) || (materialHelper.IndexCount >= MyVoxelCacheCellRenderHelper.MAX_INDICES_COUNT_STOP)) { // If this batch is almost full (or is full), we end it and start with new one EndSingleMaterial(materialHelper); } } else { int id = GetMultimaterialId(vertex0.Material, vertex1.Material, vertex2.Material); // Assign current material MyMultiMaterialHelper multiMaterialHelper = MyVoxelCacheCellRenderHelper.GetForMultimaterial(vertex0.Material, vertex1.Material, vertex2.Material); // Copy packed normals multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 0].Normal = vertex0.Normal; multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 1].Normal = vertex0.Normal; multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 2].Normal = vertex0.Normal; multiMaterialHelper.AddVertex(ref vertex0); multiMaterialHelper.AddVertex(ref vertex1); multiMaterialHelper.AddVertex(ref vertex2); if (multiMaterialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP) { EndMultiMaterial(multiMaterialHelper); } } } } }
internal bool Intersects(ref BoundingSphere sphere) { // Get min and max cell coordinate where boundingBox can fit BoundingBox sphereBoundingBox = BoundingBox.CreateInvalid(); sphereBoundingBox.Include(ref sphere); Vector3I cellCoordMin = GetCellCoordinateFromMeters(ref sphereBoundingBox.Min); Vector3I cellCoordMax = GetCellCoordinateFromMeters(ref sphereBoundingBox.Max); // Fix min and max cell coordinates so they don't overlap the voxelmap FixDataCellCoord(ref cellCoordMin); FixDataCellCoord(ref cellCoordMax); Vector3I cellCoord; for (cellCoord.X = cellCoordMin.X; cellCoord.X <= cellCoordMax.X; cellCoord.X++) { for (cellCoord.Y = cellCoordMin.Y; cellCoord.Y <= cellCoordMax.Y; cellCoord.Y++) { for (cellCoord.Z = cellCoordMin.Z; cellCoord.Z <= cellCoordMax.Z; cellCoord.Z++) { // If no overlap between bounding box of data cell and the sphere BoundingBox cellBoundingBox; GetDataCellBoundingBox(ref cellCoord, out cellBoundingBox); if (cellBoundingBox.Intersects(ref sphere) == false) { continue; } // Get cell from cache. If not there, precalc it and store in the cache. // If null is returned, we know that cell doesn't contain any triangleVertexes so we don't need to do intersections. CellData cachedDataCell = GetCell(MyLodTypeEnum.LOD0, ref cellCoord); if (cachedDataCell == null) { continue; } for (int i = 0; i < cachedDataCell.VoxelTrianglesCount; i++) { MyVoxelTriangle voxelTriangle = cachedDataCell.VoxelTriangles[i]; MyTriangle_Vertexes triangle; cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0); cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1); cachedDataCell.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2); triangle.Vertex0 += m_voxelMap.PositionLeftBottomCorner; triangle.Vertex1 += m_voxelMap.PositionLeftBottomCorner; triangle.Vertex2 += m_voxelMap.PositionLeftBottomCorner; BoundingBox voxelTriangleBoundingBox = BoundingBox.CreateInvalid(); voxelTriangleBoundingBox.Include(ref triangle.Vertex0); voxelTriangleBoundingBox.Include(ref triangle.Vertex1); voxelTriangleBoundingBox.Include(ref triangle.Vertex2); // First test intersection of triangle's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests. if (voxelTriangleBoundingBox.Intersects(ref sphere)) { MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { // If intersection found - we are finished. We don't need to look for more. Profiler.End(); return(true); } } } } } } return(false); }
/// <summary> /// Returns true if the given triangle is defined by less than three distincs vertex indices. /// </summary> private bool IsDegenerated(MyVoxelTriangle triangle) { return(triangle.VertexIndex0 == triangle.VertexIndex1 || triangle.VertexIndex0 == triangle.VertexIndex2 || triangle.VertexIndex1 == triangle.VertexIndex2); }
public void Init(ref MyVoxelVertex[] vertices, ref int vertexCount, ref MyVoxelTriangle[] triangles, ref int triangleCount, out MyVoxelTriangle[] sortedTriangles) { for (int i = 0; i < NODE_COUNT; i++) { m_firstTriangleIndex[i] = 0; m_triangleCount[i] = 0; } for (int i = 0; i < 9; i++) { m_childEmpty[i] = 0; } // compute bounding box { BoundingBox bbox = BoundingBoxHelper.InitialBox; for (int i = 0; i < vertexCount; i++) { BoundingBoxHelper.AddPoint(vertices[i].Position, ref bbox); } m_bbMin = bbox.Min; var scale = bbox.Max - bbox.Min; m_bbInvScale = Vector3.One; // minimum bounding box size = 1 (in each dimension) if (scale.X > 1) { m_bbInvScale.X = 1 / scale.X; } if (scale.Y > 1) { m_bbInvScale.Y = 1 / scale.Y; } if (scale.Z > 1) { m_bbInvScale.Z = 1 / scale.Z; } } // compute triangle counts for (int i = 0; i < triangleCount; i++) { var t = triangles[i]; BoundingBox bbox = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddTriangle(ref bbox, vertices[t.VertexIndex0].Position, vertices[t.VertexIndex1].Position, vertices[t.VertexIndex2].Position); short count = m_triangleCount[GetNode(ref bbox)]++; } // accumulate triangle counts m_firstTriangleIndex[0] = m_triangleCount[0]; for (int i = 1; i < NODE_COUNT; i++) { m_firstTriangleIndex[i] = (short)(m_firstTriangleIndex[i - 1] + m_triangleCount[i]); } // m_firstTriangleIndex[i] now contains the first index AFTER where the node's triangles will be, e.g.: // m_triangleCount: 2 0 4 3 // m_firstTriangleIndex: 2 2 6 9 // bucketsort triangles into the output array according to the nodes they're in var newSortedTriangles = new MyVoxelTriangle[triangleCount]; for (int i = 0; i < triangleCount; i++) { var t = triangles[i]; BoundingBox bbox = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddTriangle(ref bbox, vertices[t.VertexIndex0].Position, vertices[t.VertexIndex1].Position, vertices[t.VertexIndex2].Position); newSortedTriangles[--m_firstTriangleIndex[GetNode(ref bbox)]] = t; } sortedTriangles = newSortedTriangles; // "out sortedTriangles" may be the same as "triangles" // find empty children for (int i = NODE_COUNT - 1; i > 0; i--) { if (m_triangleCount[i] == 0 && (i > 8 || m_childEmpty[i] == 0xFF)) // no triangles AND (no children OR all children empty) { m_childEmpty[i - 1 >> 3] |= (byte)(1 << (i - 1 & 7)); } } }