Axiom.Components.Terrain.TerrainQuadTreeNode.CalculateCurrentLod C# (CSharp) Method

CalculateCurrentLod() public method

Calculate appropriate LOD for this node and children
public CalculateCurrentLod ( Camera cam, float cFactor ) : bool
cam Axiom.Core.Camera The camera to be used (this should already be the LOD camera)
cFactor float The cFactor which incorporates the viewport size, max pixel error and lod bias
return bool
        public bool CalculateCurrentLod(Camera cam, float cFactor)
        {
            mSelfOrChildRendered = false;

            //check children first.
            int childrenRenderedOut = 0;
            if (!IsLeaf)
            {
                for (int i = 0; i < 4; ++i)
                {
                    if (mChildren[i].CalculateCurrentLod(cam, cFactor))
                        ++childrenRenderedOut;
                }
            }

            if (childrenRenderedOut == 0)
            {
                // no children were within their LOD ranges, so we should consider our own
                Vector3 localPos = cam.DerivedPosition - mLocalCentre - mTerrain.Position;
                float dist;
                if (TerrainGlobalOptions.IsUseRayBoxDistanceCalculation)
                {
                    // Get distance to this terrain node (to closest point of the box)
                    // head towards centre of the box (note, box may not cover mLocalCentre because of height)
                    Vector3 dir = mAABB.Center - localPos;
                    dir.Normalize();
                    Ray ray = new Ray(localPos, dir);
                    IntersectResult intersectRes = ray.Intersects(mAABB);

                    // ray will always intersect, we just want the distance
                    dist = intersectRes.Distance;
                }
                else
                {
                    // distance to tile centre
                    dist = localPos.Length;
                    // deduct half the radius of the box, assume that on average the 
                    // worst case is best approximated by this
                    dist -= (mBoundingRadius * 0.5f);
                }

                // Do material LOD
                Material material = this.Material;
                Axiom.Core.LodStrategy str = material.LodStrategy;
                float lodValue = str.GetValue(mRend, cam);
                mMaterialLodIndex = (ushort)material.GetLodIndex(lodValue);
                // For each LOD, the distance at which the LOD will transition *downwards*
                // is given by 
                // distTransition = maxDelta * cFactor;
                int lodLvl = 0;
                mCurrentLod = -1;
                foreach (LodLevel l in mLodLevels)
                {
                    // If we have no parent, and this is the lowest LOD, we always render
                    // this is the 'last resort' so to speak, we always enoucnter this last
                    if (lodLvl + 1 == mLodLevels.Count && mParent == null)
                    {
                        CurentLod = lodLvl;
                        mSelfOrChildRendered = true;
                        mLodTransition = 0;
                    }
                    else
                    {
                        //check the distance
                        LodLevel ll = l;
                        // Calculate or reuse transition distance
                        float distTransition;
                        if ( Utility.RealEqual( cFactor, ll.LastTranistionDist ) )
                            distTransition = ll.LastTranistionDist;
                        else
                        {
                            distTransition = ll.MaxHeightDelta * cFactor;
                            ll.LastCFactor = cFactor;
                            ll.LastTranistionDist = distTransition;
                        }

                        if (dist < distTransition)
                        {
                            // we're within range of this LOD
                            CurentLod = lodLvl;
                            mSelfOrChildRendered = true;

                            if (mTerrain.IsMorphRequired)
                            {
                                // calculate the transition percentage
                                // we need a percentage of the total distance for just this LOD, 
                                // which means taking off the distance for the next higher LOD
                                // which is either the previous entry in the LOD list, 
                                // or the largest of any children. In both cases these will
                                // have been calculated before this point, since we process
                                // children first. Distances at lower LODs are guaranteed
                                // to be larger than those at higher LODs

                                float distTotal = distTransition;
                                if (IsLeaf)
                                {
                                    // Any higher LODs?
#warning: check if this if is correct!
                                    if (lodLvl < mLodLevels.Count)
                                    {
                                        int prec = lodLvl - 1;
                                        distTotal -= mLodLevels[lodLvl].LastTranistionDist;
                                    }
                                }
                                else
                                {
                                    // Take the distance of the lowest LOD of child
                                    LodLevel childLod = mChildWithMaxHeightDelta.GetLodLevel(
                                        (ushort)(mChildWithMaxHeightDelta.LodCount - 1));
                                    distTotal -= childLod.LastTranistionDist;
                                }
                                // fade from 0 to 1 in the last 25% of the distance
                                float distMorphRegion = distTotal * 0.25f;
                                float distRemain = distTransition - dist;

                                mLodTransition = 1.0f - (distRemain / distMorphRegion);
                                mLodTransition = System.Math.Min(1.0f, mLodTransition);
                                mLodTransition = System.Math.Max(0.0f, mLodTransition);

                                // Pass both the transition % and target LOD (GLOBAL current + 1)
                                // this selectively applies the morph just to the
                                // vertices which would drop out at this LOD, even 
                                // while using the single shared vertex data
                                mRend.SetCustomParameter(Terrain.LOD_MORPH_CUSTOM_PARAM,
                                    new Vector4(mLodTransition, mCurrentLod + mBaseLod + 1, 0, 0));
                            }//end if

                            // since LODs are ordered from highest to lowest detail, 
                            // we can stop looking now
                            break;
                        }//end if
                    }//end else
                    ++lodLvl;
                }//end for each
            }//end if
            else
            {
                // we should not render ourself
                mCurrentLod = -1;
                mSelfOrChildRendered = true;
                if (childrenRenderedOut < 4)
                {
                    // only *some* children decided to render on their own, but either 
                    // none or all need to render, so set the others manually to their lowest
                    for (int i = 0; i < 4; ++i)
                    {
                        TerrainQuadTreeNode child = mChildren[i];
                        if (!child.IsSelfOrChildrenRenderedAtCurrentLod)
                        {
                            child.CurentLod = child.LodCount - 1;
                            child.LodTransition = 1.0f;
                        }
                    }
                }//(childRenderedCount < 4)
            }// (childRenderedCount == 0)

            return mSelfOrChildRendered;
        }
        /// <summary>