/// <summary> /// Calculates exact intersection point (in uniform grid coordinates) from stored havok's hit info object obtained during FindClosest grid. /// Returns position of intersected object in uniform grid coordinates. /// </summary> protected Vector3D?GetIntersectedBlockData(ref MatrixD inverseGridWorldMatrix, out Vector3D intersection, out MySlimBlock intersectedBlock, out ushort?compoundBlockId) { Debug.Assert(m_hitInfo != null); Debug.Assert(m_hitInfo.Value.HkHitInfo.Body.GetEntity() == CurrentGrid); intersection = Vector3D.Zero; intersectedBlock = null; compoundBlockId = null; double distance = double.MaxValue; Vector3D?intersectedObjectPos = null; var line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * IntersectionDistance); Vector3I position = Vector3I.Zero; if (!CurrentGrid.GetLineIntersectionExactGrid(ref line, ref position, ref distance, m_hitInfo.Value)) { return(null); } distance = Math.Sqrt(distance); intersectedObjectPos = position; intersectedBlock = CurrentGrid.GetCubeBlock(position); if (intersectedBlock == null) { return(null); } // Compound block - get index of internal block for removing if (intersectedBlock.FatBlock is MyCompoundCubeBlock) { MyCompoundCubeBlock compoundBlock = intersectedBlock.FatBlock as MyCompoundCubeBlock; ushort?idInCompound = null; ushort blockId; MyIntersectionResultLineTriangleEx?triIntersection; if (compoundBlock.GetIntersectionWithLine(ref line, out triIntersection, out blockId)) { idInCompound = blockId; } else if (compoundBlock.GetBlocksCount() == 1) // If not intersecting with any internal block and there is only one then set the index to it { idInCompound = compoundBlock.GetBlockId(compoundBlock.GetBlocks()[0]); } compoundBlockId = idInCompound; } Debug.Assert(intersectedObjectPos != null); Vector3D rayStart = Vector3D.Transform(IntersectionStart, inverseGridWorldMatrix); Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, inverseGridWorldMatrix)); intersection = rayStart + distance * rayDir; intersection *= 1.0f / CurrentGrid.GridSize; return(intersectedObjectPos); }
protected bool GetBlockAddPosition(float gridSize, bool placingSmallGridOnLargeStatic, out MySlimBlock intersectedBlock, out Vector3D intersectedBlockPos, out Vector3D intersectExactPos, out Vector3I addPositionBlock, out Vector3I addDirectionBlock, out ushort?compoundBlockId) { intersectedBlock = null; intersectedBlockPos = new Vector3D(); intersectExactPos = new Vector3(); addDirectionBlock = new Vector3I(); addPositionBlock = new Vector3I(); compoundBlockId = null; if (CurrentVoxelBase != null) { Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal; Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal); Vector3I hitNormal = Base6Directions.GetIntVector(closestDir); double distance = IntersectionDistance * m_hitInfo.Value.HkHitInfo.HitFraction; Vector3D rayStart = IntersectionStart; Vector3D rayDir = Vector3D.Normalize(IntersectionDirection); Vector3D intersection = rayStart + distance * rayDir; // Get cube block placement position (add little threshold to hit normal direction to avoid wavy surfaces). addPositionBlock = MyCubeGrid.StaticGlobalGrid_WorldToUGInt(intersection + 0.1f * Vector3.Half * hitNormal * gridSize, gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter); addDirectionBlock = hitNormal; intersectedBlockPos = addPositionBlock - hitNormal; // Exact intersection in uniform grid coords. intersectExactPos = MyCubeGrid.StaticGlobalGrid_WorldToUG(intersection, gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter); // Project exact intersection to cube face of intersected block. intersectExactPos = ((Vector3.One - Vector3.Abs(hitNormal)) * intersectExactPos) + ((intersectedBlockPos + 0.5f * hitNormal) * Vector3.Abs(hitNormal)); return(true); } Vector3D?intersectedObjectPos = GetIntersectedBlockData(ref m_invGridWorldMatrix, out intersectExactPos, out intersectedBlock, out compoundBlockId); if (intersectedObjectPos == null) { return(false); } intersectedBlockPos = intersectedObjectPos.Value; Vector3I removePos; if (!GetCubeAddAndRemovePositions(Vector3I.Round(intersectedBlockPos), placingSmallGridOnLargeStatic, out addPositionBlock, out addDirectionBlock, out removePos)) { return(false); } if (!placingSmallGridOnLargeStatic) { if (MyFakes.ENABLE_BLOCK_PLACING_ON_INTERSECTED_POSITION) { Vector3I newRemovepos = Vector3I.Round(intersectedBlockPos); if (newRemovepos != removePos) { if (m_hitInfo.HasValue) { Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal; Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal); Vector3I hitNormal = Base6Directions.GetIntVector(closestDir); addDirectionBlock = hitNormal; } removePos = newRemovepos; addPositionBlock = removePos + addDirectionBlock; } } else { if (CurrentGrid.CubeExists(addPositionBlock)) { return(false); } } } if (placingSmallGridOnLargeStatic) { removePos = Vector3I.Round(intersectedBlockPos); } intersectedBlockPos = removePos; intersectedBlock = CurrentGrid.GetCubeBlock(removePos); if (intersectedBlock == null) { Debug.Assert(false, "No intersected block"); return(false); } return(true); }
/// <summary> /// Calculates exact intersection point (in uniform grid coordinates) from stored havok's hit info object obtained during FindClosest grid. /// Returns position of intersected object in uniform grid coordinates. /// </summary> protected Vector3D?GetIntersectedBlockData(ref MatrixD inverseGridWorldMatrix, out Vector3D intersection, out MySlimBlock intersectedBlock, out ushort?compoundBlockId) { Debug.Assert(m_hitInfo != null); Debug.Assert(m_hitInfo.Value.HkHitInfo.Body.GetEntity() == CurrentGrid); intersection = Vector3D.Zero; intersectedBlock = null; compoundBlockId = null; double distance = double.MaxValue; Vector3D?intersectedObjectPos = null; var line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * IntersectionDistance); Vector3I position = Vector3I.Zero; if (!CurrentGrid.GetLineIntersectionExactGrid(ref line, ref position, ref distance, m_hitInfo.Value)) { return(null); } distance = Math.Sqrt(distance); intersectedObjectPos = position; intersectedBlock = CurrentGrid.GetCubeBlock(position); if (intersectedBlock == null) { return(null); } // Compound block - get index of internal block for removing if (intersectedBlock.FatBlock is MyCompoundCubeBlock) { MyCompoundCubeBlock compoundBlock = intersectedBlock.FatBlock as MyCompoundCubeBlock; ListReader <MySlimBlock> slimBlocksInCompound = compoundBlock.GetBlocks(); double distanceSquaredInCompound = double.MaxValue; ushort?idInCompound = null; for (int i = 0; i < slimBlocksInCompound.Count; ++i) { MySlimBlock cmpSlimBlock = slimBlocksInCompound.ItemAt(i); MyIntersectionResultLineTriangleEx?intersectionTriResult; if (cmpSlimBlock.FatBlock.GetIntersectionWithLine(ref line, out intersectionTriResult) && intersectionTriResult != null) { Vector3D startToIntersection = intersectionTriResult.Value.IntersectionPointInWorldSpace - IntersectionStart; double instrDistanceSq = startToIntersection.LengthSquared(); if (instrDistanceSq < distanceSquaredInCompound) { distanceSquaredInCompound = instrDistanceSq; idInCompound = compoundBlock.GetBlockId(cmpSlimBlock); } } } // If not intersecting with any internal block and there is only one then set the index to it if (idInCompound == null && compoundBlock.GetBlocksCount() == 1) { idInCompound = compoundBlock.GetBlockId(compoundBlock.GetBlocks()[0]); } compoundBlockId = idInCompound; } Debug.Assert(intersectedObjectPos != null); Vector3D rayStart = Vector3D.Transform(IntersectionStart, inverseGridWorldMatrix); Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, inverseGridWorldMatrix)); intersection = rayStart + distance * rayDir; intersection *= 1.0f / CurrentGrid.GridSize; return(intersectedObjectPos); }