Example #1
0
        private void Split(DoubleVector3 cameraLocation, DoubleVector3 planetLocation)
        {
            // TODO: should we bother to write specs for the threading behavior?

            Interlocked.Increment(ref _statistics.NumberOfSplitsScheduledPerInterval);
            Interlocked.Increment(ref _statistics.NumberOfPendingSplits);

            CreateCancellationTokenSource();
            var splitTasks = CreateBackgroundSplitTasks(cameraLocation, planetLocation);

            CreateSplitCompletionTask(splitTasks);
        }
Example #2
0
        public void Update(DoubleVector3 cameraLocation, DoubleVector3 planetLocation)
        {
            // TODO: I don't like this class's public member design.  In order to get properties like IsVisibleToCamera,
            // you must first call Update with appropriate information.  Internally, a lot of stuff is also
            // order-dependent.  However, this seems to be the most performant design at the moment.

            var meshDistance       = GetDistanceFrom(cameraLocation);
            var distanceFromCamera = meshDistance.ClosestDistance;

            CameraDistanceToWidthRatio = distanceFromCamera / WidthInRealSpaceUnits();

            IsAboveHorizonToCamera = CalculateIsAboveHorizonToCamera(cameraLocation, planetLocation, meshDistance.ClosestVertex);
        }
        double GetRegionalModifier(DoubleVector3 location)
        {
            var lowFrequencyRegionalModifier = _regionalGenerator1.GetSpectralNoise(location, 21, 4, 2.0, 0.5);

            lowFrequencyRegionalModifier += 1;

            var mediumFrequencyRegionalModifier = _regionalGenerator2.GetSpectralNoise(location, 30, 4, 2.0, 0.5);

            mediumFrequencyRegionalModifier += 1;

            var regionalModifier = DoubleMathHelper.Clamp(lowFrequencyRegionalModifier * mediumFrequencyRegionalModifier, 0, 2);

            return(regionalModifier);
        }
Example #4
0
        public IPlanet Create(DoubleVector3 location, double radius)
        {
            // TODO: should we inject into the factory everything it will need to inject
            // into the planets?  That reduces calls to the container but makes an assumption
            // about dependency lifetimes.

            var terrain    = _terrainFactory.Create(radius);
            var renderer   = CreateRenderer(radius);
            var generator  = ObjectFactory.GetInstance <IHeightfieldGenerator>();
            var statistics = ObjectFactory.GetInstance <Statistics>();

            var planet = new Planet(location, radius, terrain, renderer, generator, _settings, statistics);

            return(planet);
        }
Example #5
0
        public Settings(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;

            ShouldUpdate                = true;
            ShouldSingleStep            = false;
            ShouldDrawWireframe         = false;
            CameraStartingLocation      = new DoubleVector3(0, PhysicalConstants.RadiusOfEarth * 1.002, 0);
            CameraStartingLookAt        = CameraStartingLocation + DoubleVector3.Backward + DoubleVector3.Down * .2;
            CameraMoveSpeedPerSecond    = PhysicalConstants.RadiusOfEarth / 1000;
            CameraMouseLookDamping      = 300f;
            MaximumQuadNodeLevel        = 19;
            ShowQuadBoundaries          = true;
            FarClippingPlaneDistance    = 10000000;
            ShouldDrawMeshBoundingBoxes = false;
        }
Example #6
0
        // TODO: push this data in through the constructor, probably in a QuadNodeDefintion class, and make
        // this method private.  Except that would do real work in construction.  Hmmm.
        public void Initialize(double planetRadius, DoubleVector3 planeNormalVector, DoubleVector3 uVector, DoubleVector3 vVector, QuadNodeExtents extents, int level)
        {
            _planetRadius      = planetRadius;
            _planeNormalVector = planeNormalVector;
            _uVector           = uVector;
            _vVector           = vVector;
            _extents           = extents;
            Level = level;

            _locationRelativeToPlanet = (_planeNormalVector) + (_uVector * (_extents.North + (_extents.Width / 2.0))) + (_vVector * (_extents.West + (_extents.Width / 2.0)));
            _locationRelativeToPlanet = _locationRelativeToPlanet.ProjectUnitPlaneToUnitSphere() * _planetRadius;

            _mesh.Initialize(planetRadius, planeNormalVector, uVector, vVector, extents, level);

            Interlocked.Increment(ref _statistics.NumberOfQuadNodes);
            Interlocked.Increment(ref _statistics.NumberOfQuadNodesAtLevel[Level]);
        }
