예제 #1
0
        private unsafe Mesh ConvertToMesh(GraphicsDevice graphicsDevice, PrimitiveType primitiveType, LightProbeRuntimeData lightProbeRuntimeData)
        {
            // Generate data for vertex buffer
            var vertices = new VertexPositionNormalColor[lightProbeRuntimeData.LightProbes.Length];

            for (var i = 0; i < lightProbeRuntimeData.LightProbes.Length; i++)
            {
                vertices[i] = new VertexPositionNormalColor(lightProbeRuntimeData.Vertices[i], Vector3.Zero, Color4.White);
            }

            // Generate data for index buffer
            var indices = new int[lightProbeRuntimeData.Faces.Count * 6];

            for (var i = 0; i < lightProbeRuntimeData.Faces.Count; ++i)
            {
                var currentFace = lightProbeRuntimeData.Faces[i];

                // Skip infinite edges to not clutter display
                // Maybe we could reenable it when we have better infinite nodes
                if (currentFace.Vertices[0] >= lightProbeRuntimeData.UserVertexCount ||
                    currentFace.Vertices[1] >= lightProbeRuntimeData.UserVertexCount ||
                    currentFace.Vertices[2] >= lightProbeRuntimeData.UserVertexCount)
                {
                    continue;
                }

                indices[i * 6 + 0] = currentFace.Vertices[0];
                indices[i * 6 + 1] = currentFace.Vertices[1];
                indices[i * 6 + 2] = currentFace.Vertices[1];
                indices[i * 6 + 3] = currentFace.Vertices[2];
                indices[i * 6 + 4] = currentFace.Vertices[2];
                indices[i * 6 + 5] = currentFace.Vertices[0];
            }

            var boundingBox = BoundingBox.Empty;

            for (int i = 0; i < vertices.Length; i++)
            {
                BoundingBox.Merge(ref boundingBox, ref vertices[i].Position, out boundingBox);
            }

            // Compute bounding sphere
            BoundingSphere boundingSphere;

            fixed(void *verticesPtr = vertices)
            BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere);

            var layout = vertices[0].GetLayout();

            var meshDraw = new MeshDraw
            {
                IndexBuffer   = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length),
                VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertices, BufferFlags.VertexBuffer).RecreateWith(vertices), layout, vertices.Length) },
                DrawCount     = indices.Length,
                PrimitiveType = primitiveType,
            };

            wireframeResources.Add(meshDraw.VertexBuffers[0].Buffer);
            wireframeResources.Add(meshDraw.IndexBuffer.Buffer);

            return(new Mesh {
                Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere
            });
        }
예제 #2
0
        private void UpdateLightProbeWireframe()
        {
            var lightProbeProcessor = game.SceneSystem.SceneInstance.GetProcessor <LightProbeProcessor>();

            var lightProbeRuntimeData = lightProbeProcessor?.VisibilityGroup.Tags.Get(LightProbeRenderer.CurrentLightProbes);

            if (lightProbeRuntimeData == null)
            {
                // Nothing, just remove existing wireframe and exit
                Cleanup();
                return;
            }

            var needWireframeRefresh = false;

            if (lightProbeRuntimeData != currentLightProbeRuntimeData)
            {
                // LightProbe runtime data changed (light probe added or removed) => force a wireframe refresh
                currentLightProbeRuntimeData = lightProbeRuntimeData;
                needWireframeRefresh         = true;
            }
            else
            {
                // check if we need to trigger a manual refresh (the LightProbeProcessor only reacts to LightProbe added/removed at runtime)
                var needPositionRefresh     = false;
                var needCoefficientsRefresh = false;
                for (var lightProbeIndex = 0; lightProbeIndex < lightProbeRuntimeData.LightProbes.Length; lightProbeIndex++)
                {
                    // check if lightprobe moved
                    var lightProbe = lightProbeRuntimeData.LightProbes[lightProbeIndex] as LightProbeComponent;
                    if (lightProbe == null)
                    {
                        continue;
                    }

                    if (lightProbe.Entity.Transform.WorldMatrix.TranslationVector != lightProbeRuntimeData.Vertices[lightProbeIndex])
                    {
                        needPositionRefresh  = true;
                        needWireframeRefresh = true;
                    }

                    // check if lightprobe coefficients changed
                    var coefficientIndex = lightProbeIndex * LightProbeGenerator.LambertHamonicOrder * LightProbeGenerator.LambertHamonicOrder;
                    for (int i = 0; i < LightProbeGenerator.LambertHamonicOrder * LightProbeGenerator.LambertHamonicOrder; ++i)
                    {
                        var expectedCoefficient = lightProbe.Coefficients != null ? lightProbe.Coefficients[i] : default(Color3);
                        if (expectedCoefficient != lightProbeRuntimeData.Coefficients[coefficientIndex + i])
                        {
                            needCoefficientsRefresh = true;
                        }
                    }
                }

                if (needPositionRefresh)
                {
                    lightProbeProcessor.UpdateLightProbePositions();
                    lightProbeRuntimeData = lightProbeProcessor.VisibilityGroup.Tags.Get(LightProbeRenderer.CurrentLightProbes);
                    if (lightProbeRuntimeData == null)
                    {
                        Cleanup();
                        return;
                    }
                }
                else if (needCoefficientsRefresh)
                {
                    lightProbeProcessor.UpdateLightProbeCoefficients();
                }
            }

            // Do we need to regenerate the wireframe?
            if (!needWireframeRefresh)
            {
                return;
            }

            Cleanup();

            // Need at least a tetrahedron to not have empty buffers
            if (lightProbeRuntimeData.Tetrahedra.Count > 0)
            {
                var mesh  = ConvertToMesh(game.GraphicsDevice, PrimitiveType.LineList, lightProbeRuntimeData);
                var model = new Model
                {
                    mesh,
                    wireframeMaterial,
                };

                wireframeModelComponent = new ModelComponent(model)
                {
                    RenderGroup = LightProbeWireGroup, Enabled = IsLightProbeVolumesVisible
                };
                var lightProbeWireframe = new Entity("LightProbe Wireframe")
                {
                    wireframeModelComponent
                };
                debugEntity.AddChild(lightProbeWireframe);
            }
        }