Exemplo n.º 1
0
        /// <summary>
        /// Cleans up the rendering view of the models.
        /// </summary>
        /// <param name="frustumCuller">The area where models can be viewed from the camera.</param>
        /// <param name="frustumCullMode">The mode of the culling.</param>
        public void FrustumCull(FrustumCulling frustumCuller, EnumFrustumCullMode frustumCullMode)
        {
            indicesGroupsCount = 0;
            int multiplier = (IntPtr.Size == 8) ? 2 : 1;

            RenderedTriangles = 0;
            AllocatedTris     = 0;

            for (int i = 0; i < poolLocations.Count; i++)
            {
                ModelDataPoolLocation location = poolLocations[i];

                int size = location.IndicesEnd - location.IndicesStart;
                if (location.IsVisible(frustumCullMode, frustumCuller))
                {
                    indicesStartsByte[indicesGroupsCount * multiplier] = location.IndicesStart * 4; // Offset in bytes, not ints
                    indicesSizes[indicesGroupsCount] = size;

                    RenderedTriangles += size / 3;

                    indicesGroupsCount++;
                }

                AllocatedTris += size / 3;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Attempts to remove the model from the pool if the model exists.  Will throw an invalid call or an InvalidOperationException if used improperly.
        /// </summary>
        /// <param name="location">The location of the model data.</param>
        public void RemoveLocation(ModelDataPoolLocation location)
        {
            if (location.PoolId != poolId)
            {
                throw new Exception("invalid call");
            }

            if (!poolLocations.Remove(location))
            {
                throw new InvalidOperationException("Tried to remove mesh that does not exist. This shouldn't happen");
            }

            // Last location?
            if (poolLocations.Count == 0)
            {
                indicesPosition  = 0;
                verticesPosition = 0;
            }
            else
            {
                // Location at the end of the buffer?
                if (location.IndicesEnd == indicesPosition && location.VerticesEnd == verticesPosition)
                {
                    indicesPosition  = poolLocations[poolLocations.Count - 1].IndicesEnd;
                    verticesPosition = poolLocations[poolLocations.Count - 1].VerticesEnd;
                }
            }


            CalcFragmentation();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Attempts to add the new model.
        /// </summary>
        /// <param name="capi">The core client API</param>
        /// <param name="modeldata">The model to add</param>
        /// <param name="modelOrigin">The origin point of the model.</param>
        /// <param name="frustumCullSphere">The culling sphere.</param>
        /// <returns>The location of the model (and the data) in the pool.</returns>
        public ModelDataPoolLocation TryAdd(ICoreClientAPI capi, MeshData modeldata, Vec3i modelOrigin, Sphere frustumCullSphere)
        {
            if (poolLocations.Count >= MaxPartsPerPool)
            {
                return(null);
            }

            // Can't add a model data to far away from our baseposition, otherwise our floating point positions
            // become too inaccurate
            if (poolOrigin != null && modelOrigin.SquareDistanceTo(poolOrigin) > 5000 * 5000)
            {
                return(null);
            }

            if (CurrentFragmentation > 0.05f)
            {
                ModelDataPoolLocation location = TrySqueezeInbetween(capi, modeldata, modelOrigin, frustumCullSphere);
                if (location != null)
                {
                    return(location);
                }
            }

            return(TryAppend(capi, modeldata, modelOrigin, frustumCullSphere));
        }
Exemplo n.º 4
0
        ModelDataPoolLocation TryAppend(ICoreClientAPI capi, MeshData modeldata, Vec3i modelOrigin, Sphere frustumCullSphere)
        {
            if (modeldata.IndicesCount + indicesPosition >= IndicesPoolSize || modeldata.VerticesCount + verticesPosition >= VerticesPoolSize)
            {
                return(null);
            }

            ModelDataPoolLocation location = InsertAt(capi, modeldata, modelOrigin, frustumCullSphere, indicesPosition, verticesPosition, -1);

            indicesPosition  += modeldata.IndicesCount;
            verticesPosition += modeldata.VerticesCount;

            return(location);
        }
Exemplo n.º 5
0
        ModelDataPoolLocation TrySqueezeInbetween(ICoreClientAPI capi, MeshData modeldata, Vec3i modelOrigin, Sphere frustumCullSphere)
        {
            int curVertexPos = 0;
            int curIndexPos  = 0;

            for (int i = 0; i < poolLocations.Count; i++)
            {
                ModelDataPoolLocation location = poolLocations[i];

                if (location.IndicesStart - curIndexPos > modeldata.IndicesCount && location.VerticesStart - curVertexPos > modeldata.VerticesCount)
                {
                    return(InsertAt(capi, modeldata, modelOrigin, frustumCullSphere, curIndexPos, curVertexPos, i));
                }

                curIndexPos  = location.IndicesEnd + 1;
                curVertexPos = location.VerticesEnd + 1;
            }

            return(null);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Adds a model to the mesh pool.
        /// </summary>
        /// <param name="modeldata">The model data</param>
        /// <param name="modelOrigin">The origin point of the Model</param>
        /// <param name="frustumCullSphere">The culling sphere.</param>
        /// <returns>The location identifier for the pooled model.</returns>
        public ModelDataPoolLocation AddModel(MeshData modeldata, Vec3i modelOrigin, Sphere frustumCullSphere)
        {
            ModelDataPoolLocation location = null;

            for (int i = 0; i < pools.Count; i++)
            {
                location = pools[i].TryAdd(capi, modeldata, modelOrigin, frustumCullSphere);
                if (location != null)
                {
                    break;
                }
            }

            if (location == null)
            {
                int vertexSize = Math.Max(modeldata.VerticesCount + 1, defaultVertexPoolSize);
                int indexSize  = Math.Max(modeldata.IndicesCount + 1, defaultIndexPoolSize);

                if (vertexSize > defaultIndexPoolSize)
                {
                    capi.World.Logger.Warning("Chunk (or some other mesh source at origin: {0}) exceeds default geometric complexity maximum of {1} vertices and {2} indices. You must be loading some very complex objects (#v = {3}, #i = {4}). Adjusted Pool size accordingly.", modelOrigin, defaultVertexPoolSize, defaultIndexPoolSize, modeldata.VerticesCount, modeldata.IndicesCount);
                }

                MeshDataPool pool = MeshDataPool.AllocateNewPool(capi, vertexSize, indexSize, maxPartsPerPool, customFloats, customShorts, customBytes, customInts);
                pool.poolOrigin = modelOrigin;

                masterPool.AddModelDataPool(pool);
                pools.Add(pool);
                location = pool.TryAdd(capi, modeldata, modelOrigin, frustumCullSphere);
            }

            if (location == null)
            {
                capi.World.Logger.Fatal("Can't add modeldata (probably a tesselated chunk @{0}) to the model data pool list, it exceeds the size of a single empty pool of {1} vertices and {2} indices. You must be loading some very complex objects (#v = {3}, #i = {4}). Try increasing MaxVertexSize and MaxIndexSize. The whole chunk will be invisible.", modelOrigin, defaultVertexPoolSize, defaultIndexPoolSize, modeldata.VerticesCount, modeldata.IndicesCount);

                //location = new ModelDataPoolLocation() { frustumCullSphere = frustumCullSphere };
                //pools[0].poolLocations.Add(location);
            }

            return(location);
        }
Exemplo n.º 7
0
        ModelDataPoolLocation InsertAt(ICoreClientAPI capi, MeshData modeldata, Vec3i modelOrigin, Sphere frustumCullSphere, int indexPosition, int vertexPosition, int listPosition)
        {
            // Shift the indices numbers accordingly
            for (int i = 0; i < modeldata.IndicesCount; i++)
            {
                modeldata.Indices[i] += vertexPosition;
            }

            // Relative offset to our pool origin
            if (poolOrigin != null)
            {
                int dx = modelOrigin.X - this.poolOrigin.X;
                int dy = modelOrigin.Y - this.poolOrigin.Y;
                int dz = modelOrigin.Z - this.poolOrigin.Z;

                for (int i = 0; i < modeldata.VerticesCount; i++)
                {
                    modeldata.xyz[3 * i]     += dx;
                    modeldata.xyz[3 * i + 1] += dy;
                    modeldata.xyz[3 * i + 2] += dz;
                }
            }

            // Shift position to the end of the used buffers memory
            modeldata.XyzOffset     = vertexPosition * MeshData.XyzSize;
            modeldata.NormalsOffset = vertexPosition * MeshData.NormalSize;
            modeldata.RgbaOffset    = vertexPosition * MeshData.RgbaSize;
            modeldata.Rgba2Offset   = vertexPosition * MeshData.RgbaSize;
            modeldata.UvOffset      = vertexPosition * MeshData.UvSize;
            modeldata.FlagsOffset   = vertexPosition * MeshData.FlagsSize;
            modeldata.IndicesOffset = indexPosition * MeshData.IndexSize;

            if (modeldata.CustomFloats != null)
            {
                modeldata.CustomFloats.BaseOffset = vertexPosition * modeldata.CustomFloats.InterleaveStride;
            }

            if (modeldata.CustomBytes != null)
            {
                modeldata.CustomBytes.BaseOffset = vertexPosition * modeldata.CustomBytes.InterleaveStride;
            }

            if (modeldata.CustomInts != null)
            {
                modeldata.CustomInts.BaseOffset = vertexPosition * modeldata.CustomInts.InterleaveStride;
            }

            // Load into graphics card
            capi.Render.UpdateMesh(modelRef, modeldata);


            // Assign a location to it
            ModelDataPoolLocation poolLocation = new ModelDataPoolLocation()
            {
                IndicesStart      = indexPosition,
                IndicesEnd        = indexPosition + modeldata.IndicesCount,
                VerticesStart     = vertexPosition,
                VerticesEnd       = vertexPosition + modeldata.VerticesCount,
                PoolId            = poolId,
                FrustumCullSphere = frustumCullSphere
            };

            // Maintain correct ordering
            if (listPosition != -1)
            {
                poolLocations.Insert(listPosition, poolLocation);
            }
            else
            {
                poolLocations.Add(poolLocation);
            }

            CalcFragmentation();

            return(poolLocation);
        }