Example #7
0
        // Ridged multifractal
        // See "Texturing & Modeling, A Procedural Approach", Chapter 12
        public double AccumulateNoise(DoubleVector3 sampleLocation, int numberOfOctaves, double lacunarity, double gain, double offset)
        {
            double sum  = 0;   // The return result
            double amp  = 0.5; // Reduce the amplitude per octave of noise
            double prev = 1.0;

            for (int i = 0; i < numberOfOctaves; i++)
            {
                double n = ridge(_noiseGenerator.GetNoise(sampleLocation), offset);
                sum            += n * amp * prev;
                prev            = n;
                sampleLocation *= lacunarity;
                amp            *= gain;
            }

            // Return the result
            return(sum * 1.25 * 2 - 1);
        }
Example #8
0
        public void Draw(DoubleVector3 location, DoubleVector3 cameraLocation, Matrix originBasedViewMatrix, Matrix projectionMatrix)
        {
            _effect.View       = originBasedViewMatrix;
            _effect.Projection = projectionMatrix;
            _effect.World      = GetWorldMatrix(location, cameraLocation);

            // TODO: we shouldn't have to set all of these every time - could be optimized
            SetLightingEffects();
            SetFogEffects();
            SetFillMode();

            DrawMesh();
            if (_settings.ShouldDrawMeshBoundingBoxes)
            {
                DrawBoundingBox();
            }

            _statistics.NumberOfQuadMeshesRendered++;
        }
Example #9
0
        public void Update(DoubleVector3 cameraLocation, DoubleVector3 planetLocation)
        {
            _mesh.Update(cameraLocation, planetLocation);

            if (ShouldSplit())
            {
                Split(cameraLocation, planetLocation);
            }
            else if (ShouldMerge())
            {
                Merge();
            }
            else if (ShouldCancelSplit())
            {
                CancelSplit();
            }

            UpdateSubnodes(cameraLocation, planetLocation);
        }
Example #10
0
        bool CalculateIsAboveHorizonToCamera(DoubleVector3 cameraLocation, DoubleVector3 planetLocation, DoubleVector3 closestVertex)
        {
            // Taken from http://www.crappycoding.com/2009/04/

            // TODO: This algorithm is poor.  Implement this algorithm instead:
            // http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=263350&reply_id=3173799

            // TODO: sometimes the mesh is so large and we're so close the surface that none of the sampled
            // vertices are above the horizon.  That causes problems when we want to do early termination
            // when we do a draw walk on the QuadNode tree (see comments there).  Can we add a test here to
            // see if we're inside the mesh's bounding box?

            var planetToCamera = DoubleVector3.Normalize(cameraLocation - planetLocation);
            var planetToMesh   = DoubleVector3.Normalize(closestVertex - planetLocation);

            var horizonAngle = Math.Acos(_planetRadius * 0.99 / DoubleVector3.Distance(planetLocation, cameraLocation));
            var angleToMesh  = Math.Acos(DoubleVector3.Dot(planetToCamera, planetToMesh));

            return(horizonAngle > angleToMesh);
        }
Example #11
0
 public void Draw(DoubleVector3 cameraLocation, BoundingFrustum originBasedViewFrustum, Matrix originBasedViewMatrix, Matrix projectionMatrix)
 {
     if (_hasSubnodes)
     {
         // TODO: we'd like to stop traversing into subnodes if this node's mesh isn't visibile, but our
         // horizon culling algorithm isn't that great right now and the primary faces are so large that
         // sometimes all of their sample points are below the horizon even though we're above that face
         // and would want to draw its children.  For now, we'll scan all subnodes regardless.  The child
         // node's meshes will do visibility culling on an individual basis.
         foreach (var subnode in _subnodes)
         {
             subnode.Draw(cameraLocation, originBasedViewFrustum, originBasedViewMatrix, projectionMatrix);
         }
     }
     else
     {
         _renderer.Draw(_locationRelativeToPlanet, cameraLocation, originBasedViewMatrix, projectionMatrix);
         _mesh.Draw(cameraLocation, originBasedViewFrustum, originBasedViewMatrix, projectionMatrix);
     }
 }
