protected Vector3D?GetFreeSpacePlacementPosition(bool copyPaste, out bool buildAllowed) { Vector3D?freePlacementIntersectionPoint = null; buildAllowed = false; float gridSize = PreviewGrids[0].GridSize; double shortestDistance = double.MaxValue; double?currentRayInts = GetCurrentRayIntersection(); if (currentRayInts.HasValue) { shortestDistance = currentRayInts.Value; } Vector3D worldRefPointOffset = Vector3D.Zero; if (copyPaste) { Matrix firstGridOrientation = GetFirstGridOrientationMatrix(); worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation); } Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero); Matrix blockWorlTransform; foreach (var block in PreviewGrids[0].GetBlocks()) { Vector3 halfExt = block.BlockDefinition.Size * PreviewGrids[0].GridSize * 0.5f; Vector3 minLocal = block.Min * PreviewGrids[0].GridSize - Vector3.Half * PreviewGrids[0].GridSize; Vector3 maxLocal = block.Max * PreviewGrids[0].GridSize + Vector3.Half * PreviewGrids[0].GridSize; block.Orientation.GetMatrix(out blockWorlTransform); blockWorlTransform.Translation = 0.5f * (minLocal + maxLocal); blockWorlTransform = blockWorlTransform * PreviewGrids[0].WorldMatrix; Vector3D offset = blockWorlTransform.Translation + worldRefPointOffset - worldRefPoint; HkShape shape = new HkBoxShape(halfExt); Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset; double castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart); rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection; Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset; MatrixD matrix = blockWorlTransform; matrix.Translation = rayStart; try { float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayerWithoutCharacter); if (dist.HasValue && dist.Value != 0f) { Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart); const bool debugDraw = false; if (debugDraw) { Color green = Color.Green; BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt); MatrixD drawMatrix = matrix; drawMatrix.Translation = intersectionPoint; MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); } double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart; if (fixedDistance <= 0) { fixedDistance = 0; shortestDistance = 0; break; } if (fixedDistance < shortestDistance) { shortestDistance = fixedDistance; } buildAllowed = true; } } finally { shape.RemoveReference(); } } float boxRadius = (float)PreviewGrids[0].PositionComp.WorldAABB.HalfExtents.Length(); float dragDistance = 1.5f * boxRadius; if (shortestDistance < dragDistance) { shortestDistance = dragDistance; buildAllowed = false; } if (shortestDistance < m_dragDistance) { freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection; } return(freePlacementIntersectionPoint); }
/// <summary> /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null. /// </summary> protected Vector3D?GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed) { Vector3D?freePlacementIntersectionPoint = null; buildAllowed = true; float gridSize = PreviewGrids[0].GridSize; double shortestDistance = double.MaxValue; double?currentRayInts = MyCubeBuilder.GetCurrentRayIntersection(); if (currentRayInts.HasValue) { shortestDistance = currentRayInts.Value; } Vector3D worldRefPointOffset = Vector3D.Zero; if (copyPaste) { Matrix firstGridOrientation = GetFirstGridOrientationMatrix(); worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation); } Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero); foreach (var grid in PreviewGrids) { Vector3 halfExt = grid.PositionComp.LocalAABB.HalfExtents; Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize; Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize; MatrixD gridWorlTransform = MatrixD.Identity; gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal); gridWorlTransform = gridWorlTransform * grid.WorldMatrix; Vector3I size = grid.Max - grid.Min + Vector3I.One; Vector3 sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize; sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix); Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint; HkShape shape = new HkBoxShape(halfExt); Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset; double castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart); rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection; Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset; MatrixD matrix = gridWorlTransform; matrix.Translation = rayStart; try { float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter); if (dist.HasValue && dist.Value != 0f) { Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart); const bool debugDraw = true; if (debugDraw) { Color green = Color.Green; BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt); localAABB.Inflate(0.03f); MatrixD drawMatrix = matrix; drawMatrix.Translation = intersectionPoint; MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); } double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart; if (fixedDistance <= 0) { fixedDistance = 0; shortestDistance = 0; buildAllowed = false; break; } if (fixedDistance < shortestDistance) { shortestDistance = fixedDistance; } } else { buildAllowed = false; } } finally { shape.RemoveReference(); } } if (shortestDistance != 0 && shortestDistance < m_dragDistance) { freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection; } else { buildAllowed = false; } return(freePlacementIntersectionPoint); }