예제 #1
0
        //queary
        public BTerrainVisual.eLODLevel getLODLevel(Vector3 pt, Vector3 Eye)
        {
            if (!TerrainGlobals.getVisual().isDynamicLODEnabled())
            {
                return(TerrainGlobals.getVisual().getStaticLODLevel());
            }

            Vector3 d    = pt - Eye;
            float   dist = d.Length();

            if (dist > (float)BTerrainVisual.eLODLevelDists.cLOD3Dist)
            {
                return(BTerrainVisual.eLODLevel.cLOD3);
            }
            else if (dist > (float)BTerrainVisual.eLODLevelDists.cLOD2Dist)
            {
                return(BTerrainVisual.eLODLevel.cLOD2);
            }
            else if (dist > (float)BTerrainVisual.eLODLevelDists.cLOD1Dist)
            {
                return(BTerrainVisual.eLODLevel.cLOD1);
            }

            return(BTerrainVisual.eLODLevel.cLOD0);
        }
예제 #2
0
        public void calcualteAO(eAOQuality quality, bool renderWorldObjects, ref float totalTime, ref float peelTime, ref float gatherTime,
                                int startSampleIndex, int endSampleIndex)
        {
            totalTime  = 0;
            peelTime   = 0;
            gatherTime = 0;

            DateTime n = DateTime.Now;


            //should we multithread?
            if (CoreGlobals.mProcessorInfo.NumLogicalProcessors > 1)
            {
                mUsingMultithreading            = true;
                AmbientOcclusion.IncrementCount = 0;
                AOIncrements = new int[TerrainGlobals.getTerrain().getNumXVerts() * TerrainGlobals.getTerrain().getNumZVerts()];
            }
            else
            {
                mUsingMultithreading = false;
            }



            int width  = 512;
            int height = 512;

            int numXSegments = 1;
            int numYSegments = 1;

            //special settings for Final mode
            if (quality == eAOQuality.cAO_Final)
            {
                numXSegments = 4; //what should these values really be?
                numYSegments = 4; // they should scale, so that huge terrain gets more segments..

                //   width = 1024;
                //  height = 1024;

                // mUsingMultithreading = false;
            }

            //clear any handles available so we can use them as we see fit!
            TerrainGlobals.getTerrain().getQuadNodeRoot().clearVisibleDatHandle();
            TerrainGlobals.getVisual().destroyAllHandles();
            TerrainGlobals.getVisual().setHandleGenMode(true);

            blackoutAO(); //so we can gather light data

            Vector3      mWorldMin   = Vector3.Empty;
            Vector3      mWorldMax   = Vector3.Empty;
            BBoundingBox worldBounds = new BBoundingBox();

            calculateWorldBounds(ref mWorldMin, ref mWorldMax, ref worldBounds, renderWorldObjects);


            mPeeler.init(width, height);

            Vector3 rayDir = -BMathLib.unitY;

            rayDir.Normalize();
            Matrix worldToView = Matrix.Identity;
            Matrix viewToProj  = Matrix.Identity;

            int numDesiredSamples = (int)Math.Sqrt((int)quality);

            int            startIndex = 0;
            int            endIndex   = numDesiredSamples;
            List <Vector3> rayDirs    = null;

            if (startSampleIndex != -1)
            {
                rayDirs    = giveStratifiedOnHemiSphere(0, numDesiredSamples, false);
                startIndex = startSampleIndex;
                endIndex   = Math.Min(endSampleIndex, rayDirs.Count);
            }
            else
            {
                rayDirs    = giveStratifiedOnHemiSphere(0, numDesiredSamples, true);
                startIndex = 0;
                endIndex   = rayDirs.Count;
            }

            float rcpNumSamples = 1.0f / (float)(rayDirs.Count);


            int numSamples = endIndex - startIndex;
            //begin our peel & gather process...
            bool ownBeginScene = !BRenderDevice.isInSceneRender();

            if (ownBeginScene)
            {
                BRenderDevice.getDevice().BeginScene();
            }
            for (int dc = startIndex; dc < endIndex; dc++)
            {
                //choose one
                rayDir = -rayDirs[dc];

                computeWorldToView(ref rayDir, ref mWorldMin, ref mWorldMax, out worldToView);
                for (int x = 0; x < numXSegments; x++)
                {
                    for (int y = 0; y < numYSegments; y++)
                    {
                        //calculate our lightspace projection matrix
                        computeViewToProj(ref rayDir, worldBounds, worldToView, out viewToProj,
                                          numXSegments, numYSegments, x, y);


                        //use worker threads..
                        gatherWorkerData wd = new gatherWorkerData(0, 0, TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts(),
                                                                   width, height,
                                                                   rayDir,
                                                                   worldToView * viewToProj,
                                                                   rcpNumSamples);
                        mPeeler.mDepthArray = null;
                        mPeeler.mDepthArray = wd.fragList;



                        //create our depth layers
                        DateTime dpn = DateTime.Now;
                        mPeeler.depthPeel(ref rayDir, ref worldToView, ref viewToProj, renderWorldObjects);
                        TimeSpan dpts = DateTime.Now - dpn;
                        peelTime += (float)dpts.TotalMinutes;



                        //do final gathering (AO SPECIFIC)
                        if (mUsingMultithreading)
                        {
                            finalGatherMultiThreaded(wd);
                        }
                        else
                        {
                            DateTime fgn = DateTime.Now;
                            finalGatherSingleThreaded(wd);
                            TimeSpan fgts = DateTime.Now - fgn;
                            gatherTime += (float)fgts.TotalMinutes;
                        }
                        wd = null;
                        mPeeler.mDepthArray = null;
                    }
                }
            }



            if (ownBeginScene)
            {
                BRenderDevice.getDevice().EndScene();
            }
            mPeeler.destroy();
            TerrainGlobals.getVisual().setHandleGenMode(false);



            //if we're using multithreading, wait for all our worker threads to finish.
            if (mUsingMultithreading)
            {
                while (AmbientOcclusion.IncrementCount <= numSamples - 1)
                {
                    Thread.Sleep(1);
                }

                float[] AOVals = TerrainGlobals.getEditor().getAmbientOcclusionValues();
                for (int i = 0; i < AOIncrements.Length; i++)
                {
                    AOVals[i] = AOIncrements[i] * rcpNumSamples;
                }
            }



            TimeSpan ts = DateTime.Now - n;

            totalTime = (float)ts.TotalMinutes;
        }