Example #12
0
        public double GetNoise(DoubleVector3 location)
        {
            // Taken from Interactive Visualization paper

            uint xHash = (uint)location.X.GetHashCode();
            uint yHash = (uint)location.Y.GetHashCode();
            uint zHash = (uint)location.Z.GetHashCode();

            uint result = GetFromPool(0);

            while (xHash > 0 || yHash > 0 || zHash > 0)
            {
                result += GetFromPool(xHash + GetFromPool(yHash + GetFromPool(zHash)));

                xHash >>= 16;
                yHash >>= 16;
                zHash >>= 16;
            }

            return((result % _poolSize) / (double)(_poolSize / 2) - 1.0);
        }
Example #13
0
        double AccumulateNoise(DoubleVector3 location, int numberOfOctaves, double lacunarity, double gain)
        {
            double noiseSum     = 0;
            double amplitude    = 1;
            double amplitudeSum = 0;

            DoubleVector3 sampleLocation = location;

            for (int x = 0; x < numberOfOctaves; x++)
            {
                noiseSum     += amplitude * _noiseGenerator.GetNoise(sampleLocation);
                amplitudeSum += amplitude;

                amplitude      *= gain;
                sampleLocation *= lacunarity;
            }

            noiseSum /= amplitudeSum;

            return(noiseSum * 1.35);
        }
        public double GetHeight(DoubleVector3 location, int level, double scale)
        {
            var heightVariance1 = _varianceGenerator1.GetNoise(location, 5, 4, 2.0, 0.5);

            heightVariance1 = (heightVariance1 + 1);

            var heightVariance2 = _varianceGenerator2.GetNoise(location, 15, 4, 3.0, 0.5);

            heightVariance2 = (heightVariance2 + 1);

            var heightVariance = DoubleMathHelper.Clamp(heightVariance1 * heightVariance2, 0, 2);

            _sampleCount++;
            if (_sampleCount % 1000 == 0)
            {
                Debug.WriteLine(heightVariance);
            }

            var height = heightVariance * scale;

            return(height);
        }
        double AccumulateNoise(DoubleVector3 location, int numberOfOctaves, double lacunarity, double gain)
        {
            double weight    = 1;
            double noise     = 0;
            double amplitude = 1;

            for (int x = 0; x < numberOfOctaves; x++)
            {
                double signal = _noiseGenerator.GetNoise(location);
                signal  = 1 - Math.Abs(signal);
                signal *= signal * weight;

                weight = signal / gain;
                weight = DoubleMathHelper.Clamp(weight, 0, 1);

                noise += (signal * amplitude);

                location  *= lacunarity;
                amplitude *= gain;
            }

            return((noise * 1.25) - 1.0);;
        }
Example #16
0
        public void SetViewParameters(DoubleVector3 location, DoubleVector3 lookAt)
        {
            _cameraLocation = location;

            // To convert from a look-at vector to Euler angles, we'll go
            // via a rotation matrix.  There may be a shorter way, but
            // this works.

            Matrix        rotationMatrix = CreateOriginBasedLookAt(location, lookAt);
            DoubleVector3 lookDirection  = lookAt - location;

            if (IsStraightUp(lookDirection))
            {
                // singularity at north pole
                _cameraYaw   = (float)Math.Atan2(rotationMatrix.M13, rotationMatrix.M33);
                _cameraPitch = MaximumPitch;
                _cameraRoll  = 0;
            }
            else if (IsStraightDown(lookDirection))
            {
                // singularity at south pole
                _cameraYaw   = (float)Math.Atan2(rotationMatrix.M13, rotationMatrix.M33);
                _cameraPitch = MinimumPitch;
                _cameraRoll  = 0;
            }
            else
            {
                // Normal conversion
                _cameraYaw   = (float)Math.Atan2(-rotationMatrix.M31, rotationMatrix.M11);
                _cameraPitch = (float)Math.Atan2(-rotationMatrix.M23, rotationMatrix.M22);
                _cameraRoll  = (float)Math.Asin(rotationMatrix.M21);
            }

            ClampPitch();

            CreateViewMatrix();
        }
