Ejemplo n.º 1
0
//          /// <summary>
//          /// Normalizes all brick data
//          /// </summary>
//          public void	FinalizeLeafVoxels() {
//              for ( int Z=0; Z < 2; Z++ )
//                  for ( int Y=0; Y < 2; Y++ )
//                      for ( int X=0; X < 2; X++ ) {
//                          OctreeNode	child = m_children[X,Y,Z];
//                          if ( child != null ) {
//                              child.FinalizeLeafVoxels();
//                          }
//                      }
//
//              // Normalize brick data
//              m_brick.Normalize();
//          }

            /// <summary>
            /// Builds all the mip at all levels
            /// </summary>
            public void     BuildAllMips()
            {
                if (m_brick.accumulationCounter > 0)
                {
                    // Already built! Just normalize...
                    m_brick.Normalize();
                    return;
                }

                for (int Z = 0; Z < 2; Z++)
                {
                    for (int Y = 0; Y < 2; Y++)
                    {
                        for (int X = 0; X < 2; X++)
                        {
                            OctreeNode child = m_children[X, Y, Z];
                            if (child == null)
                            {
                                continue;
                            }

                            // Make sure the child's brick data are built
                            child.BuildAllMips();

                            // Accumulate from all valid children
                            m_brick.Accumulate(ref child.m_brick);
                        }
                    }
                }

                // Normalize
                m_brick.accumulationCounter = 8;                        // We always assume all children contribute equally
                m_brick.Normalize();
            }
Ejemplo n.º 2
0
        public OctreeBuilder(Device _device, float3 _wsCornerMin, float _volumeSize, int _subdivisionsLevelsCount)
        {
            int   subdivisionsCount = 1 << _subdivisionsLevelsCount;
            float voxelSize         = _volumeSize / subdivisionsCount;

                        #if LOAD_OCTREE
            // Load the octree
            OctreeNode root = null;
            using (System.IO.FileStream S = new System.IO.FileInfo("CornellBox_" + subdivisionsCount + ".octree").OpenRead())
                using (System.IO.BinaryReader R = new System.IO.BinaryReader(S))
                    root = new OctreeNode(R);
                        #else
            //////////////////////////////////////////////////////////////////////////
            // 1] Generate a list of non-empty voxels
            //
                        #if !LOAD_VOXELS
            // Start collecting all non-empty voxels
            float3 dV            = voxelSize * float3.One;
            float3 wsVoxelMin    = _wsCornerMin + 0.5f * dV;                    // Start voxel center
            float  voxelDistance = (float)Math.Sqrt(dV.x * dV.x + dV.y * dV.y + dV.z * dV.z);

            List <Voxel> voxels = new List <Voxel>(10000000);                           // 10 million voxels

            DateTime buildStartTime = DateTime.Now;

            float3 voxelCenter = new float3();
            voxelCenter.z = wsVoxelMin.z;
            for (uint Z = 0; Z < subdivisionsCount; Z++, voxelCenter.z += dV.z)
            {
                voxelCenter.y = wsVoxelMin.y;
                for (uint Y = 0; Y < subdivisionsCount; Y++, voxelCenter.y += dV.y)
                {
                    voxelCenter.x = wsVoxelMin.x;
                    for (uint X = 0; X < subdivisionsCount; X++, voxelCenter.x += dV.x)
                    {
                        float2 sceneDistance = Map(voxelCenter);
                        if (sceneDistance.x > voxelDistance)
                        {
                            continue;                                           // Scene is too far away
                        }
                        float3 sceneNormal = Normal(voxelCenter);
                        float3 sceneAlbedo = Albedo(voxelCenter, sceneDistance.y);

                        voxels.Add(new Voxel()
                        {
                            X      = X, Y = Y, Z = Z,
                            albedo = sceneAlbedo,
                            normal = sceneNormal
                        });
                    }
                }
            }

            DateTime buildEndTime = DateTime.Now;

            System.Diagnostics.Debug.WriteLine("Octree build time = " + (buildEndTime - buildStartTime).TotalSeconds + " seconds");

            // Write to disk as it takes hell of a time to generate!
            using (System.IO.FileStream S = new System.IO.FileInfo("CornellBox_" + subdivisionsCount + ".voxels").Create())
                using (System.IO.BinaryWriter W = new System.IO.BinaryWriter(S)) {
                    W.Write(_wsCornerMin.x);
                    W.Write(_wsCornerMin.y);
                    W.Write(_wsCornerMin.z);
                    W.Write(_volumeSize);
                    W.Write(_subdivisionsLevelsCount);
                    W.Write(voxels.Count);
                    foreach (Voxel V in voxels)
                    {
                        W.Write(V.X);
                        W.Write(V.Y);
                        W.Write(V.Z);
                        W.Write(V.albedo.x);
                        W.Write(V.albedo.y);
                        W.Write(V.albedo.z);
                        W.Write(V.normal.x);
                        W.Write(V.normal.y);
                        W.Write(V.normal.z);
                    }
                }
                        #else
            // Read from disk as it takes hell of a time to generate!
            List <Voxel> voxels = null;

            using (System.IO.FileStream S = new System.IO.FileInfo("CornellBox_" + subdivisionsCount + ".voxels").OpenRead())
                using (System.IO.BinaryReader R = new System.IO.BinaryReader(S)) {
                    _wsCornerMin.x           = R.ReadSingle();
                    _wsCornerMin.y           = R.ReadSingle();
                    _wsCornerMin.z           = R.ReadSingle();
                    _volumeSize              = R.ReadSingle();
                    _subdivisionsLevelsCount = R.ReadInt32();
                    int voxelsCount = (int)R.ReadUInt32();
                    voxels = new List <Voxel>(voxelsCount);

                    Voxel V = new Voxel();
                    for (int voxelIndex = 0; voxelIndex < voxelsCount; voxelIndex++)
                    {
                        V.X        = R.ReadUInt32();
                        V.Y        = R.ReadUInt32();
                        V.Z        = R.ReadUInt32();
                        V.albedo.x = R.ReadSingle();
                        V.albedo.y = R.ReadSingle();
                        V.albedo.z = R.ReadSingle();
                        V.normal.x = R.ReadSingle();
                        V.normal.y = R.ReadSingle();
                        V.normal.z = R.ReadSingle();
                        voxels.Add(V);
                    }
                }
                        #endif

            //////////////////////////////////////////////////////////////////////////
            // 2] Encode these voxels into an octree
            OctreeNode root            = new OctreeNode(_wsCornerMin, _volumeSize, 0);
            float3     wsVoxelPosition = float3.Zero;

            // 2.1) Add each voxel individually
            foreach (Voxel V in voxels)
            {
                wsVoxelPosition.x = _wsCornerMin.x + (0.5f + V.X) * voxelSize;
                wsVoxelPosition.y = _wsCornerMin.y + (0.5f + V.Y) * voxelSize;
                wsVoxelPosition.z = _wsCornerMin.z + (0.5f + V.Z) * voxelSize;
                root.AddVoxel(ref wsVoxelPosition, V, _subdivisionsLevelsCount);
            }

//          // 2.2) Normalize existing voxels
//          root.FinalizeLeafVoxels();

            // 2.3) Build mips at all levels
            root.BuildAllMips();

            // Save the resulting octree
            using (System.IO.FileStream S = new System.IO.FileInfo("CornellBox_" + subdivisionsCount + ".octree").Create())
                using (System.IO.BinaryWriter W = new System.IO.BinaryWriter(S))
                    root.SaveRoot(W);
                        #endif
        }