public void InitEnvironment() { EnvironmentDefinition = Planet.Generator.EnvironmentDefinition; PlanetTranslation = Planet.WorldMatrix.Translation; m_InstanceHash = Planet.GetInstanceHash(); double radius = Planet.AverageRadius; double faceSize = radius * Math.Sqrt(2); double faceSize2 = faceSize / 2; double sectorSize = EnvironmentDefinition.SectorSize; // Prepare each clipmap for (int i = 0; i < 6; ++i) { // get forward and up Vector3D forward, up; MyPlanetCubemapHelper.GetForwardUp((Base6Directions.Direction)i, out forward, out up); var translation = forward * faceSize2 + PlanetTranslation; forward = -forward; // prepare matrix MatrixD worldMatrix; MatrixD.CreateWorld(ref translation, ref forward, ref up, out worldMatrix); // Setup origins Vector3D origin = new Vector3D(-faceSize2, -faceSize2, 0); Vector3D.Transform(ref origin, ref worldMatrix, out origin); // Basis vectors Vector3D basisX = new Vector3D(1, 0, 0), basisY = new Vector3D(0, 1, 0); Vector3D.RotateAndScale(ref basisX, ref worldMatrix, out basisX); Vector3D.RotateAndScale(ref basisY, ref worldMatrix, out basisY); // Create and init the clipmap. m_clipmaps[i] = new My2DClipmap <MyPlanetEnvironmentClipmapProxy>(); ActiveClipmap = m_clipmaps[i]; ActiveFace = i; m_clipmaps[i].Init(this, ref worldMatrix, sectorSize, faceSize); ActiveFace = -1; // Prepare the provider for the face var provider = new MyProceduralEnvironmentProvider { ProviderId = i }; provider.Init(this, ref origin, ref basisX, ref basisY, ActiveClipmap.LeafSize, m_providerData[i]); Providers[i] = provider; } }
private void UpdateClipmaps() { // This avoids the clipmap from overruning and going bad if (m_sectorsToWorkParallel.Count > 0) { return; } Vector3D camera = MySector.MainCamera.Position - PlanetTranslation; double distance = camera.Length(); // Update only if relevant if (distance > Planet.AverageRadius + m_clipmaps[0].FaceHalf && Proxies.Count == 0) { return; } distance = Math.Abs(Planet.Provider.Shape.GetDistanceToSurfaceCacheless(camera)); // Get cubemap coordinates Vector2D texcoords; int direction; MyPlanetCubemapHelper.ProjectToCube(ref camera, out direction, out texcoords); // Update each clipmap accordingly. for (int face = 0; face < 6; ++face) { ActiveFace = face; ActiveClipmap = m_clipmaps[face]; Vector2D localCoords; MyPlanetCubemapHelper.TranslateTexcoordsToFace(ref texcoords, direction, face, out localCoords); Vector3D pos; pos.X = localCoords.X * ActiveClipmap.FaceHalf; pos.Y = localCoords.Y * ActiveClipmap.FaceHalf; if ((face ^ direction) == 1) { pos.Z = distance + Planet.AverageRadius * 2; } else { pos.Z = distance; } //pos.Z = 0; ActiveClipmap.Update(pos); EvaluateOperations(); // Enqueue operations from this clipmap. } ActiveFace = -1; }
public MyEnvironmentSector GetSectorForPosition(Vector3D positionWorld) { var positionLocal = positionWorld - PlanetTranslation; int face; Vector2D texcoords; MyPlanetCubemapHelper.ProjectToCube(ref positionLocal, out face, out texcoords); texcoords *= m_clipmaps[face].FaceHalf; var handler = m_clipmaps[face].GetHandler(texcoords); if (handler != null) { return(handler.EnvironmentSector); } return(null); }
// Iterate over sector boxes in a range. // TODO: Dumb version of this for small boxes private unsafe void RasterSectorsForPhysics(BoundingBoxD range) { range.InflateToMinimum(EnvironmentDefinition.SectorSize); Vector2I top = new Vector2I(1 << m_clipmaps[0].Depth) - 1; Vector3D *pos = stackalloc Vector3D[8]; range.GetCornersUnsafe(pos); // bitmask for faces, 7th bit is simple bit int markedFaces = 0; int firstFace = 0; for (var i = 0; i < 8; ++i) { Vector3D copy = pos[i]; int index = MyPlanetCubemapHelper.FindCubeFace(ref copy); firstFace = index; index = 1 << index; if ((markedFaces & ~index) != 0) { markedFaces |= 0x40; } markedFaces |= index; } // This way we can ensure a single code path. int startFace = 0; int endFace = 5; // If we only encounter one face we narrow it down. if ((markedFaces & 0x40) == 0) { startFace = endFace = firstFace; } for (int face = startFace; face <= endFace; ++face) { if (((1 << face) & markedFaces) == 0) { continue; } double size = m_clipmaps[face].LeafSize; // Offset var offset = 1 << m_clipmaps[face].Depth - 1; BoundingBox2D bounds = BoundingBox2D.CreateInvalid(); for (int i = 0; i < 8; ++i) { Vector3D copy = pos[i]; Vector2D normCoords; MyPlanetCubemapHelper.ProjectForFace(ref copy, face, out normCoords); bounds.Include(normCoords); } bounds.Min += 1; bounds.Min *= offset; bounds.Max += 1; bounds.Max *= offset; // Calculate bounds in sectors. var start = new Vector2I((int)bounds.Min.X, (int)bounds.Min.Y); var end = new Vector2I((int)bounds.Max.X, (int)bounds.Max.Y); Vector2I.Max(ref start, ref Vector2I.Zero, out start); Vector2I.Min(ref end, ref top, out end); for (int x = start.X; x <= end.X; ++x) { for (int y = start.Y; y <= end.Y; ++y) { EnsurePhysicsSector(x, y, face); } } } }
private unsafe void RasterSectorsForCollision(MyEntity entity) { if (!(entity is MyCubeGrid)) { return; } BoundingBoxD range = entity.PositionComp.WorldAABB; range.Inflate(8); range.Translate(-PlanetTranslation); Vector2I top = new Vector2I(1 << m_clipmaps[0].Depth) - 1; Vector3D *pos = stackalloc Vector3D[8]; range.GetCornersUnsafe(pos); // bitmask for faces, 7th bit is simple bit int markedFaces = 0; int firstFace = 0; for (var i = 0; i < 8; ++i) { Vector3D copy = pos[i]; int index = MyPlanetCubemapHelper.FindCubeFace(ref copy); firstFace = index; index = 1 << index; if ((markedFaces & ~index) != 0) { markedFaces |= 0x40; } markedFaces |= index; } // This way we can ensure a single code path. int startFace = 0; int endFace = 5; // If we only encounter one face we narrow it down. if ((markedFaces & 0x40) == 0) { startFace = endFace = firstFace; } for (int face = startFace; face <= endFace; ++face) { if (((1 << face) & markedFaces) == 0) { continue; } // Offset var offset = 1 << m_clipmaps[face].Depth - 1; BoundingBox2D bounds = BoundingBox2D.CreateInvalid(); for (int i = 0; i < 8; ++i) { Vector3D copy = pos[i]; Vector2D normCoords; MyPlanetCubemapHelper.ProjectForFace(ref copy, face, out normCoords); bounds.Include(normCoords); } bounds.Min += 1; bounds.Min *= offset; bounds.Max += 1; bounds.Max *= offset; // Calculate bounds in sectors. var start = new Vector2I((int)bounds.Min.X, (int)bounds.Min.Y); var end = new Vector2I((int)bounds.Max.X, (int)bounds.Max.Y); Vector2I.Max(ref start, ref Vector2I.Zero, out start); Vector2I.Min(ref end, ref top, out end); for (int x = start.X; x <= end.X; ++x) { for (int y = start.Y; y <= end.Y; ++y) { long sect = MyPlanetSectorId.MakeSectorId(x, y, face); List <MyOrientedBoundingBoxD> boxes; if (!m_obstructorsPerSector.TryGetValue(sect, out boxes)) { boxes = new List <MyOrientedBoundingBoxD>(); m_obstructorsPerSector.Add(sect, boxes); } var bb = entity.PositionComp.LocalAABB; bb.Inflate(8); // inflate by 8m to increase the likellyhood of overlap with trees' roots. boxes.Add(new MyOrientedBoundingBoxD((BoundingBoxD)bb, entity.PositionComp.WorldMatrix)); } } } }