Example #17
0
        Matrix GetWorldMatrix(DoubleVector3 location, DoubleVector3 cameraLocation)
        {
            // The mesh stored in the vertex buffer is centered at the origin in order to take it easy on
            // the float number system.  The camera view matrix is also generated as though the camera were
            // at the origin.  In order to correctly render the mesh we translate it away from the origin
            // by the same vector that the mesh (in double space) is displaced from the camera (in double space).

            // We also translate and scale distant meshes to bring them inside the far clipping plane.  For
            // every mesh that's further than the start of the scaled space, we calcuate a new distance
            // using an exponential downscale function to make it fall in the view frustum.  We also scale
            // it down proportionally so that it appears perspective-wise to be identical to the original
            // location.  See the Interactive Visualization paper, page 24.

            Matrix scaleMatrix;
            Matrix translationMatrix;

            var locationRelativeToCamera = location - cameraLocation;
            var distanceFromCamera       = locationRelativeToCamera.Length();
            var unscaledViewSpace        = _settings.FarClippingPlaneDistance * 0.25;

            if (distanceFromCamera > unscaledViewSpace)
            {
                var    scaledViewSpace                = _settings.FarClippingPlaneDistance - unscaledViewSpace;
                double scaledDistanceFromCamera       = unscaledViewSpace + (scaledViewSpace * (1.0 - Math.Exp((scaledViewSpace - distanceFromCamera) / 1000000000)));
                var    scaledLocationRelativeToCamera = DoubleVector3.Normalize(locationRelativeToCamera) * scaledDistanceFromCamera;

                scaleMatrix       = Matrix.CreateScale((float)(scaledDistanceFromCamera / distanceFromCamera));
                translationMatrix = Matrix.CreateTranslation(scaledLocationRelativeToCamera);
            }
            else
            {
                scaleMatrix       = Matrix.Identity;
                translationMatrix = Matrix.CreateTranslation(locationRelativeToCamera);
            }

            return(scaleMatrix * translationMatrix);
        }
Example #18
0
 bool IsStraightUp(DoubleVector3 vector)
 {
     return(vector.X == 0 && vector.Z == 0 && vector.Y > 0);
 }
Example #19
0
        public void Update(DoubleVector3 cameraLocation)
        {
            _terrain.Update(cameraLocation, _location);

            UpdateStatistics(cameraLocation);
        }
Example #20
0
        Matrix CreateOriginBasedLookAt(DoubleVector3 location, DoubleVector3 lookAt)
        {
            Matrix rotationMatrix = Matrix.CreateLookAt(Vector3.Zero, lookAt - location, Vector3.Up);

            return(rotationMatrix);
        }
Example #21
0
 bool IsStraightDown(DoubleVector3 vector)
 {
     return(vector.X == 0 && vector.Z == 0 && vector.Y < 0);
 }
        public double GetNoise(DoubleVector3 location, int startingOctave, int numberOfOctaves, double lacunarity, double gain)
        {
            var sampleLocation = location * (1 << (startingOctave));

            return(AccumulateNoise(sampleLocation, numberOfOctaves, lacunarity, gain));
        }
Example #23
0
        List <Task <IQuadNode> > CreateBackgroundSplitTasks(DoubleVector3 cameraLocation, DoubleVector3 planetLocation)
        {
            // TODO: there's a problem with this algorithm.  If we need to split very deeply because for example
            // the camera is teleported to the surface, we only split one level at a time and wait for that level
            // to finish and for the next update sweep to occur before queuing splits for the next level.  There
            // may be wasted time in there (not clear yet).  We also spend time generating meshes for quads that
            // we know we don't need.  Ideally we'd jump straight to rendering meshes for the new leaves and worry
            // about rendering meshes for the intermediate nodes later when we need them.  This means we need a
            // general way to delay completing a merge (continuing to render its children in the meantime) until
            // a mesh is rendered for that node.  Once we have that behavior
            // we can maybe throw away the vertex buffers for all non-leaf meshes to save memory and regenerate them
            // as needed.  That would take more CPU overall but it's not time sensitive because we'd just keep
            // rendering the child nodes until we got around to it.  That would be a problem only if we end up
            // overloading the GPU but in many cases that wouldn't happen because the merging nodes would be behind
            // the camera as it travels and thus not rendered.
            // Potential problem: we don't know for sure if a node needs to be split until after we generate its mesh.

            _splitInProgress = true;
            var subextents = _extents.Split();

            return(subextents.Select(extent => Task <IQuadNode> .Factory.StartNew(() =>
            {
                var node = _quadNodeFactory.Create();
                node.Initialize(_planetRadius, _planeNormalVector, _uVector, _vVector, extent, Level + 1);
                node.Update(cameraLocation, planetLocation);
                return node;
            }, _cancellationTokenSource.Token, TaskCreationOptions.None, _taskSchedulerFactory.CreateForLevel(Level))).ToList());
        }
