コード例 #1
0
        protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos)
        {
            bool result = false;

            addPos    = new Vector3I();
            addDir    = new Vector3I();
            removePos = new Vector3I();

            MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix);

            Vector3D intersectionPos;

            addPos = intersectedCube;
            addDir = Vector3I.Forward;

            Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv);
            Vector3D rayDir   = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv));

            RayD r = new RayD(rayStart, rayDir);

            for (int i = 0; i < 100; ++i) // Limit iterations to 100
            {
                var cubeBb = GetCubeBoundingBox(addPos);
                if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains)
                {
                    break;
                }

                double?dist = cubeBb.Intersects(r);
                if (!dist.HasValue)
                {
                    break;
                }

                removePos = addPos;

                intersectionPos = rayStart + rayDir * dist.Value;
                Vector3  center = removePos * CurrentGrid.GridSize;
                Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center));

                addPos = removePos + dirInt;
                addDir = dirInt;
                result = true;

                if (!CurrentGrid.CubeExists(addPos))
                {
                    break;
                }
            }

            Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero");
            return(result);
        }
コード例 #2
0
        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);
        }