예제 #3
0
        public bool render()
        {
            if (mSetVBs.Count == 0)
            {
                createRenderVBs();
                if (mSetVBs.Count == 0)
                {
                    return(false);
                }
            }

            BRenderDevice.getDevice().VertexDeclaration = VertexTypes.Pos.vertDecl;

            //my shader is started in the parent FoliageManager class..

            BTerrainQuadNode qn = TerrainGlobals.getTerrain().getQuadNodeLeafArray()[mOwnerQNIndex];

            //find our visual handle index
            //CLM the skirts f**k this up.. just find the highest LOD that's valid...
            BTerrainVisualDataHandle vdh = null;

            for (int i = 0; i < (int)Terrain.BTerrainVisual.eLODLevel.cLODCount; i++)
            {
                if (qn.mVisualDataIndxPerLOD[i] != -1)
                {
                    vdh = TerrainGlobals.getVisual().getVisualHandle(qn.mVisualDataIndxPerLOD[i]);
                    break;
                }
            }

            if (vdh == null)
            {
                return(false);
            }

            //bind my QN positions texture
            FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mTerrainQNPosTexture, vdh.mHandle.mPositionsTexture);

            Vector4 QnData = new Vector4((BTerrainQuadNode.getMaxNodeWidth() >> vdh.LOD), TerrainGlobals.getTerrain().getTileScale(), mOwnerNodeDesc.mMinXVert, mOwnerNodeDesc.mMinZVert);

            FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mTerrainQNData, QnData);


            for (int setI = 0; setI < mSetsUsed.Count; setI++)
            {
                FoliageSet set = FoliageManager.giveSet(mSetsUsed[setI]);

                float rcpBladeImgWidth = 1.0f / (float)set.mNumBlades;
                FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetRCPBladeTexWidth, rcpBladeImgWidth);


                FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetAlbedoTexture,
                                                                  set.mD3DAlbedoTexture == null?
                                                                  BRenderDevice.getTextureManager().getDefaultTexture(TextureManager.eDefaultTextures.cDefTex_Red):
                                                                  set.mD3DAlbedoTexture.mTexture);

                FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetOpacityTexture,
                                                                  set.mD3DOpacityTexture == null ?
                                                                  BRenderDevice.getTextureManager().getDefaultTexture(TextureManager.eDefaultTextures.cDefTex_White) :
                                                                  set.mD3DOpacityTexture.mTexture);


                FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetPositionsTexture, set.mD3DPositionsTexture);
                FoliageManager.mFoliageGPUShader.mShader.SetValue(FoliageManager.mSetUVsTexture, set.mD3DUVsTexture);

                //DRAW US FOOL!
                BRenderDevice.getDevice().SetStreamSource(0, mSetVBs[setI], 0);
                BRenderDevice.getDevice().Indices = mSetIBs[setI];

                FoliageManager.mFoliageGPUShader.mShader.CommitChanges();
                BRenderDevice.getDevice().DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, mSetVertCount[setI], 0, mSetPolyCount[setI]);
            }

            return(true);
        }