Example #24
0
        public double GetSpectralNoise(DoubleVector3 location, double initialFrequencyMultiplier, int numberOfOctaves, double lacunarity, double gain)
        {
            var sampleLocation = location * initialFrequencyMultiplier;

            return(AccumulateNoise(sampleLocation, numberOfOctaves, lacunarity, gain, 1));
        }
        public double GetNoise(DoubleVector3 location)
        {
            double xin = location.X;
            double yin = location.Y;
            double zin = location.Z;

            double n0, n1, n2, n3; // Noise contributions from the four corners

            // Skew the input space to determine which simplex cell we're in
            const double F3 = 1.0 / 3.0;
            double       s  = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D
            int          i  = fastfloor(xin + s);
            int          j  = fastfloor(yin + s);
            int          k  = fastfloor(zin + s);

            const double G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
            double       t  = (i + j + k) * G3;
            double       X0 = i - t;     // Unskew the cell origin back to (x,y,z) space
            double       Y0 = j - t;
            double       Z0 = k - t;
            double       x0 = xin - X0; // The x,y,z distances from the cell origin
            double       y0 = yin - Y0;
            double       z0 = zin - Z0;

            // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
            // Determine which simplex we are in.
            int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
            int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords

            if (x0 >= y0)
            {
                if (y0 >= z0)
                {
                    // X Y Z order
                    i1 = 1;
                    j1 = 0;
                    k1 = 0;
                    i2 = 1;
                    j2 = 1;
                    k2 = 0;
                }
                else if (x0 >= z0)
                {
                    // X Z Y order
                    i1 = 1;
                    j1 = 0;
                    k1 = 0;
                    i2 = 1;
                    j2 = 0;
                    k2 = 1;
                }
                else
                {
                    // Z X Y order
                    i1 = 0;
                    j1 = 0;
                    k1 = 1;
                    i2 = 1;
                    j2 = 0;
                    k2 = 1;
                }
            }
            else
            {
                // x0 < y0
                if (y0 < z0)
                {
                    // Z Y X order
                    i1 = 0;
                    j1 = 0;
                    k1 = 1;
                    i2 = 0;
                    j2 = 1;
                    k2 = 1;
                }
                else if (x0 < z0)
                {
                    // Y Z X order
                    i1 = 0;
                    j1 = 1;
                    k1 = 0;
                    i2 = 0;
                    j2 = 1;
                    k2 = 1;
                }
                else
                {
                    // Y X Z order
                    i1 = 0;
                    j1 = 1;
                    k1 = 0;
                    i2 = 1;
                    j2 = 1;
                    k2 = 0;
                }
            }

            // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
            // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
            // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
            // c = 1/6.

            double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
            double y1 = y0 - j1 + G3;
            double z1 = z0 - k1 + G3;
            double x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
            double y2 = y0 - j2 + 2.0 * G3;
            double z2 = z0 - k2 + 2.0 * G3;
            double x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
            double y3 = y0 - 1.0 + 3.0 * G3;
            double z3 = z0 - 1.0 + 3.0 * G3;

            // Work out the hashed gradient indices of the four simplex corners
            int ii  = i & 255;
            int jj  = j & 255;
            int kk  = k & 255;
            int gi0 = perm[ii + perm[jj + perm[kk]]] % 12;
            int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12;
            int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12;
            int gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12;

            // Calculate the contribution from the four corners
            double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;

            if (t0 < 0)
            {
                n0 = 0.0;
            }
            else
            {
                t0 *= t0;
                n0  = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
            }

            double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;

            if (t1 < 0)
            {
                n1 = 0.0;
            }
            else
            {
                t1 *= t1;
                n1  = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
            }

            double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;

            if (t2 < 0)
            {
                n2 = 0.0;
            }
            else
            {
                t2 *= t2;
                n2  = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
            }

            double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;

            if (t3 < 0)
            {
                n3 = 0.0;
            }
            else
            {
                t3 *= t3;
                n3  = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
            }

            // Add contributions from each corner to get the final noise value.
            // The result is scaled to stay just inside [-1,1]
            return(32.0 * (n0 + n1 + n2 + n3));
        }
