public MovementPlanner.MovementNode GenerateNode(Vector3D position, double facingAngle, double desiredSpeed, Vector3D goal) { var groundPlane = new PlaneD(CurrentLocation, UpDirection); var referencePoint = new Vector3D(position); var projectedPoint = groundPlane.ProjectPoint(ref referencePoint); var projectedX = (projectedPoint - CurrentLocation).Dot(X_Axis); var projectedY = (projectedPoint - CurrentLocation).Dot(Y_Axis); var projectedPosition = new Vector2D(projectedX, projectedY); referencePoint = new Vector3D(goal); projectedPoint = groundPlane.ProjectPoint(ref referencePoint); projectedX = (projectedPoint - CurrentLocation).Dot(X_Axis); projectedY = (projectedPoint - CurrentLocation).Dot(Y_Axis); var projectedGoal = new Vector2D(projectedX, projectedY); return(GenerateNode(projectedPosition, facingAngle, desiredSpeed, projectedGoal)); }
/// <summary> /// Generates a movement planner from a terrain map with a valid up direction. /// </summary> /// <remarks>Does not copy points. Must be done before adding any points.</remarks> public void GenerateMovementPlanner() { var groundPlane = new PlaneD(CurrentLocation, UpDirection); var referenceCenter = new Vector3D(terrainMap_.Center); var projectedCenter = groundPlane.ProjectPoint(ref referenceCenter); var projectedCenterX = (projectedCenter - CurrentLocation).Dot(X_Axis); var projectedCenterY = (projectedCenter - CurrentLocation).Dot(Y_Axis); var flatCenter = new Vector2D(projectedCenterX, projectedCenterY); var referenceExtents = new Vector3D(terrainMap_.Extents); var projectedExtents = groundPlane.ProjectPoint(ref referenceExtents); var maxExtent = Math.Abs((projectedExtents - CurrentLocation).Dot(X_Axis)); maxExtent = Math.Max(maxExtent, Math.Abs((projectedExtents - CurrentLocation).Dot(Y_Axis))); var flatExtents = new Vector2D(maxExtent, maxExtent); movementPlanner_ = new MovementPlanner(flatCenter, flatExtents); }
private static Vector3D CollideWithTriangles(BoundingSphereD sphere, Vector3D velocity, Triangle[] triangles, int recurssionDepth) { if (recurssionDepth > MAX_RECURSSION_DEPTH) { return(Vector3D.Zero); } CollisionResult collision = CollidesWith(sphere, triangles, velocity); if (!collision.FoundCollision) { return(velocity); } Vector3D originalDestinationPoint = sphere.Center + velocity; double intersectionDistance = velocity.Length() * collision.IntersectionTime; //Only update if we aren't very close, and if so only move very close //if (intersectionDistance >= VeryCloseDistance) //{ Vector3D normalizedVelocity = velocity.Normalized(); velocity = (intersectionDistance - VeryCloseDistance) * normalizedVelocity; sphere.Center += velocity; //Fake the collision results to match the very close approximation collision.IntersectionPoint -= normalizedVelocity * VeryCloseDistance; //} PlaneD slidingPlane = CollisionExtensions.Plane(collision.IntersectionPoint, sphere.Center - collision.IntersectionPoint); Vector3D destinationPoint = originalDestinationPoint.ProjectOn(slidingPlane); Vector3D newVelocityVector = destinationPoint - collision.IntersectionPoint; if (newVelocityVector.Length() < VeryCloseDistance) { return(velocity); } return(velocity + CollideWithTriangles(sphere, newVelocityVector, triangles, recurssionDepth + 1)); }
public static Vector3D GetXYZDistance(IMyTerminalBlock block, Vector3D targetPos) { Vector3D myPos = block.GetPosition(); Vector3D targetVector = Vector3D.Subtract(targetPos, myPos); double targetDistance = targetVector.Length(); targetVector.Normalize(); PlaneD forwardReversePlane = new PlaneD(block.WorldMatrix.Forward, 0); PlaneD leftRightPlane = new PlaneD(block.WorldMatrix.Left, 0); PlaneD upDownPlane = new PlaneD(block.WorldMatrix.Up, 0); float forwardReverseDistance = Convert.ToSingle(Math.Sin(forwardReversePlane.DotNormal(targetVector)) * targetDistance); float leftRightDistance = Convert.ToSingle(Math.Sin(leftRightPlane.DotNormal(targetVector)) * targetDistance); float upDownDistance = Convert.ToSingle(Math.Sin(upDownPlane.DotNormal(targetVector)) * targetDistance); Vector3D xyzDistance = new Vector3D(); xyzDistance.X = leftRightDistance; xyzDistance.Y = forwardReverseDistance; xyzDistance.Z = upDownDistance; return(xyzDistance); }
public bool Intersects(ref BoundingSphereD localSphere) { MyPrecalcComponent.AssertUpdateThread(); // Get min and max cell coordinate where boundingBox can fit BoundingBoxD sphereBoundingBox = BoundingBoxD.CreateInvalid(); sphereBoundingBox.Include(ref localSphere); Vector3I cellCoordMin, cellCoordMax; { Vector3D minD = sphereBoundingBox.Min; Vector3D maxD = sphereBoundingBox.Max; MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref minD, out cellCoordMin); MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref maxD, out cellCoordMax); } // Fix min and max cell coordinates so they don't overlap the voxelmap ClampCellCoord(ref cellCoordMin); ClampCellCoord(ref cellCoordMax); MyCellCoord cell = new MyCellCoord(); for (cell.CoordInLod.X = cellCoordMin.X; cell.CoordInLod.X <= cellCoordMax.X; cell.CoordInLod.X++) { for (cell.CoordInLod.Y = cellCoordMin.Y; cell.CoordInLod.Y <= cellCoordMax.Y; cell.CoordInLod.Y++) { for (cell.CoordInLod.Z = cellCoordMin.Z; cell.CoordInLod.Z <= cellCoordMax.Z; cell.CoordInLod.Z++) { // If no overlap between bounding box of data cell and the sphere BoundingBox cellBoundingBox; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox); if (cellBoundingBox.Intersects(ref localSphere) == 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 cachedData = GetCell(ref cell); if (cachedData == null) { continue; } for (int i = 0; i < cachedData.VoxelTrianglesCount; i++) { MyVoxelTriangle voxelTriangle = cachedData.VoxelTriangles[i]; MyTriangle_Vertexes triangle; cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2); BoundingBox localTriangleAABB = BoundingBox.CreateInvalid(); localTriangleAABB.Include(ref triangle.Vertex0); localTriangleAABB.Include(ref triangle.Vertex1); localTriangleAABB.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 (localTriangleAABB.Intersects(ref localSphere)) { PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref localSphere, ref trianglePlane, ref triangle) != null) { // If intersection found - we are finished. We don't need to look for more. return(true); } } } } } } return(false); }
public bool GetIntersectionWithSphere(IMyEntity entity, ref BoundingSphereD sphere) { // Transform sphere from world space to object space MatrixD worldInv = entity.PositionComp.WorldMatrixNormalizedInv; Vector3 positionInObjectSpace = (Vector3)Vector3D.Transform(sphere.Center, ref worldInv); BoundingSphereD sphereInObjectSpace = new BoundingSphereD(positionInObjectSpace, (float)sphere.Radius); var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphereInObjectSpace; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); m_overlappedTriangles.Clear(); if (m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles)) { // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphereInObjectSpace)) { // See that we swaped vertex indices!! MyTriangle_Vertices triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphereInObjectSpace, ref trianglePlane, ref triangle) != null) { // If we found intersection we can stop and dont need to look further return true; } } } } return false; }
public void CollectData() { //Rectangle3D rect = new Rectangle3D(new Vector3D(-5, 0, -5), new Vector3D(5, 0, 5), new PlaneD(new Vector3D(0, 1, 0), 0)); //Vector3D iPoint; //bool result = rect.IntersectWithLine(new Vector3D(5, 5, 0), new Vector3D(0, -1, 0), out iPoint); // create frame buffer to store data buffer = new FrameData(viewArea.Width, viewArea.Height, false, Color.Black); CameraView cView = new CameraView(); cView.Centre = new Vector3D(3, 5, 3); cView.Direction = cView.Centre - new Vector3D(0, 0, 0); cView.Direction.Normalize(); cView.XUV = Vector3D.Cross(cView.Direction, Vector3D.Up); cView.XUV.Normalize(); cView.YUV = Vector3D.Cross(cView.XUV, cView.Direction); cView.YUV.Normalize(); cView.ViewArea = new Vector2D(1, 1); Vector3D halfX = cView.XUV * 0.5 * cView.ViewArea.X; Vector3D halfY = cView.YUV * 0.5 * cView.ViewArea.Y; cView.Corners = new Vector3D[] { cView.Centre - halfX + halfY, // top left cView.Centre + halfX + halfY, // top right cView.Centre - halfX - halfY, // bottom left cView.Centre + halfX - halfY // bottom right }; cView.Frustum = new PlaneD[] { PlaneD.FromPointNormal(cView.Corners[0], -cView.XUV), PlaneD.FromPointNormal(cView.Corners[1], cView.XUV), PlaneD.FromPointNormal(cView.Corners[2], cView.YUV), PlaneD.FromPointNormal(cView.Corners[3], -cView.YUV) }; cView.Area = viewArea; cView.ProjectionScale = new Vector2D(0.2, 0.2); texture = Bitmap.FromFile("c:/checkers2.bmp"); //Bitmap texture2 = (Bitmap)Bitmap.FromFile("c:/newheightmap.jpg"); // setup temp scene SimpleSceneManager scene = new SimpleSceneManager(new RGBA_D(0.2, 0.2, 0.2, 1)); /*scene.AddObject(new TriangleGroupSceneObject(new Vector3D(0, 0, 2), * new MaterialShader(new RGBA_D(1, 1, 1, 1), * 15, 0.1, 0, 0, 1), * 1.1));*/ /*scene.AddObject(new SphereSceneObject(new Vector3D(0, 0, 0), * new MaterialShader(new RGBA_D(0, 0, 1, 1), * 15, 0, 0, 0, 1), * 1));*/ /*scene.AddObject(new SphereSceneObject(new Vector3D(0, 0, 0), * new MaterialShader(new RGBA_D(1, 0, 0, 1), * 15, 1, 0, 0, 1), * 1)); * scene.AddObject(new SphereSceneObject(new Vector3D(-3, -1, -3), * new MaterialShader(new RGBA_D(0.2, 1, 0.1, 1), * 15, 0, 0, 0, 1, texture2), * 1)); * scene.AddObject(new SphereSceneObject(new Vector3D(2, 0, 0), * new MaterialShader(new RGBA_D(1, 1, 0, 1), * 10, 0.1, 0, 0, 1), * 1)); * scene.AddObject(new SphereSceneObject(new Vector3D(0.5, 1, 0), * new MaterialShader(new RGBA_D(1, 1, 1, 1), * 5, 0, 0, 0, 1, texture), * 0.8)); * * scene.AddObject(new PlaneSceneObject(new Vector3D(0, -5, 0), new Vector3D(0, 1, 0), * new MaterialShader(new RGBA_D(0.1, 0.1, 0.1, 1.0), * 5, 0, 0, 0, 1), -1)); */ scene.AddObject(new HeightFieldObject(new Vector3D(), new MaterialShader(new RGBA_D(1, 1, 1, 1), 5, 0, 0, 0, 1, texture), new Vector2D(2, 2), (Bitmap)texture)); /* * IOpticalSceneObject obj; * Vector3D iPos; * double iDist; * uint subIdx; * scene.GetFirstIntersection(new Vector3D(10, 0.5, 0), new Vector3D(1, 0, 0), 100, out obj, out iPos, out iDist, out subIdx); */ // collect data DateTime start = DateTime.Now; RayGroup initialGroup = new RayGroup(true, 100, cView.Area, scene, null, buffer, cView); rayDispatch.DispatchRayGroupReq(initialGroup); rayDispatch.WaitForCompletion(); DateTime end = DateTime.Now; TimeSpan time = end - start; string aaFilter = buffer.AALayer != null ? "true[5_point_star]" : "false"; stats = string.Format("threads={0} rays={1} pixels={2} time={3}ms AA={4}", rayDispatch.ProcessedThreads, rayDispatch.ProcessedRays, viewArea.Width * viewArea.Height, time.TotalMilliseconds, aaFilter); }
public override void Draw() { ProfilerShort.Begin("base.Draw()"); base.Draw(); ProfilerShort.BeginNextBlock("DebugDraw"); DebugDraw(); if (BlockCreationIsActivated) { MyHud.Crosshair.Recenter(); } if (!IsActivated || CurrentBlockDefinition == null) { this.ClearRenderData(); ProfilerShort.End(); return; } this.DrawGuiIndicators(); if (!BuildInputValid) { this.ClearRenderData(); ProfilerShort.End(); return; } ProfilerShort.BeginNextBlock("DrawBuildingStepsCount"); DrawBuildingStepsCount(m_gizmo.SpaceDefault.m_startBuild, m_gizmo.SpaceDefault.m_startRemove, m_gizmo.SpaceDefault.m_continueBuild, ref m_gizmo.SpaceDefault.m_localMatrixAdd); ProfilerShort.End(); bool addPos = m_gizmo.SpaceDefault.m_startBuild.HasValue; bool removePos = false; float gridSize = 0; if (CurrentBlockDefinition != null) gridSize = MyDefinitionManager.Static.GetCubeSize(CurrentBlockDefinition.CubeSize); if (DynamicMode) { PlaneD cameraPlane = new PlaneD(MySector.MainCamera.Position, MySector.MainCamera.UpVector); Vector3D projectedPoint = IntersectionStart; projectedPoint = cameraPlane.ProjectPoint(ref projectedPoint); Vector3D freePlacementIntersectionPoint = projectedPoint + IntersectionDistance * IntersectionDirection; if (m_hitInfo != null) freePlacementIntersectionPoint = m_hitInfo.Value.Position; addPos = this.CaluclateDynamicModePos(freePlacementIntersectionPoint, IsDynamicOverride()); MyCoordinateSystem.Static.Visible = false; } else { if (m_gizmo.SpaceDefault.m_startBuild == null && m_gizmo.SpaceDefault.m_startRemove == null) { if (!FreezeGizmo) { if (CurrentGrid != null) { MyCoordinateSystem.Static.Visible = false; ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for grid"); addPos = GetAddAndRemovePositions(gridSize, PlacingSmallGridOnLargeStatic, out m_gizmo.SpaceDefault.m_addPos, out m_gizmo.SpaceDefault.m_addPosSmallOnLarge, out m_gizmo.SpaceDefault.m_addDir, out m_gizmo.SpaceDefault.m_removePos, out m_gizmo.SpaceDefault.m_removeBlock, out m_gizmo.SpaceDefault.m_blockIdInCompound, m_gizmo.SpaceDefault.m_removeBlocksInMultiBlock); if (addPos) { if (PlacingSmallGridOnLargeStatic) m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPosSmallOnLarge.Value; else m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPos; m_gizmo.SpaceDefault.m_worldMatrixAdd = m_gizmo.SpaceDefault.m_localMatrixAdd * CurrentGrid.WorldMatrix; var normal = GetSingleMountPointNormal(); // Gizmo add dir can be zero in some cases if (normal.HasValue && GridAndBlockValid && m_gizmo.SpaceDefault.m_addDir != Vector3I.Zero) { m_gizmo.SetupLocalAddMatrix(m_gizmo.SpaceDefault, normal.Value); } } ProfilerShort.End(); } else { MyCoordinateSystem.Static.Visible = true; ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for voxel"); Vector3D localSnappedPos = m_lastLocalCoordSysData.LocalSnappedPos; if (!CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter) localSnappedPos -= new Vector3D(0.5 * gridSize, 0.5 * gridSize, -0.5 * gridSize); Vector3I gridCoord = Vector3I.Round(localSnappedPos / gridSize); m_gizmo.SpaceDefault.m_addPos = gridCoord; m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_lastLocalCoordSysData.LocalSnappedPos; m_gizmo.SpaceDefault.m_worldMatrixAdd = m_lastLocalCoordSysData.Origin.TransformMatrix; addPos = true; ProfilerShort.End(); } } Debug.Assert(!m_gizmo.SpaceDefault.m_worldMatrixAdd.IsNan(), "Invalid gizmo matrix"); if (m_gizmo.SpaceDefault.m_removeBlock != null) removePos = true; } } ProfilerShort.Begin("buildingDisabledByCockpit"); bool buildingDisabledByCockpit = MySession.Static.ControlledEntity != null && MySession.Static.ControlledEntity is MyCockpit && !SpectatorIsBuilding; if (!buildingDisabledByCockpit) { if (IsInSymmetrySettingMode) { m_gizmo.SpaceDefault.m_continueBuild = null; addPos = false; removePos = false; if (m_gizmo.SpaceDefault.m_removeBlock != null) { var min = (m_gizmo.SpaceDefault.m_removeBlock.Min * CurrentGrid.GridSize); var max = (m_gizmo.SpaceDefault.m_removeBlock.Max * CurrentGrid.GridSize); Vector3 center = (min + max) * 0.5f; Color color = DrawSymmetryPlane(m_symmetrySettingMode, CurrentGrid, center); DrawSemiTransparentBox(CurrentGrid, m_gizmo.SpaceDefault.m_removeBlock, color.ToVector4()); } } if (CurrentGrid != null && (UseSymmetry || IsInSymmetrySettingMode)) { if (CurrentGrid.XSymmetryPlane != null) { Vector3 center = CurrentGrid.XSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.XSymmetryOdd ? MySymmetrySettingModeEnum.XPlaneOdd : MySymmetrySettingModeEnum.XPlane, CurrentGrid, center); } if (CurrentGrid.YSymmetryPlane != null) { Vector3 center = CurrentGrid.YSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.YSymmetryOdd ? MySymmetrySettingModeEnum.YPlaneOdd : MySymmetrySettingModeEnum.YPlane, CurrentGrid, center); } if (CurrentGrid.ZSymmetryPlane != null) { Vector3 center = CurrentGrid.ZSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.ZSymmetryOdd ? MySymmetrySettingModeEnum.ZPlaneOdd : MySymmetrySettingModeEnum.ZPlane, CurrentGrid, center); } } } ProfilerShort.BeginNextBlock("UpdateGizmos"); UpdateGizmos(addPos, removePos, true); ProfilerShort.BeginNextBlock("UpdateRenderInstanceData"); m_renderData.UpdateRenderInstanceData(); ProfilerShort.BeginNextBlock("CurrentVoxelBase"); if (CurrentGrid == null || (DynamicMode && CurrentGrid != null)) { MatrixD drawMatrix = m_gizmo.SpaceDefault.m_worldMatrixAdd; Vector3D rotatedModelOffset; Vector3D.TransformNormal(ref CurrentBlockDefinition.ModelOffset, ref drawMatrix, out rotatedModelOffset); drawMatrix.Translation = drawMatrix.Translation + rotatedModelOffset; m_renderData.UpdateRenderEntitiesData(drawMatrix, UseTransparency, CurrentBlockScale); } else { m_renderData.UpdateRenderEntitiesData(CurrentGrid.WorldMatrix, UseTransparency); } ProfilerShort.BeginNextBlock("UpdateBlockInfoHud"); UpdateBlockInfoHud(); ProfilerShort.End(); }
public void GetTrianglesIntersectingSphere(ref BoundingSphereD sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphere; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); m_overlappedTriangles.Clear(); if (m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles)) { // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; //MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; m_model.GetVertex(triangleIndices.I0, triangleIndices.I2, triangleIndices.I1, out triangle.Vertex0, out triangle.Vertex1, out triangle.Vertex2); /* * triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); * triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); * triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); */ triangleNormals.Normal0 = m_model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = m_model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = m_model.GetVertexNormal(triangleIndices.I1); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertices = triangle; retTriangle.Normals = triangleNormals; retTriangles.Add(retTriangle); } } } } } } }
public override void Draw() { ProfilerShort.Begin("base.Draw()"); base.Draw(); ProfilerShort.BeginNextBlock("DebugDraw"); DebugDraw(); if (BlockCreationIsActivated) { MyHud.Crosshair.Recenter(); } if (!IsActivated || CurrentBlockDefinition == null) { this.ClearRenderData(); ProfilerShort.End(); return; } this.DrawGuiIndicators(); if (!BuildInputValid) { this.ClearRenderData(); ProfilerShort.End(); return; } ProfilerShort.BeginNextBlock("DrawBuildingStepsCount"); DrawBuildingStepsCount(m_gizmo.SpaceDefault.m_startBuild, m_gizmo.SpaceDefault.m_startRemove, m_gizmo.SpaceDefault.m_continueBuild, ref m_gizmo.SpaceDefault.m_localMatrixAdd); ProfilerShort.End(); bool addPos = m_gizmo.SpaceDefault.m_startBuild.HasValue; bool removePos = false; float gridSize = 0; if (CurrentBlockDefinition != null) { gridSize = MyDefinitionManager.Static.GetCubeSize(CurrentBlockDefinition.CubeSize); } if (DynamicMode) { PlaneD cameraPlane = new PlaneD(MySector.MainCamera.Position, MySector.MainCamera.UpVector); Vector3D projectedPoint = IntersectionStart; projectedPoint = cameraPlane.ProjectPoint(ref projectedPoint); Vector3D freePlacementIntersectionPoint = projectedPoint + IntersectionDistance * IntersectionDirection; if (m_hitInfo != null) { freePlacementIntersectionPoint = m_hitInfo.Value.Position; } addPos = this.CaluclateDynamicModePos(freePlacementIntersectionPoint, IsDynamicOverride()); MyCoordinateSystem.Static.Visible = false; } else { if (m_gizmo.SpaceDefault.m_startBuild == null && m_gizmo.SpaceDefault.m_startRemove == null) { if (!FreezeGizmo) { if (CurrentGrid != null) { MyCoordinateSystem.Static.Visible = false; ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for grid"); addPos = GetAddAndRemovePositions(gridSize, PlacingSmallGridOnLargeStatic, out m_gizmo.SpaceDefault.m_addPos, out m_gizmo.SpaceDefault.m_addPosSmallOnLarge, out m_gizmo.SpaceDefault.m_addDir, out m_gizmo.SpaceDefault.m_removePos, out m_gizmo.SpaceDefault.m_removeBlock, out m_gizmo.SpaceDefault.m_blockIdInCompound, m_gizmo.SpaceDefault.m_removeBlocksInMultiBlock); if (addPos) { if (PlacingSmallGridOnLargeStatic) { m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPosSmallOnLarge.Value; } else { m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPos; } m_gizmo.SpaceDefault.m_worldMatrixAdd = m_gizmo.SpaceDefault.m_localMatrixAdd * CurrentGrid.WorldMatrix; var normal = GetSingleMountPointNormal(); // Gizmo add dir can be zero in some cases if (normal.HasValue && GridAndBlockValid && m_gizmo.SpaceDefault.m_addDir != Vector3I.Zero) { m_gizmo.SetupLocalAddMatrix(m_gizmo.SpaceDefault, normal.Value); } } ProfilerShort.End(); } else { MyCoordinateSystem.Static.Visible = true; ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for voxel"); Vector3D localSnappedPos = m_lastLocalCoordSysData.LocalSnappedPos; if (!CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter) { localSnappedPos -= new Vector3D(0.5 * gridSize, 0.5 * gridSize, -0.5 * gridSize); } Vector3I gridCoord = Vector3I.Round(localSnappedPos / gridSize); m_gizmo.SpaceDefault.m_addPos = gridCoord; m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_lastLocalCoordSysData.LocalSnappedPos; m_gizmo.SpaceDefault.m_worldMatrixAdd = m_lastLocalCoordSysData.Origin.TransformMatrix; addPos = true; ProfilerShort.End(); } } Debug.Assert(!m_gizmo.SpaceDefault.m_worldMatrixAdd.IsNan(), "Invalid gizmo matrix"); if (m_gizmo.SpaceDefault.m_removeBlock != null) { removePos = true; } } } ProfilerShort.Begin("buildingDisabledByCockpit"); bool buildingDisabledByCockpit = MySession.Static.ControlledEntity != null && MySession.Static.ControlledEntity is MyCockpit && !SpectatorIsBuilding; if (!buildingDisabledByCockpit) { if (IsInSymmetrySettingMode) { m_gizmo.SpaceDefault.m_continueBuild = null; addPos = false; removePos = false; if (m_gizmo.SpaceDefault.m_removeBlock != null) { var min = (m_gizmo.SpaceDefault.m_removeBlock.Min * CurrentGrid.GridSize); var max = (m_gizmo.SpaceDefault.m_removeBlock.Max * CurrentGrid.GridSize); Vector3 center = (min + max) * 0.5f; Color color = DrawSymmetryPlane(m_symmetrySettingMode, CurrentGrid, center); DrawSemiTransparentBox(CurrentGrid, m_gizmo.SpaceDefault.m_removeBlock, color.ToVector4()); } } if (CurrentGrid != null && (UseSymmetry || IsInSymmetrySettingMode)) { if (CurrentGrid.XSymmetryPlane != null) { Vector3 center = CurrentGrid.XSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.XSymmetryOdd ? MySymmetrySettingModeEnum.XPlaneOdd : MySymmetrySettingModeEnum.XPlane, CurrentGrid, center); } if (CurrentGrid.YSymmetryPlane != null) { Vector3 center = CurrentGrid.YSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.YSymmetryOdd ? MySymmetrySettingModeEnum.YPlaneOdd : MySymmetrySettingModeEnum.YPlane, CurrentGrid, center); } if (CurrentGrid.ZSymmetryPlane != null) { Vector3 center = CurrentGrid.ZSymmetryPlane.Value * CurrentGrid.GridSize; DrawSymmetryPlane(CurrentGrid.ZSymmetryOdd ? MySymmetrySettingModeEnum.ZPlaneOdd : MySymmetrySettingModeEnum.ZPlane, CurrentGrid, center); } } } ProfilerShort.BeginNextBlock("UpdateGizmos"); UpdateGizmos(addPos, removePos, true); ProfilerShort.BeginNextBlock("UpdateRenderInstanceData"); m_renderData.UpdateRenderInstanceData(); ProfilerShort.BeginNextBlock("CurrentVoxelBase"); if (CurrentGrid == null || (DynamicMode && CurrentGrid != null)) { MatrixD drawMatrix = m_gizmo.SpaceDefault.m_worldMatrixAdd; Vector3D rotatedModelOffset; Vector3D.TransformNormal(ref CurrentBlockDefinition.ModelOffset, ref drawMatrix, out rotatedModelOffset); drawMatrix.Translation = drawMatrix.Translation + rotatedModelOffset; m_renderData.UpdateRenderEntitiesData(drawMatrix, UseTransparency, CurrentBlockScale); } else { m_renderData.UpdateRenderEntitiesData(CurrentGrid.WorldMatrix, UseTransparency); } ProfilerShort.BeginNextBlock("UpdateBlockInfoHud"); UpdateBlockInfoHud(); ProfilerShort.End(); }
public override void UpdateBeforeSimulation() { int rayCount = 0; if (m_rayCastQueue.Count > 0 && m_rayCastCounter % 20 == 0) { while (rayCount < 50 && m_rayCastQueue.Count > 0) { var rand = MyUtils.GetRandomInt(m_rayCastQueue.Count - 1); var entity = m_rayCastQueue[rand].Entity; var l = m_rayCastQueue[rand]._Ray; var p = m_rayCastQueue[rand].Position; var particle = m_rayCastQueue[rand].Particle; if (entity is MyCubeGrid) { particle.Stop(); var grid = entity as MyCubeGrid; var invMat = grid.PositionComp.WorldMatrixNormalizedInv; if (grid.BlocksDestructionEnabled) { grid.Physics.ApplyDeformation(6f, 3f, 3f, Vector3.Transform(p, invMat), Vector3.Normalize(Vector3.Transform(m_directionFromSunNormalized, invMat)), MyDamageType.Environment); } //MyPhysics.HavokWorld.CastRay(l.From, l.To, m_hitLst); //rayCount++; //MyEntity ent = null; //if (m_hitLst.Count != 0) // ent = m_hitLst[0].GetEntity(); //if (ent == grid) //{ // grid.Physics.ApplyDeformation(6f, 3f, 3f, Vector3.Transform(m_hitLst[0].Position, invMat), Vector3.Normalize(Vector3.Transform(m_directionFromSunNormalized, invMat)), Sandbox.Game.Weapons.MyDamageType.Environment); // //var block = grid.GetBlock(Vector3I.Floor(Vector3.Transform(m_hitLst[0].Position, invMat) / grid.GridSize)); // //if (block != null) // // grid.ApplyDestructionDeformation(block); // m_rayCastQueue.RemoveAt(0); // m_hitLst.Clear(); // break; //} m_rayCastQueue.RemoveAt(rand); m_hitLst.Clear(); break; } } } m_rayCastCounter++; // Update only if sun wind is active if (IsActive == false) return; //? float dT = ((float)MySandboxGame.TotalGamePlayTimeInMilliseconds - (float)m_timeLastUpdate) / 1000.0f; m_timeLastUpdate = MySandboxGame.TotalGamePlayTimeInMilliseconds; if(MySandboxGame.IsPaused) return; m_deltaTime += dT; float traveledDistance = m_speed * m_deltaTime; // If sun wind finished its way, we will turn it off if (traveledDistance >= MySunWindConstants.SUN_WIND_LENGTH_TOTAL) { IsActive = false; StopCue(); return; } Vector3D campos = MySession.Static.LocalCharacter == null ? Vector3D.Zero : MySession.Static.LocalCharacter.Entity.WorldMatrix.Translation; // This is plane that goes through sun wind, it's in its middle m_planeMiddle = new PlaneD(m_initialSunWindPosition + m_directionFromSunNormalized * traveledDistance, m_directionFromSunNormalized); m_distanceToSunWind = m_planeMiddle.DistanceToPoint(ref campos); // We make sure that sound moves always on line that goes through camera. So it's not in the middle of sun wind, more like middle where is camera. // Reason is that I want the sound always go through camera. m_positionOnCameraLine = /*MySession.Static.Player.PlayerEntity.Entity.WorldMatrix.Translation*/ - m_directionFromSunNormalized * m_distanceToSunWind; Vector3D positionFront = m_positionOnCameraLine + m_directionFromSunNormalized * 2000; Vector3D positionBack = m_positionOnCameraLine + m_directionFromSunNormalized * -2000; m_planeFront = new PlaneD(positionFront, m_directionFromSunNormalized); m_planeBack = new PlaneD(positionBack, m_directionFromSunNormalized); var distanceToFrontPlane = m_planeFront.DistanceToPoint(ref campos); var distanceToBackPlane = m_planeBack.DistanceToPoint(ref campos); #region commented //Vector3 positionOfSound; //if ((distanceToFrontPlane <= 0) && (distanceToBackPlane >= 0)) //{ // positionOfSound = MySession.Static.Player.PlayerEntity.Entity.WorldMatrix.Translation; //} //else if (distanceToFrontPlane > 0) //{ // positionOfSound = positionFront; //} //else //{ // positionOfSound = positionBack; //} // Update position of sound. It works like this: we hear coming sound, then we are in the sound and then we hear it coming out. //MyAudio.Static.UpdateCuePosition(m_burningCue, positionOfSound, m_directionFromSunNormalized, -m_downVector, m_directionFromSunNormalized * m_speed); //MySounds.UpdateCuePosition(m_burningCue, positionOfSound, m_directionFromSunNormalized, Vector3.Up, Vector3.Zero); //MyLogManager.WriteLine("positionOfSound: " + MyUtils.GetFormatedVector3(positionOfSound, 3)); //MyLogManager.WriteLine("m_directionFromSunNormalized: " + MyUtils.GetFormatedVector3(m_directionFromSunNormalized, 3)); //MyLogManager.WriteLine("m_downVector: " + MyUtils.GetFormatedVector3(m_downVector, 3)); //Position = positionOfSound; // Shake player's head //float distanceToSound; //Vector3.Distance(ref positionOfSound, ref campos, out distanceToSound); //float shake = 1 - MathHelper.Clamp(distanceToSound / 1000, 0, 1); /*if (MySession.Static.Player.Controller.ControlledEntity != null) { MySession.Static.PlayerShip.IncreaseHeadShake( MathHelper.Lerp(MyHeadShakeConstants.HEAD_SHAKE_AMOUNT_DURING_SUN_WIND_MIN, MyHeadShakeConstants.HEAD_SHAKE_AMOUNT_DURING_SUN_WIND_MAX, shake)); }*/ #endregion for (int i = 0; i < m_sunwindEntities.Count;) { if (m_sunwindEntities[i].MarkedForClose) { m_sunwindEntities.RemoveAtFast(i); } else { i++; } } var q = VRageMath.Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir(m_directionFromSunNormalized, m_downVector)); var v = new Vector3(10000, 10000, 2000); MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(positionFront + m_directionFromSunNormalized * 2500, v, q), Color.Red.ToVector3(), 1, false, false); if (m_rayCastCounter == 120) { var pos = positionFront + m_directionFromSunNormalized * 2500; MyPhysics.GetPenetrationsBox(ref v, ref pos, ref q, m_intersectionLst, MyPhysics.CollisionLayers.DefaultCollisionLayer); foreach (var hit in m_intersectionLst) { var entity = hit.GetCollisionEntity(); if (entity is MyVoxelMap) continue; if (!m_sunwindEntities.Contains(entity)) m_sunwindEntities.Add(entity); } m_intersectionLst.Clear(); for (int i = 0; i < m_sunwindEntities.Count; i++) { var entity = m_sunwindEntities[i]; if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; var aabb = grid.PositionComp.WorldAABB; var halfDiagonal = (aabb.Center - aabb.Min).Length(); var rightMax = ((aabb.Center - aabb.Min) / m_rightVector).AbsMin(); var downMax = ((aabb.Center - aabb.Min) / m_downVector).AbsMin(); var size = (grid.Max - grid.Min); var max = Math.Max(size.X, Math.Max(size.Y, size.Z)); var invMat = grid.PositionComp.WorldMatrixNormalizedInv; var start = aabb.Center - rightMax * m_rightVector - downMax * m_downVector; for (int x = 0; x < rightMax * 2; x += grid.GridSizeEnum == MyCubeSize.Large ? 25 : 10) { for (int y = 0; y < downMax * 2; y += grid.GridSizeEnum == MyCubeSize.Large ? 25 : 10) { var pivot = start + x * m_rightVector + y * m_downVector; pivot += (float)halfDiagonal * m_directionFromSunNormalized; var circle = MyUtils.GetRandomVector3CircleNormalized(); float rand = MyUtils.GetRandomFloat(0, grid.GridSizeEnum == MyCubeSize.Large ? 10 : 5); pivot += m_rightVector * circle.X * rand + m_downVector * circle.Z * rand; LineD l = new LineD(pivot - m_directionFromSunNormalized * (float)halfDiagonal, pivot); if (grid.RayCastBlocks(l.From, l.To).HasValue) { l.From = pivot - m_directionFromSunNormalized * 1000; MyPhysics.CastRay(l.From, l.To, m_hitLst); m_rayCastCounter++; if (m_hitLst.Count == 0 || m_hitLst[0].HkHitInfo.GetHitEntity() != grid.Components) { m_hitLst.Clear(); continue; } MyParticleEffect particle; if (MyParticlesManager.TryCreateParticleEffect((int)MyParticleEffectsIDEnum.Prefab_LeakingFire, out particle)) { particle.WorldMatrix = MatrixD.CreateWorld(m_hitLst[0].Position, Vector3D.Forward, Vector3D.Up); } m_rayCastQueue.Add(new MyEntityRayCastPair() { Entity = grid, _Ray = l , Position = m_hitLst[0].Position, Particle = particle}); //grid.Physics.ApplyDeformation(0.2f, 4, 2, Vector3.Transform(m_hitLst[0].Position, invMat), Vector3.Transform(m_directionFromSunNormalized, invMat), Sandbox.Game.Weapons.MyDamageType.Environment); } } } m_sunwindEntities.Remove(grid); i--; } else { m_sunwindEntities.Remove(entity); i--; } } m_rayCastCounter = 0; } // Apply force to all objects that aren't static and are hit by sun wind (ignoring voxels and large ships) //MyEntities.ApplySunWindForce(m_sunwindEntities, ref m_planeFront, ref m_planeBack, DoNotIgnoreTheseTypes, ref m_directionFromSunNormalized); // Start small billboards if (m_distanceToSunWind <= MySunWindConstants.SWITCH_LARGE_AND_SMALL_BILLBOARD_DISTANCE) { Debug.Assert(m_computedMaxDistances == MySunWindConstants.SMALL_BILLBOARDS_SIZE.X * MySunWindConstants.SMALL_BILLBOARDS_SIZE.Y, "Not all small billboard MaxDistances are computed!"); m_smallBillboardsStarted = true; } ComputeMaxDistances(); base.UpdateBeforeSimulation(); }
public static bool IsParallelTo(this Vector3D vector, PlaneD plane) { return(plane.DotNormal(vector) == 0.0d); }
/// <summary> /// Method returns intersection point between sphere and triangle (which is defined by vertexes and plane). /// If no intersection found, method returns null. /// See below how intersection point can be calculated, because it's not so easy - for example sphere vs. triangle will /// hardly generate just intersection point... more like intersection area or something. /// </summary> public static Vector3? GetSphereTriangleIntersection(ref BoundingSphereD sphere, ref PlaneD trianglePlane, ref MyTriangle_Vertices triangle) { // Vzdialenost gule od roviny trojuholnika double distance; // Zistim, ci sa gula nachadza pred alebo za rovinou trojuholnika, alebo ju presekava MySpherePlaneIntersectionEnum spherePlaneIntersection = GetSpherePlaneIntersection(ref sphere, ref trianglePlane, out distance); // Ak gula presekava rovinu, tak hladam pseudo-priesecnik if (spherePlaneIntersection == MySpherePlaneIntersectionEnum.INTERSECTS) { // Offset ktory pomoze vypocitat suradnicu stredu gule premietaneho na rovinu trojuholnika Vector3D offset = trianglePlane.Normal * distance; // Priesecnik na rovine trojuholnika, je to premietnuty stred gule na rovine trojuholnika Vector3D intersectionPoint; intersectionPoint.X = sphere.Center.X - offset.X; intersectionPoint.Y = sphere.Center.Y - offset.Y; intersectionPoint.Z = sphere.Center.Z - offset.Z; if (GetInsidePolygonForSphereCollision(ref intersectionPoint, ref triangle)) // Ak priesecnik nachadza v trojuholniku { // Toto je pripad, ked sa podarilo premietnut stred gule na rovinu trojuholnika a tento priesecnik sa // nachadza vnutri trojuholnika (tzn. sedia uhly) return (Vector3)intersectionPoint; } else // Ak sa priesecnik nenachadza v trojuholniku, este stale sa moze nachadzat na hrane trojuholnika { Vector3? edgeIntersection = GetEdgeSphereCollision(ref sphere.Center, (float)sphere.Radius / 1.0f, ref triangle); if (edgeIntersection != null) { // Toto je pripad, ked sa priemietnuty stred gule nachadza mimo trojuholnika, ale intersection gule a trojuholnika tam // je, pretoze gula presekava jednu z hran trojuholnika. Takze vratim suradnice priesecnika na jednej z hran. return edgeIntersection.Value; } } } // Sphere doesn't collide with any triangle return null; }
public static PlaneD FromPointNormal(Vector3D point, PlaneD normal) { return new PlaneD(normal.Normal, -point.Dot(normal.Normal)); }
public void InsideOrIntersectingOBBd_IsTrue(PlaneD plane, OBBd obb) { Assert.True(plane.InsideOrIntersecting(obb)); }
public void IntersectsAABBd_IsFalse(PlaneD plane, AABBd aabb) { Assert.False(plane.Intersects(aabb)); }
public static bool IsFrontFacingTo(this PlaneD plane, Vector3D direction) { return(plane.DotNormal(direction) <= 0.0d); }
public void GetTrianglesIntersectingSphere(MyModel model, ref BoundingSphereD sphere, Vector3? referenceNormalVector, float? maxAngle, List<MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { // Check if sphere intersects bounding box of this node //if (m_boundingBox.Contains(sphere) == ContainmentType.Disjoint) return; if (m_boundingBox.Intersects(ref sphere) == false) return; // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_triangleIndices.Count; i++) { // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) return; int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; //MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); triangleNormals.Normal0 = model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = model.GetVertexNormal(triangleIndices.I1); /* triangleTangents.Normal0 = model.GetVertexTangent(triangleIndices.I0); triangleTangents.Normal1 = model.GetVertexTangent(triangleIndices.I2); triangleTangents.Normal2 = model.GetVertexTangent(triangleIndices.I1); */ PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertices = triangle; retTriangle.Normals = triangleNormals; // retTriangle.Tangents = triangleTangents; retTriangles.Add(retTriangle); } } } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { //m_childs[value].GetTrianglesIntersectingSphere(physObject, ref sphere, referenceNormalVector, maxAngle, ignoreTriangleWithIndex, retTriangles, maxNeighbourTriangles); m_childs[i].GetTrianglesIntersectingSphere(model, ref sphere, referenceNormalVector, maxAngle, retTriangles, maxNeighbourTriangles); } } }
public static bool EmbeddedIn(this BoundingSphereD sphere, PlaneD plane) { return(plane.Intersects(sphere) == PlaneIntersectionType.Intersecting); }
public void KeepMoving(Vector3D destination, double velocity /* Meters per sec*/) { var matrix = RotorRotation.Rotor.WorldMatrix; // getting world points var rotationBasePoint = RotorRotation.Rotor.GetPosition(); var armBasePoint = Rotor1.Rotor.GetPosition(); var armElbowPoint = Rotor2.Rotor.GetPosition(); var armTipPoint = Tip.GetPosition(); // adjust destination in case its something wrong with it var averageLength = (Vector3D.Distance(armBasePoint, armElbowPoint) + Vector3D.Distance(armElbowPoint, armTipPoint)) / 2; destination = CutTrailAtClosestToBase(rotationBasePoint, armTipPoint, destination); destination = BringToSafeZone(destination, armBasePoint, armElbowPoint, armTipPoint); destination = TakeNearbyPoint(destination, armTipPoint, averageLength); // no point doing anything if the tip is already there if (Vector3D.Distance(armTipPoint, destination) < DistanceToCancelMovement) { RotorRotation.Stop(); Rotor1.Stop(); Rotor2.Stop(); return; } var rotationEndPoint = GetRotationEndPoint(destination, rotationBasePoint, armTipPoint); // calculate local points var localArmBasePoint = VectorUtility.GetLocalVector(matrix, rotationBasePoint, armBasePoint); var localArmTipPoint = VectorUtility.GetLocalVector(matrix, rotationBasePoint, armTipPoint); var localDestination = VectorUtility.GetLocalVector(matrix, rotationBasePoint, destination); var localRotationEndPoint = VectorUtility.GetLocalVector(matrix, rotationBasePoint, rotationEndPoint); var localArmElbow = VectorUtility.GetLocalVector(matrix, rotationBasePoint, armElbowPoint); var localArmPlaneNormalPoint = /*localArmBasePoint + */ Vector3D.Rotate(Rotor1.Rotor.WorldMatrix.Up, MatrixD.Transpose(matrix)); // calculating planes to project on var rotationPlane = new PlaneD(Vector3D.Zero, Vector3D.UnitY); // note that rotation plane is XZ var armPlane = new PlaneD(localArmBasePoint, localArmPlaneNormalPoint); // normalizing arm points by projecting them to the arm plane for the arm part calculations var normalizedArmTip = armPlane.ProjectPoint(ref localArmTipPoint); var normalizedArmElbow = armPlane.ProjectPoint(ref localArmElbow); var normalizedDestination = armPlane.ProjectPoint(ref localDestination); // calculate local projected points var localProjectedArmBase = rotationPlane.ProjectPoint(ref localArmBasePoint); var localProjectedTip = rotationPlane.ProjectPoint(ref normalizedArmTip); var localProjectedTipForRotation = rotationPlane.ProjectPoint(ref localArmTipPoint); var localProjectedDestination = rotationPlane.ProjectPoint(ref localDestination); // for rotation // calculate rotation distance var rotationDistance = Math.Abs(VectorUtility.Angle(localProjectedTipForRotation, localProjectedDestination)) * localProjectedTip.Length(); // adjust speeds //var rotationSpeedPart = GetRotationSpeedPart(localDestination, localArmTipPoint, localRotationBase, armDistance); var armDistance = Vector3D.Distance(localDestination, localRotationEndPoint); var rotationSpeedPart = rotationDistance / (rotationDistance + armDistance); var armSpeedPart = 1d - rotationSpeedPart; var rotationVelocity = rotationSpeedPart * velocity; var armVelocity = armSpeedPart * velocity; // calculate base rotor rotation speed var targetRps = rotationVelocity / localProjectedTip.Length(); // calculating tip and destination as 2D points for the arm by rotating them parallel to YZ plane var armBaseElevation = localArmBasePoint.Y; var angle2D = (float)VectorUtility.Angle(localProjectedTip - localProjectedArmBase, Vector3D.UnitX); if (localProjectedTip.Z < 0) { angle2D *= -1; } var armTipR = VectorUtility.Rotate(normalizedArmTip, Vector3D.UnitY, angle2D); var armElbowR = VectorUtility.Rotate(normalizedArmElbow, Vector3D.UnitY, angle2D); var armDestinationR = VectorUtility.Rotate(normalizedDestination, Vector3D.UnitY, angle2D); var armTipPoint2D = new Vector2D(armTipR.X, armTipR.Y - armBaseElevation); var armElbow2D = new Vector2D(armElbowR.X, armElbowR.Y - armBaseElevation); var armDestinationPoint2D = new Vector2D(armDestinationR.X, armDestinationR.Y - armBaseElevation); // launch movement MakeRotationMovement(localProjectedTipForRotation, localProjectedDestination, targetRps); MakeArmMovement(armTipPoint2D, armElbow2D, armDestinationPoint2D, armVelocity); }
public static Vector3D ProjectOn(this Vector3D vector, PlaneD plane) { return(vector - plane.SignedDistanceTo(vector) * plane.Normal); }
public void GetTrianglesIntersectingSphere(ref BoundingSphereD sphere, List <MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { Vector3?referenceNormalVector = null; float? maxAngle = null; var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphere; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); m_overlappedTriangles.Clear(); // VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_bvh.BoxQuery"); // This code is called recursively and cause profiler to lag bool res = m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles); // VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); if (res) { //VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_overlappedTriangles"); // This code is called recursively and cause profiler to lag // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); //gi_aabb.CollideTriangleExact // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normal retTriangle; retTriangle.Vertexes = triangle; retTriangle.Normal = calculatedTriangleNormal; retTriangles.Add(retTriangle); } } } } } //VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } }
public static double SignedDistanceTo(this PlaneD plane, Vector3D point) { return(plane.DotCoordinate(point)); }
public PlaneSceneObject(Vector3D origin, Vector3D normal, MaterialShader shader, double radius) : base(origin, shader, radius) { plane = PlaneD.FromPointNormal(origin, normal); }
public static double DistanceToPlaneD(PlaneD plane, Vector3D point) { return(plane.Normal.Dot(point) + plane.D); }
public void GetTrianglesIntersectingSphere(ref BoundingSphereD sphere, Vector3? referenceNormalVector, float? maxAngle, List<MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphere; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); m_overlappedTriangles.Clear(); if (m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles)) { // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) return; m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertices triangle; MyTriangle_Normals triangleNormals; //MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; m_model.GetVertex(triangleIndices.I0, triangleIndices.I2, triangleIndices.I1, out triangle.Vertex0, out triangle.Vertex1, out triangle.Vertex2); /* triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); */ triangleNormals.Normal0 = m_model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = m_model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = m_model.GetVertexNormal(triangleIndices.I1); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertices = triangle; retTriangle.Normals = triangleNormals; retTriangles.Add(retTriangle); } } } } } } }
public static bool Equal(PlaneD a, PlaneD b) => Equal(a.Normal, b.Normal) && Equal(a.D, b.D);
public void GetTrianglesIntersectingSphere(ref BoundingSphereD sphere, List<MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { Vector3? referenceNormalVector = null; float? maxAngle = null; var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphere; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); m_overlappedTriangles.Clear(); // VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_bvh.BoxQuery"); // This code is called recursively and cause profiler to lag bool res = m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles); // VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); if (res) { //VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_overlappedTriangles"); // This code is called recursively and cause profiler to lag // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) return; m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); //gi_aabb.CollideTriangleExact // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertices triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normal retTriangle; retTriangle.Vertexes = triangle; retTriangle.Normal = calculatedTriangleNormal; retTriangles.Add(retTriangle); } } } } } //VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } }
public override void UpdateBeforeSimulation() { int num = 0; if ((m_rayCastQueue.Count > 0) && ((this.m_rayCastCounter % 20) == 0)) { while ((num < 50) && (m_rayCastQueue.Count > 0)) { int randomInt = MyUtils.GetRandomInt(m_rayCastQueue.Count - 1); MyEntity entity = m_rayCastQueue[randomInt].Entity; MyEntityRayCastPair local1 = m_rayCastQueue[randomInt]; Vector3D position = m_rayCastQueue[randomInt].Position; MyParticleEffect particle = m_rayCastQueue[randomInt].Particle; if (entity is MyCubeGrid) { particle.Stop(true); MyCubeGrid grid = entity as MyCubeGrid; MatrixD worldMatrixNormalizedInv = grid.PositionComp.WorldMatrixNormalizedInv; if (grid.BlocksDestructionEnabled) { grid.Physics.ApplyDeformation(6f, 3f, 3f, (Vector3)Vector3.Transform((Vector3)position, worldMatrixNormalizedInv), Vector3.Normalize(Vector3.Transform((Vector3)m_directionFromSunNormalized, worldMatrixNormalizedInv)), MyDamageType.Environment, 0f, 0f, 0L); } m_rayCastQueue.RemoveAt(randomInt); this.m_hitLst.Clear(); break; } } } this.m_rayCastCounter++; if (IsActive) { float num2 = (MySandboxGame.TotalGamePlayTimeInMilliseconds - m_timeLastUpdate) / 1000f; m_timeLastUpdate = MySandboxGame.TotalGamePlayTimeInMilliseconds; if (!MySandboxGame.IsPaused) { m_deltaTime += num2; float num3 = m_speed * m_deltaTime; if (num3 >= 60000f) { IsActive = false; StopCue(); } else { Vector3D translation; if (MySession.Static.LocalCharacter != null) { translation = MySession.Static.LocalCharacter.Entity.WorldMatrix.Translation; } else { translation = Vector3D.Zero; } Vector3D point = translation; m_planeMiddle = new PlaneD(m_initialSunWindPosition + (m_directionFromSunNormalized * num3), m_directionFromSunNormalized); m_distanceToSunWind = m_planeMiddle.DistanceToPoint(ref point); m_positionOnCameraLine = -m_directionFromSunNormalized * m_distanceToSunWind; Vector3D position = m_positionOnCameraLine + (m_directionFromSunNormalized * 2000.0); Vector3D vectord3 = m_positionOnCameraLine + (m_directionFromSunNormalized * -2000.0); m_planeFront = new PlaneD(position, m_directionFromSunNormalized); m_planeBack = new PlaneD(vectord3, m_directionFromSunNormalized); m_planeFront.DistanceToPoint(ref point); m_planeBack.DistanceToPoint(ref point); int index = 0; while (index < m_sunwindEntities.Count) { if (m_sunwindEntities[index].MarkedForClose) { m_sunwindEntities.RemoveAtFast <IMyEntity>(index); continue; } index++; } Quaternion orientation = Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir((Vector3)m_directionFromSunNormalized, (Vector3)m_downVector)); Vector3 halfExtents = new Vector3(10000f, 10000f, 2000f); MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(position + (m_directionFromSunNormalized * 2500.0), halfExtents, orientation), Color.Red.ToVector3(), 1f, false, false, false); if (this.m_rayCastCounter == 120) { Vector3D translation = position + (m_directionFromSunNormalized * 2500.0); MyPhysics.GetPenetrationsBox(ref halfExtents, ref translation, ref orientation, m_intersectionLst, 15); using (List <HkBodyCollision> .Enumerator enumerator = m_intersectionLst.GetEnumerator()) { while (enumerator.MoveNext()) { IMyEntity collisionEntity = enumerator.Current.GetCollisionEntity(); if (!(collisionEntity is MyVoxelMap) && !m_sunwindEntities.Contains(collisionEntity)) { m_sunwindEntities.Add(collisionEntity); } } } m_intersectionLst.Clear(); int num6 = 0; while (true) { if (num6 >= m_sunwindEntities.Count) { this.m_rayCastCounter = 0; break; } IMyEntity item = m_sunwindEntities[num6]; if (item is MyCubeGrid) { MyCubeGrid grid2 = item as MyCubeGrid; BoundingBoxD worldAABB = grid2.PositionComp.WorldAABB; double num7 = (worldAABB.Center - worldAABB.Min).Length(); double num8 = ((worldAABB.Center - worldAABB.Min) / m_rightVector).AbsMin(); double num9 = ((worldAABB.Center - worldAABB.Min) / m_downVector).AbsMin(); Vector3I vectori = grid2.Max - grid2.Min; Math.Max(vectori.X, Math.Max(vectori.Y, vectori.Z)); MatrixD worldMatrixNormalizedInv = grid2.PositionComp.WorldMatrixNormalizedInv; Vector3D vectord6 = (worldAABB.Center - (num8 * m_rightVector)) - (num9 * m_downVector); int num10 = 0; while (true) { if (num10 >= (num8 * 2.0)) { m_sunwindEntities.Remove(grid2); num6--; break; } int num11 = 0; while (true) { if (num11 >= (num9 * 2.0)) { num10 += (grid2.GridSizeEnum == MyCubeSize.Large) ? 0x19 : 10; break; } Vector3D to = ((vectord6 + (num10 * m_rightVector)) + (num11 * m_downVector)) + (((float)num7) * m_directionFromSunNormalized); Vector3 vector2 = MyUtils.GetRandomVector3CircleNormalized(); float randomFloat = MyUtils.GetRandomFloat(0f, (grid2.GridSizeEnum == MyCubeSize.Large) ? ((float)10) : ((float)5)); to += ((m_rightVector * vector2.X) * randomFloat) + ((m_downVector * vector2.Z) * randomFloat); LineD ed = new LineD(to - (m_directionFromSunNormalized * ((float)num7)), to); if (grid2.RayCastBlocks(ed.From, ed.To) != null) { ed.From = to - (m_directionFromSunNormalized * 1000.0); MyPhysics.CastRay(ed.From, ed.To, this.m_hitLst, 0); this.m_rayCastCounter++; if ((this.m_hitLst.Count == 0) || !ReferenceEquals(this.m_hitLst[0].HkHitInfo.GetHitEntity(), grid2.Components)) { this.m_hitLst.Clear(); } else { MyParticleEffect effect2; MyParticlesManager.TryCreateParticleEffect("Dummy", MatrixD.CreateWorld(this.m_hitLst[0].Position, Vector3D.Forward, Vector3D.Up), out effect2); MyEntityRayCastPair pair = new MyEntityRayCastPair { Entity = grid2, _Ray = ed, Position = this.m_hitLst[0].Position, Particle = effect2 }; m_rayCastQueue.Add(pair); } } num11 += (grid2.GridSizeEnum == MyCubeSize.Large) ? 0x19 : 10; } } } else { m_sunwindEntities.Remove(item); num6--; } num6++; } } if (m_distanceToSunWind <= 10000.0) { m_smallBillboardsStarted = true; } ComputeMaxDistances(); base.UpdateBeforeSimulation(); } } } }
public void InsideOrIntersectingAABBd_IsTrue(PlaneD plane, AABBd aabb) { Assert.True(plane.InsideOrIntersecting(aabb)); }
public void GetTrianglesIntersectingSphere(MyModel model, ref BoundingSphereD sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { // Check if sphere intersects bounding box of this node //if (m_boundingBox.Contains(sphere) == ContainmentType.Disjoint) return; if (m_boundingBox.Intersects(ref sphere) == false) { return; } // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_triangleIndices.Count; i++) { // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertices triangle; MyTriangle_Normals triangleNormals; //MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); triangleNormals.Normal0 = model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = model.GetVertexNormal(triangleIndices.I1); /* * triangleTangents.Normal0 = model.GetVertexTangent(triangleIndices.I0); * triangleTangents.Normal1 = model.GetVertexTangent(triangleIndices.I2); * triangleTangents.Normal2 = model.GetVertexTangent(triangleIndices.I1); */ PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertices = triangle; retTriangle.Normals = triangleNormals; // retTriangle.Tangents = triangleTangents; retTriangles.Add(retTriangle); } } } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { //m_childs[value].GetTrianglesIntersectingSphere(physObject, ref sphere, referenceNormalVector, maxAngle, ignoreTriangleWithIndex, retTriangles, maxNeighbourTriangles); m_childs[i].GetTrianglesIntersectingSphere(model, ref sphere, referenceNormalVector, maxAngle, retTriangles, maxNeighbourTriangles); } } }
public void Normalize_Instance(PlaneD plane, PlaneD expected) { var normalizedPlane = plane.Normalize(); Assert.Equal(normalizedPlane, expected); }
// Control was picked, prepare for rotation operation private void PrepareRotation(Vector3D axis) { m_rotationAxis = axis; // Create plane for picking of rotation vectors m_rotationPlane = new PlaneD(m_gizmoMatrix.Translation, m_rotationAxis); // Set up the starting point of rotation m_rotationStartingPoint = m_rotationPlane.Intersection(ref m_lastRay.From, ref m_lastRay.Direction); // Store the transformations var worldMat = ControlledEntity.PositionComp.WorldMatrix; m_storedScale = MatrixD.CreateScale(worldMat.Scale); m_storedTranslation = worldMat.Translation; m_storedOrientation = worldMat.GetOrientation(); }
public override void UpdateBeforeSimulation() { int rayCount = 0; if (m_rayCastQueue.Count > 0 && m_rayCastCounter % 20 == 0) { while (rayCount < 50 && m_rayCastQueue.Count > 0) { var rand = MyUtils.GetRandomInt(m_rayCastQueue.Count - 1); var entity = m_rayCastQueue[rand].Entity; var l = m_rayCastQueue[rand].Ray; var p = m_rayCastQueue[rand].Position; var particle = m_rayCastQueue[rand].Particle; if (entity is MyCubeGrid) { particle.Stop(); var grid = entity as MyCubeGrid; var invMat = grid.PositionComp.GetWorldMatrixNormalizedInv(); if (grid.BlocksDestructionEnabled) { grid.Physics.ApplyDeformation(6f, 3f, 3f, Vector3.Transform(p, invMat), Vector3.Normalize(Vector3.Transform(m_directionFromSunNormalized, invMat)), MyDamageType.Environment); } //MyPhysics.HavokWorld.CastRay(l.From, l.To, m_hitLst); //rayCount++; //MyEntity ent = null; //if (m_hitLst.Count != 0) // ent = m_hitLst[0].GetEntity(); //if (ent == grid) //{ // grid.Physics.ApplyDeformation(6f, 3f, 3f, Vector3.Transform(m_hitLst[0].Position, invMat), Vector3.Normalize(Vector3.Transform(m_directionFromSunNormalized, invMat)), Sandbox.Game.Weapons.MyDamageType.Environment); // //var block = grid.GetBlock(Vector3I.Floor(Vector3.Transform(m_hitLst[0].Position, invMat) / grid.GridSize)); // //if (block != null) // // grid.ApplyDestructionDeformation(block); // m_rayCastQueue.RemoveAt(0); // m_hitLst.Clear(); // break; //} m_rayCastQueue.RemoveAt(rand); m_hitLst.Clear(); break; } } } m_rayCastCounter++; // Update only if sun wind is active if (IsActive == false) { return; } //? float dT = ((float)MySandboxGame.TotalGamePlayTimeInMilliseconds - (float)m_timeLastUpdate) / 1000.0f; m_timeLastUpdate = MySandboxGame.TotalGamePlayTimeInMilliseconds; if (MySandboxGame.IsPaused) { return; } m_deltaTime += dT; float traveledDistance = m_speed * m_deltaTime; // If sun wind finished its way, we will turn it off if (traveledDistance >= MySunWindConstants.SUN_WIND_LENGTH_TOTAL) { IsActive = false; StopCue(); return; } Vector3D campos = MySession.LocalCharacter == null ? Vector3D.Zero : MySession.LocalCharacter.Entity.WorldMatrix.Translation; // This is plane that goes through sun wind, it's in its middle m_planeMiddle = new PlaneD(m_initialSunWindPosition + m_directionFromSunNormalized * traveledDistance, m_directionFromSunNormalized); m_distanceToSunWind = m_planeMiddle.DistanceToPoint(ref campos); // We make sure that sound moves always on line that goes through camera. So it's not in the middle of sun wind, more like middle where is camera. // Reason is that I want the sound always go through camera. m_positionOnCameraLine = /*MySession.Player.PlayerEntity.Entity.WorldMatrix.Translation*/ -m_directionFromSunNormalized * m_distanceToSunWind; Vector3D positionFront = m_positionOnCameraLine + m_directionFromSunNormalized * 2000; Vector3D positionBack = m_positionOnCameraLine + m_directionFromSunNormalized * -2000; m_planeFront = new PlaneD(positionFront, m_directionFromSunNormalized); m_planeBack = new PlaneD(positionBack, m_directionFromSunNormalized); var distanceToFrontPlane = m_planeFront.DistanceToPoint(ref campos); var distanceToBackPlane = m_planeBack.DistanceToPoint(ref campos); #region commented //Vector3 positionOfSound; //if ((distanceToFrontPlane <= 0) && (distanceToBackPlane >= 0)) //{ // positionOfSound = MySession.Player.PlayerEntity.Entity.WorldMatrix.Translation; //} //else if (distanceToFrontPlane > 0) //{ // positionOfSound = positionFront; //} //else //{ // positionOfSound = positionBack; //} // Update position of sound. It works like this: we hear coming sound, then we are in the sound and then we hear it coming out. //MyAudio.Static.UpdateCuePosition(m_burningCue, positionOfSound, m_directionFromSunNormalized, -m_downVector, m_directionFromSunNormalized * m_speed); //MySounds.UpdateCuePosition(m_burningCue, positionOfSound, m_directionFromSunNormalized, Vector3.Up, Vector3.Zero); //MyLogManager.WriteLine("positionOfSound: " + MyUtils.GetFormatedVector3(positionOfSound, 3)); //MyLogManager.WriteLine("m_directionFromSunNormalized: " + MyUtils.GetFormatedVector3(m_directionFromSunNormalized, 3)); //MyLogManager.WriteLine("m_downVector: " + MyUtils.GetFormatedVector3(m_downVector, 3)); //Position = positionOfSound; // Shake player's head //float distanceToSound; //Vector3.Distance(ref positionOfSound, ref campos, out distanceToSound); //float shake = 1 - MathHelper.Clamp(distanceToSound / 1000, 0, 1); /*if (MySession.Player.Controller.ControlledEntity != null) * { * MySession.PlayerShip.IncreaseHeadShake( * MathHelper.Lerp(MyHeadShakeConstants.HEAD_SHAKE_AMOUNT_DURING_SUN_WIND_MIN, * MyHeadShakeConstants.HEAD_SHAKE_AMOUNT_DURING_SUN_WIND_MAX, shake)); * }*/ #endregion for (int i = 0; i < m_sunwindEntities.Count;) { if (m_sunwindEntities[i].MarkedForClose) { m_sunwindEntities.RemoveAtFast(i); } else { i++; } } var q = VRageMath.Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir(m_directionFromSunNormalized, m_downVector)); var v = new Vector3(10000, 10000, 2000); MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(positionFront + m_directionFromSunNormalized * 2500, v, q), Color.Red.ToVector3(), 1, false, false); if (m_rayCastCounter == 120) { var pos = positionFront + m_directionFromSunNormalized * 2500; MyPhysics.GetPenetrationsBox(ref v, ref pos, ref q, m_intersectionLst, MyPhysics.DefaultCollisionLayer); foreach (var hit in m_intersectionLst) { var entity = hit.GetCollisionEntity(); if (entity is MyVoxelMap) { continue; } if (!m_sunwindEntities.Contains(entity)) { m_sunwindEntities.Add(entity); } } m_intersectionLst.Clear(); for (int i = 0; i < m_sunwindEntities.Count; i++) { var entity = m_sunwindEntities[i]; if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; var aabb = grid.PositionComp.WorldAABB; var halfDiagonal = (aabb.Center - aabb.Min).Length(); var rightMax = ((aabb.Center - aabb.Min) / m_rightVector).AbsMin(); var downMax = ((aabb.Center - aabb.Min) / m_downVector).AbsMin(); var size = (grid.Max - grid.Min); var max = Math.Max(size.X, Math.Max(size.Y, size.Z)); var invMat = grid.PositionComp.GetWorldMatrixNormalizedInv(); var start = aabb.Center - rightMax * m_rightVector - downMax * m_downVector; for (int x = 0; x < rightMax * 2; x += grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large ? 25 : 10) { for (int y = 0; y < downMax * 2; y += grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large ? 25 : 10) { var pivot = start + x * m_rightVector + y * m_downVector; pivot += (float)halfDiagonal * m_directionFromSunNormalized; var circle = MyUtils.GetRandomVector3CircleNormalized(); float rand = MyUtils.GetRandomFloat(0, grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large ? 10 : 5); pivot += m_rightVector * circle.X * rand + m_downVector * circle.Z * rand; LineD l = new LineD(pivot - m_directionFromSunNormalized * (float)halfDiagonal, pivot); if (grid.RayCastBlocks(l.From, l.To).HasValue) { l.From = pivot - m_directionFromSunNormalized * 1000; MyPhysics.CastRay(l.From, l.To, m_hitLst); m_rayCastCounter++; if (m_hitLst.Count == 0 || m_hitLst[0].HkHitInfo.GetHitEntity() != grid.Components) { m_hitLst.Clear(); continue; } MyParticleEffect particle; if (MyParticlesManager.TryCreateParticleEffect((int)MyParticleEffectsIDEnum.Prefab_LeakingFire, out particle)) { particle.WorldMatrix = MatrixD.CreateWorld(m_hitLst[0].Position, Vector3D.Forward, Vector3D.Up); } m_rayCastQueue.Add(new MyEntityRayCastPair() { Entity = grid, Ray = l, Position = m_hitLst[0].Position, Particle = particle }); //grid.Physics.ApplyDeformation(0.2f, 4, 2, Vector3.Transform(m_hitLst[0].Position, invMat), Vector3.Transform(m_directionFromSunNormalized, invMat), Sandbox.Game.Weapons.MyDamageType.Environment); } } } m_sunwindEntities.Remove(grid); i--; } else { m_sunwindEntities.Remove(entity); i--; } } m_rayCastCounter = 0; } // Apply force to all objects that aren't static and are hit by sun wind (ignoring voxels and large ships) //MyEntities.ApplySunWindForce(m_sunwindEntities, ref m_planeFront, ref m_planeBack, DoNotIgnoreTheseTypes, ref m_directionFromSunNormalized); // Start small billboards if (m_distanceToSunWind <= MySunWindConstants.SWITCH_LARGE_AND_SMALL_BILLBOARD_DISTANCE) { Debug.Assert(m_computedMaxDistances == MySunWindConstants.SMALL_BILLBOARDS_SIZE.X * MySunWindConstants.SMALL_BILLBOARDS_SIZE.Y, "Not all small billboard MaxDistances are computed!"); m_smallBillboardsStarted = true; } ComputeMaxDistances(); base.UpdateBeforeSimulation(); }
// Control was picked, prepare for drag operation private void PrepareDrag(Vector3D? planeNormal, Vector3D? axis) { if (axis.HasValue) { var toCameraVect = Session.Camera.Position - m_gizmoMatrix.Translation; var rightVect = Vector3D.Cross(axis.Value, toCameraVect); planeNormal = Vector3D.Cross(axis.Value, rightVect); // now get rid of the axis part to create perpendicular vector m_dragPlane = new PlaneD(m_gizmoMatrix.Translation, planeNormal.Value); } else if (planeNormal.HasValue) { m_dragPlane = new PlaneD(m_gizmoMatrix.Translation, planeNormal.Value); } m_dragStartingPoint = m_dragPlane.Intersection(ref m_lastRay.From, ref m_lastRay.Direction); // store axis if (axis != null) { m_dragAxis = axis.Value; } // Set the flag for drag in plane option. m_dragOverAxis = axis != null; // store position m_dragStartingPosition = ControlledEntity.PositionComp.GetPosition(); }
public bool Intersects(ref BoundingSphereD localSphere) { MyPrecalcComponent.AssertUpdateThread(); // Get min and max cell coordinate where boundingBox can fit BoundingBoxD sphereBoundingBox = BoundingBoxD.CreateInvalid(); sphereBoundingBox.Include(ref localSphere); Vector3I cellCoordMin, cellCoordMax; { Vector3D minD = sphereBoundingBox.Min; Vector3D maxD = sphereBoundingBox.Max; MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref minD, out cellCoordMin); MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref maxD, out cellCoordMax); } // Fix min and max cell coordinates so they don't overlap the voxelmap ClampCellCoord(ref cellCoordMin); ClampCellCoord(ref cellCoordMax); MyCellCoord cell = new MyCellCoord(); for (cell.CoordInLod.X = cellCoordMin.X; cell.CoordInLod.X <= cellCoordMax.X; cell.CoordInLod.X++) { for (cell.CoordInLod.Y = cellCoordMin.Y; cell.CoordInLod.Y <= cellCoordMax.Y; cell.CoordInLod.Y++) { for (cell.CoordInLod.Z = cellCoordMin.Z; cell.CoordInLod.Z <= cellCoordMax.Z; cell.CoordInLod.Z++) { // If no overlap between bounding box of data cell and the sphere BoundingBox cellBoundingBox; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox); if (cellBoundingBox.Intersects(ref localSphere) == 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 cachedData = GetCell(ref cell); if (cachedData == null) continue; for (int i = 0; i < cachedData.VoxelTrianglesCount; i++) { MyVoxelTriangle voxelTriangle = cachedData.VoxelTriangles[i]; MyTriangle_Vertexes triangle; cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1); cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2); BoundingBox localTriangleAABB = BoundingBox.CreateInvalid(); localTriangleAABB.Include(ref triangle.Vertex0); localTriangleAABB.Include(ref triangle.Vertex1); localTriangleAABB.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 (localTriangleAABB.Intersects(ref localSphere)) { PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref localSphere, ref trianglePlane, ref triangle) != null) { // If intersection found - we are finished. We don't need to look for more. return true; } } } } } } return false; }
public static PlaneD FromPointNormal(Vector3D point, PlaneD normal) { return(new PlaneD(normal.Normal, -point.Dot(normal.Normal))); }
// Return true if object intersects specified sphere. // This method doesn't return exact point of intersection or any additional data. // We don't look for closest intersection - so we stop on first intersection found. // IMPORTANT: Sphere must be in model space, so don't transform it! public bool GetIntersectionWithSphere(MyModel model, ref BoundingSphereD sphere) { // Check if sphere intersects bounding box of this node if (m_boundingBox.Intersects(ref sphere) == false) { return false; } // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_triangleIndices.Count; i++) { int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref sphere)) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { // If we found intersection we can stop and dont need to look further return true; } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { if (m_childs[i].GetIntersectionWithSphere(model, ref sphere)) { return true; } } } return false; }
/// <summary> /// This tells if a sphere is BEHIND, in FRONT, or INTERSECTS a plane, also it's distance /// </summary> public static MySpherePlaneIntersectionEnum GetSpherePlaneIntersection(ref BoundingSphereD sphere, ref PlaneD plane, out double distanceFromPlaneToSphere) { // First we need to find the distance our polygon plane is from the origin. var planeDistance = plane.D; // Here we use the famous distance formula to find the distance the center point // of the sphere is from the polygon's plane. distanceFromPlaneToSphere = (plane.Normal.X * sphere.Center.X + plane.Normal.Y * sphere.Center.Y + plane.Normal.Z * sphere.Center.Z + planeDistance); // If the absolute value of the distance we just found is less than the radius, // the sphere intersected the plane. if (Math.Abs(distanceFromPlaneToSphere) < sphere.Radius) { return(MySpherePlaneIntersectionEnum.INTERSECTS); } else if (distanceFromPlaneToSphere >= sphere.Radius) { // Else, if the distance is greater than or equal to the radius, the sphere is // completely in FRONT of the plane. return(MySpherePlaneIntersectionEnum.FRONT); } // If the sphere isn't intersecting or in FRONT of the plane, it must be BEHIND return(MySpherePlaneIntersectionEnum.BEHIND); }
/// <summary> /// Method returns intersection point between sphere and triangle (which is defined by vertexes and plane). /// If no intersection found, method returns null. /// See below how intersection point can be calculated, because it's not so easy - for example sphere vs. triangle will /// hardly generate just intersection point... more like intersection area or something. /// </summary> public static Vector3?GetSphereTriangleIntersection(ref BoundingSphereD sphere, ref PlaneD trianglePlane, ref MyTriangle_Vertices triangle) { // Vzdialenost gule od roviny trojuholnika double distance; // Zistim, ci sa gula nachadza pred alebo za rovinou trojuholnika, alebo ju presekava MySpherePlaneIntersectionEnum spherePlaneIntersection = GetSpherePlaneIntersection(ref sphere, ref trianglePlane, out distance); // Ak gula presekava rovinu, tak hladam pseudo-priesecnik if (spherePlaneIntersection == MySpherePlaneIntersectionEnum.INTERSECTS) { // Offset ktory pomoze vypocitat suradnicu stredu gule premietaneho na rovinu trojuholnika Vector3D offset = trianglePlane.Normal * distance; // Priesecnik na rovine trojuholnika, je to premietnuty stred gule na rovine trojuholnika Vector3D intersectionPoint; intersectionPoint.X = sphere.Center.X - offset.X; intersectionPoint.Y = sphere.Center.Y - offset.Y; intersectionPoint.Z = sphere.Center.Z - offset.Z; if (GetInsidePolygonForSphereCollision(ref intersectionPoint, ref triangle)) // Ak priesecnik nachadza v trojuholniku { // Toto je pripad, ked sa podarilo premietnut stred gule na rovinu trojuholnika a tento priesecnik sa // nachadza vnutri trojuholnika (tzn. sedia uhly) return((Vector3)intersectionPoint); } else // Ak sa priesecnik nenachadza v trojuholniku, este stale sa moze nachadzat na hrane trojuholnika { Vector3?edgeIntersection = GetEdgeSphereCollision(ref sphere.Center, (float)sphere.Radius / 1.0f, ref triangle); if (edgeIntersection != null) { // Toto je pripad, ked sa priemietnuty stred gule nachadza mimo trojuholnika, ale intersection gule a trojuholnika tam // je, pretoze gula presekava jednu z hran trojuholnika. Takze vratim suradnice priesecnika na jednej z hran. return(edgeIntersection.Value); } } } // Sphere doesn't collide with any triangle return(null); }
public PlaneSceneObject(Vector3D origin, Vector3D normal, MaterialShader shader, double radius) : base(origin, shader, radius) { plane = PlaneD.FromPointNormal(origin, normal); }