예제 #4
0
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------

        public void computeHeightFieldDirectFloat(uint width, uint height, bool includeSimMod, Vector3 upDir, bool onlyDoOneSample, ref float[] output)
        {
            copyTempD3DValues();
            TerrainGlobals.getTerrain().getQuadNodeRoot().clearVisibleDatHandle();
            TerrainGlobals.getVisual().destroyAllHandles();
            TerrainGlobals.getVisual().setHandleGenMode(true);
            GC.WaitForPendingFinalizers();

            ExportTo360.checkLoadRender();

            createTempTextures(width, height);

            calculateWorldBounds(includeSimMod);


            mHeightFieldAttributes = new BHeightFieldAttributes(width, height);

            Matrix       worldToView = Matrix.Identity;
            Matrix       viewToProj = Matrix.Identity;
            BBoundingBox worldBounds = new BBoundingBox();
            double       worldMinY = 0, worldMaxY = 0;

            computeTransforms(upDir, ref worldToView, ref viewToProj, ref worldBounds, ref worldMinY, ref worldMaxY);

            float mWorldRangeY = (float)(mWorldMax.Y - mWorldMin.Y);

            uint numVals = width * height;

            if (output == null || output.Length != numVals)
            {
                output = new float[numVals];
                for (uint i = 0; i < numVals; i++)
                {
                    output[i] = float.MinValue;
                }
            }

            uint   cNumSamples = (uint)(onlyDoOneSample?1:4);
            Random rand        = new Random();

            for (uint sampleIndex = 0; sampleIndex < cNumSamples; sampleIndex++)
            {
                float xOfs = sampleIndex != 0 ? (float)((rand.NextDouble() * 2) - 1) : 0.0f;
                float yOfs = sampleIndex != 0 ? (float)((rand.NextDouble() * 2) - 1) : 0.0f;

                Matrix projOfs = Matrix.Translation(xOfs / width, yOfs / height, 0.0f);

                generateHeightBuffer(ref pHighDepthSurf, width, height, true, worldToView, viewToProj * projOfs, includeSimMod);

                #region fill & lock

                //mWorldMin.Y += 1.0f;
                //mWorldMax.Y -= 1.0f;

                unsafe
                {
                    GraphicsStream texstreamHI = pHighDepths.LockRectangle(0, LockFlags.None);
                    float *        pSrcHigh    = (float *)texstreamHI.InternalDataPointer;

                    //copy the data out so we can screw with it.
                    for (uint c = 0; c < numVals; c++)
                    {
                        output[c] = (float)Math.Max(output[c], pSrcHigh[c]);
                    }
                    pHighDepths.UnlockRectangle(0);
                }
                //find the max & min depth for this slice


                #endregion
            }



            releaseTempTextures();
            restoreTempD3DValues();
            TerrainGlobals.getVisual().setHandleGenMode(false);
            ExportTo360.checkUnloadRender();


            //#region dumpHeightfiled
            //{
            //   FileStream s = File.Open("_outHiDirect.raw", FileMode.OpenOrCreate, FileAccess.Write);
            //   BinaryWriter f = new BinaryWriter(s);
            //   for (int i = 0; i < width * height; i++)
            //   {
            //      float kp = (output[i] - mWorldMin.Y) / mWorldRangeY;
            //      ushort op = (ushort)(kp * ushort.MaxValue);
            //      f.Write(op);
            //   }
            //   f.Close();
            //   s.Close();
            //}

            //#endregion
        }