Example #26
0
 DoubleVector3 ConvertToMeshSpace(DoubleVector3 planetSpaceVector)
 {
     return(planetSpaceVector - _locationRelativeToPlanet);
 }
Example #27
0
        // TODO: push this data in through the constructor, probably in a QuadMeshDefintion class, and make
        // this method private.  Except that would do real work in construction.  Hmmm.
        public void Initialize(double planetRadius, DoubleVector3 planeNormalVector, DoubleVector3 uVector, DoubleVector3 vVector, QuadNodeExtents extents, int level)
        {
            _planetRadius = planetRadius;
            _extents      = extents;

            // TODO: get this from the QuadNode instead
            _locationRelativeToPlanet = (planeNormalVector) + (uVector * (_extents.North + (_extents.Width / 2.0))) + (vVector * (_extents.West + (_extents.Width / 2.0)));
            _locationRelativeToPlanet = _locationRelativeToPlanet.ProjectUnitPlaneToUnitSphere() * _planetRadius;

            // TODO: cover this in specs
            _boundingBox.Min = new Vector3(float.MaxValue);
            _boundingBox.Max = new Vector3(float.MinValue);

            GenerateIndices();
            var heightmap = _generator.GenerateHeightmapSamples(new HeightmapDefinition()
            {
                GridSize          = _gridSize,
                Stride            = extents.Width / (_gridSize - 1),
                PlaneNormalVector = planeNormalVector,
                UVector           = uVector,
                VVector           = vVector,
                Extents           = _extents,
                QuadLevel         = level,
                PlanetRadius      = planetRadius
            });
            var vertices = GenerateMeshVertices(heightmap);

            CollectHeightmapSamples(heightmap);

            _renderer.Initialize(vertices, _indices, _boundingBox);
        }
Example #28
0
 void UpdateStatistics(DoubleVector3 cameraLocation)
 {
     _statistics.CameraAltitude = DoubleVector3.Distance(_location, cameraLocation) - _radius;
 }
Example #29
0
 public void Draw(DoubleVector3 location, DoubleVector3 cameraLocation, Matrix originBasedViewMatrix, Matrix projectionMatrix)
 {
 }
Example #30
0
        // TODO: push this data in through the constructor, probably in a QuadMeshDefintion class, and make
        // this method private.  Except that would do real work in construction.  Hmmm.
        public void Initialize(double planetRadius, DoubleVector3 planeNormalVector, DoubleVector3 uVector, DoubleVector3 vVector, QuadNodeExtents extents, int level)
        {
            _planetRadius      = planetRadius;
            _planeNormalVector = planeNormalVector;
            _uVector           = uVector;
            _vVector           = vVector;
            _extents           = extents;
            _level             = level;

            // TODO: get this from the QuadNode instead
            _locationRelativeToPlanet = (_planeNormalVector) + (_uVector * (_extents.North + (_extents.Width / 2.0))) + (_vVector * (_extents.West + (_extents.Width / 2.0)));
            _locationRelativeToPlanet = _locationRelativeToPlanet.ProjectUnitPlaneToUnitSphere() * _planetRadius;

            _meshStride = _extents.Width / (_gridSize - 1);

            // TODO: cover this in specs
            _boundingBox.Min = new Vector3(float.MaxValue);
            _boundingBox.Max = new Vector3(float.MinValue);

            GenerateIndices();
            GenerateMeshVertices();
            CollectMeshSamples();

            _renderer.Initialize(_vertices, _indices, _boundingBox);

            TrimUnneededMemory();
        }