예제 #5
0
        public void computeHeightField(uint width, uint height, bool includeSimMod, Vector3 upDir, uint cNumSamples)
        {
            copyTempD3DValues();
            TerrainGlobals.getTerrain().getQuadNodeRoot().clearVisibleDatHandle();
            TerrainGlobals.getVisual().destroyAllHandles();
            TerrainGlobals.getVisual().setHandleGenMode(true);
            GC.WaitForPendingFinalizers();

            ExportTo360.checkLoadRender();

            createTempTextures(width, height);

            calculateWorldBounds(includeSimMod);


            mHeightFieldAttributes = new BHeightFieldAttributes(width, height);

            Matrix       worldToView = Matrix.Identity;
            Matrix       viewToProj = Matrix.Identity;
            BBoundingBox worldBounds = new BBoundingBox();
            double       worldMinY = 0, worldMaxY = 0;

            computeTransforms(upDir, ref worldToView, ref viewToProj, ref worldBounds, ref worldMinY, ref worldMaxY);

            Random rand = new Random();

            double minDepth = float.MaxValue;
            double maxDepth = float.MinValue;



            cNumSamples = (uint)BMathLib.Clamp(cNumSamples, 1, 32);

            for (uint sampleIndex = 0; sampleIndex < cNumSamples; sampleIndex++)
            {
                float xOfs = sampleIndex != 0 ? (float)((rand.NextDouble() * 2) - 1) : 0.0f;
                float yOfs = sampleIndex != 0 ? (float)((rand.NextDouble() * 2) - 1) : 0.0f;

                Matrix projOfs = Matrix.Translation(xOfs / width, yOfs / height, 0.0f);

                generateDepthBuffer(ref pHighDepthSurf, width, height, false, worldToView, viewToProj * projOfs, includeSimMod);
                generateDepthBuffer(ref pLowDepthSurf, width, height, true, worldToView, viewToProj * projOfs, includeSimMod);

                fillHeightFieldTexture(width, height, mHeightFieldAttributes, pLowDepths, pHighDepths, ref minDepth, ref maxDepth);
            }

            viewToProj = viewToProj * Matrix.Translation(0.0f, 0.0f, (float)(-minDepth)) * Matrix.Scaling(1.0f, 1.0f, (float)(1.0f / (maxDepth - minDepth)));
            double newWorldMinY = worldMinY + (worldMaxY - worldMinY) * minDepth;

            worldMaxY = worldMinY + (worldMaxY - worldMinY) * maxDepth;
            worldMinY = newWorldMinY;
            minDepth  = 0.0f;
            maxDepth  = 1.0f;

            mHeightFieldAttributes.mWidth  = width;
            mHeightFieldAttributes.mHeight = height;
            mHeightFieldAttributes.mBounds = worldBounds;

            mHeightFieldAttributes.mWorldMinY   = (float)worldMinY;
            mHeightFieldAttributes.mWorldMaxY   = (float)worldMaxY;
            mHeightFieldAttributes.mWorldRangeY = (float)(worldMaxY - worldMinY);


            float minZ = 0;
            float maxZ = 1;
            float x    = 0;
            float y    = 0;

            Matrix cMTProjToScreen = BMathLib.matrixFrom16floats(
                width * .5f, 0.0f, 0.0f, 0.0f,
                0.0f, height * -.5f, 0.0f, 0.0f,
                0.0f, 0.0f, maxZ - minZ, 0.0f,
                x + width * .5f, y + height * .5f, minZ, 1.0f);

            mHeightFieldAttributes.mWorldToNormZ = worldToView * viewToProj * cMTProjToScreen;


            Matrix screenToProj    = Matrix.Invert(cMTProjToScreen);
            Matrix projToView      = Matrix.Invert(viewToProj);
            Matrix cMTScreenToView = Matrix.Multiply(screenToProj, projToView);

            mHeightFieldAttributes.mNormZToWorld = cMTScreenToView * Matrix.Invert(worldToView);

            releaseTempTextures();
            restoreTempD3DValues();
            TerrainGlobals.getVisual().setHandleGenMode(false);
            ExportTo360.checkUnloadRender();

            //copy our pixels from the previous point
            {
                for (int q = 0; q < width; q++)
                {
                    mHeightFieldAttributes.mpTexelsLO[(width - 1) * width + q] = mHeightFieldAttributes.mpTexelsLO[(width - 2) * width + q];
                    mHeightFieldAttributes.mpTexelsLO[q * width + (width - 1)] = mHeightFieldAttributes.mpTexelsLO[q * width + (width - 2)];
                    mHeightFieldAttributes.mpTexelsLO[q]         = mHeightFieldAttributes.mpTexelsLO[width + q];
                    mHeightFieldAttributes.mpTexelsLO[q * width] = mHeightFieldAttributes.mpTexelsLO[q * width + (1)];

                    mHeightFieldAttributes.mpTexelsHI[(width - 1) * width + q] = mHeightFieldAttributes.mpTexelsHI[(width - 2) * width + q];
                    mHeightFieldAttributes.mpTexelsHI[q * width + (width - 1)] = mHeightFieldAttributes.mpTexelsHI[q * width + (width - 2)];
                    mHeightFieldAttributes.mpTexelsHI[q]         = mHeightFieldAttributes.mpTexelsHI[width + q];
                    mHeightFieldAttributes.mpTexelsHI[q * width] = mHeightFieldAttributes.mpTexelsHI[q * width + (1)];
                }
            }

            #region dumpHeightfiled
            //{
            //   FileStream s = File.Open(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\out.raw", FileMode.OpenOrCreate, FileAccess.Write);
            //   BinaryWriter f = new BinaryWriter(s);
            //   for (int i = 0; i < width * height; i++)
            //   {
            //      f.Write(mHeightFieldAttributes.mpTexelsLO[i]);
            //      f.Write(mHeightFieldAttributes.mpTexelsHI[i]);
            //   }
            //   f.Close();
            //   s.Close();
            //}

            #endregion
        }