Ejemplo n.º 1
0
        /// <summary>
        /// Updates all children of this object. Override this to change default behavior.
        /// </summary>
        /// <param name="updateState">The current update state.</param>
        /// <param name="children">The full list of children that should be updated.</param>
        protected override void UpdateChildrenInternal(SceneRelatedUpdateState updateState, List <SceneObject> children)
        {
            bool prevForceState = updateState.ForceTransformUpdatesOnChilds;

            updateState.ForceTransformUpdatesOnChilds = prevForceState || m_forceTransformUpdateOnChilds;
            m_forceTransformUpdateOnChilds            = false;
            try
            {
                int childCount = children.Count;
                for (int loop = 0; loop < childCount; loop++)
                {
                    // Forward current transform matrix to child objects
                    Matrix4Stack currentWorld = updateState.World;
                    currentWorld.Push(m_transform);
                    try
                    {
                        children[loop].Update(updateState);
                    }
                    finally
                    {
                        currentWorld.Pop();
                    }
                }
            }
            finally
            {
                updateState.ForceTransformUpdatesOnChilds = prevForceState;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RenderState"/> class.
        /// </summary>
        /// <param name="device">The device object.</param>
        private RenderState(EngineDevice device)
        {
            // Set device members
            this.Device = device;
            DeviceIndex = device.DeviceIndex;

            // Initialize world matrix
            _world = new Matrix4Stack(Matrix4x4.Identity);

            // Create settings stack
            _cachedRenderStackEntries = new Stack <RenderStackEntry>(8);
            _renderSettingsStack      = new Stack <RenderStackEntry>();
            _sceneStack = new Stack <Tuple <Scene?, ResourceDictionary?> >();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Generates all vertex structures needed for this object
        /// </summary>
        private static VertexStructure GenerateStructure(ACFileInfo fileInfo)
        {
            VertexStructure result = new VertexStructure();

            // Create all vertex structures
            Matrix4Stack transformStack = new Matrix4Stack();

            foreach (ACObjectInfo actObject in fileInfo.Objects)
            {
                FillVertexStructure(result, fileInfo.Materials, actObject, transformStack);
            }

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RenderState"/> class.
        /// </summary>
        /// <param name="device">The device object.</param>
        /// <param name="performanceCalculator">The object used to calculate performance values</param>
        private RenderState(EngineDevice device, PerformanceAnalyzer performanceCalculator)
        {
            //Set device members
            m_device         = device;
            this.DeviceIndex = device.DeviceIndex;

            //Initialize world matrix
            m_world = new Matrix4Stack(Matrix4x4.Identity);

            //Create settings stack
            m_renderSettingsStack = new Stack <RenderStackEntry>();
            m_sceneStack          = new Stack <Tuple <Core.Scene, ResourceDictionary> >();

            m_perfomanceCalculator = performanceCalculator;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Resets the render state.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="camera">The camera for the new render target.</param>
        /// <param name="viewInformation">The view information.</param>
        /// <param name="renderTargets">The render targets used for rendering.</param>
        internal void Reset(
            RenderTargets renderTargets,
            SharpDX.Mathematics.Interop.RawViewportF viewport,
            Camera3DBase camera, ViewInformation viewInformation)
        {
            m_renderSettingsStack.Clear();
            m_sceneStack.Clear();
            m_currentScene = null;
            m_world        = new Matrix4Stack(Matrix4x4.Identity);

            //Inititialize current render properties
            m_currentRenderSettings = new RenderStackEntry();
            m_currentRenderSettings.Matrix4Stack    = new Matrix4Stack();
            m_currentRenderSettings.RenderTargets   = renderTargets;
            m_currentRenderSettings.SingleViewport  = viewport;
            m_currentRenderSettings.Camera          = camera;
            m_currentRenderSettings.ViewInformation = viewInformation;

            //Apply initial render properties
            m_currentRenderSettings.Apply(m_device.DeviceImmediateContextD3D11);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Generates the geometry needed for this object
        /// </summary>
        internal static Geometry GenerateGeometry(ACFileInfo fileInfo)
        {
            var result = new Geometry();

            // Create a surface for each material first
            var materialList = fileInfo.Materials;

            for (var actMaterialIndex = 0; actMaterialIndex < materialList.Count; actMaterialIndex++)
            {
                result.CreateSurface();
            }

            // Now load the geometry itself
            var transformStack = new Matrix4Stack();

            foreach (var actObject in fileInfo.Objects)
            {
                FillGeometry(result, materialList, actObject, transformStack);
            }

            return(result);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Fills the given geometry using information from the given AC-File-Objects.
        /// </summary>
        /// <param name="objInfo">The object information from the AC file.</param>
        /// <param name="acMaterials">A list containing all materials from the AC file.</param>
        /// <param name="geometry">The Geometry to be filled.</param>
        /// <param name="transformStack">Current matrix stack (for stacked objects).</param>
        private static void FillGeometry(Geometry geometry, List <ACMaterialInfo> acMaterials, ACObjectInfo objInfo, Matrix4Stack transformStack)
        {
            var standardShadedVertices = new List <Tuple <int, int> >();

            transformStack.Push();
            try
            {
                // Perform local transformation for the current AC object
                transformStack.TransformLocal(objInfo.Rotation);
                transformStack.TranslateLocal(objInfo.Translation);

                // Build geometry material by material
                for (var actMaterialIndex = 0; actMaterialIndex < acMaterials.Count; actMaterialIndex++)
                {
                    var actGeometrySurface = geometry.Surfaces[actMaterialIndex];

                    // Initialize local index table (needed for vertex reuse)
                    var oneSideVertexCount = objInfo.Vertices.Count;
                    var localIndices       = new int[oneSideVertexCount * 2];

                    for (var loop = 0; loop < localIndices.Length; loop++)
                    {
                        localIndices[loop] = int.MaxValue;
                    }

                    // Process all surfaces
                    foreach (var actSurface in objInfo.Surfaces)
                    {
                        // Get the vertex index on which to start
                        var startVertexIndex   = geometry.CountVertices;
                        var startTriangleIndex = actGeometrySurface.CountTriangles;

                        // Only handle surfaces of the current material
                        if (actSurface.Material != actMaterialIndex)
                        {
                            continue;
                        }

                        // Sort out unsupported surfaces
                        if (actSurface.VertexReferences.Count < 3)
                        {
                            continue;
                        }
                        if (actSurface.IsLine)
                        {
                            continue;
                        }
                        if (actSurface.IsClosedLine)
                        {
                            continue;
                        }

                        // Preprocess referenced vertices
                        var oneSideSurfaceVertexCount    = actSurface.VertexReferences.Count;
                        var countSurfaceSides            = actSurface.IsTwoSided ? 2 : 1;
                        var onGeometryReferencedVertices = new int[oneSideSurfaceVertexCount * countSurfaceSides];
                        var surfaceVertexReferences      = actSurface.VertexReferences;

                        for (var loop = 0; loop < surfaceVertexReferences.Count; loop++)
                        {
                            var actTexCoord = actSurface.TextureCoordinates[loop];

                            if (!actSurface.IsFlatShaded)
                            {
                                // Try to reuse vertices on standard shading
                                if (localIndices[surfaceVertexReferences[loop]] == int.MaxValue)
                                {
                                    var position = Vector3.Transform(
                                        objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                        transformStack.Top);
                                    localIndices[surfaceVertexReferences[loop]] = geometry.AddVertex(new VertexBasic(
                                                                                                         position, Color4.White, actTexCoord, Vector3.Zero));
                                    if (actSurface.IsTwoSided)
                                    {
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount] = geometry.AddVertex(new VertexBasic(
                                                                                                                                  position, Color4.White, actTexCoord, Vector3.Zero));
                                    }
                                }

                                // Store vertex reference for this surface's index
                                onGeometryReferencedVertices[loop] = localIndices[surfaceVertexReferences[loop]];
                                if (actSurface.IsTwoSided)
                                {
                                    onGeometryReferencedVertices[loop + oneSideSurfaceVertexCount] =
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount];
                                }
                            }
                            else
                            {
                                // Create one vertex for one reference for flat shading
                                var position = Vector3.Transform(
                                    objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                    transformStack.Top);
                                onGeometryReferencedVertices[loop] = geometry.AddVertex(new VertexBasic(
                                                                                            position, Color4.White, actTexCoord, Vector3.Zero));

                                if (actSurface.IsTwoSided)
                                {
                                    onGeometryReferencedVertices[loop + oneSideSurfaceVertexCount] = geometry.AddVertex(new VertexBasic(
                                                                                                                            position, Color4.White, actTexCoord, Vector3.Zero));
                                }
                            }
                        }

                        // Build object geometry
                        switch (actSurface.VertexReferences.Count)
                        {
                        case 3:
                            // Front side
                            actGeometrySurface.AddTriangle(
                                onGeometryReferencedVertices[0],
                                onGeometryReferencedVertices[1],
                                onGeometryReferencedVertices[2]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actGeometrySurface.AddTriangle(
                                    onGeometryReferencedVertices[5],
                                    onGeometryReferencedVertices[4],
                                    onGeometryReferencedVertices[3]);
                            }
                            break;

                        case 4:
                            // Front side
                            actGeometrySurface.AddTriangle(
                                onGeometryReferencedVertices[0],
                                onGeometryReferencedVertices[1],
                                onGeometryReferencedVertices[2]);
                            actGeometrySurface.AddTriangle(
                                onGeometryReferencedVertices[2],
                                onGeometryReferencedVertices[3],
                                onGeometryReferencedVertices[0]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actGeometrySurface.AddTriangle(
                                    onGeometryReferencedVertices[6],
                                    onGeometryReferencedVertices[5],
                                    onGeometryReferencedVertices[4]);
                                actGeometrySurface.AddTriangle(
                                    onGeometryReferencedVertices[4],
                                    onGeometryReferencedVertices[7],
                                    onGeometryReferencedVertices[6]);
                            }
                            break;

                        default:
                            if (!actSurface.IsTwoSided)
                            {
                                // Front side
                                actGeometrySurface.AddPolygonByCuttingEars(onGeometryReferencedVertices);
                            }
                            else
                            {
                                // Front and back side
                                actGeometrySurface.AddPolygonByCuttingEars(onGeometryReferencedVertices.Subset(0, oneSideSurfaceVertexCount));
                                actGeometrySurface.AddPolygonByCuttingEars(onGeometryReferencedVertices.Subset(oneSideSurfaceVertexCount, oneSideSurfaceVertexCount));
                            }
                            break;
                        }

                        // Perform shading
                        if (actSurface.IsFlatShaded)
                        {
                            actGeometrySurface.CalculateNormalsFlat(
                                startTriangleIndex, actGeometrySurface.CountTriangles - startTriangleIndex);
                        }
                        else
                        {
                            // Nothing to be done for now..
                            var vertexCount = geometry.CountVertices - startVertexIndex;
                            if (vertexCount > 0)
                            {
                                standardShadedVertices.Add(
                                    Tuple.Create(startVertexIndex, vertexCount));
                            }
                        }
                    }

                    // Calculate default shading finally (if any)
                    foreach (var actStandardShadedPair in standardShadedVertices)
                    {
                        geometry.CalculateNormals(
                            actStandardShadedPair.Item1,
                            actStandardShadedPair.Item2);
                    }
                    standardShadedVertices.Clear();
                }

                // Fill in all child object data
                foreach (var actObjInfo in objInfo.Children)
                {
                    FillGeometry(geometry, acMaterials, actObjInfo, transformStack);
                }
            }
            finally
            {
                transformStack.Pop();
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Fills the given vertex structure using information from the given AC-File-Objects.
        /// </summary>
        /// <param name="objInfo">The object information from the AC file.</param>
        /// <param name="acMaterials">A list containing all materials from the AC file.</param>
        /// <param name="structure">The VertexStructure to be filled.</param>
        /// <param name="transformStack">Current matrix stack (for stacked objects).</param>
        private static void FillVertexStructure(VertexStructure structure, List <ACMaterialInfo> acMaterials, ACObjectInfo objInfo, Matrix4Stack transformStack)
        {
            List <Tuple <int, int> > standardShadedVertices = new List <Tuple <int, int> >();

            transformStack.Push();
            try
            {
                // Perform local transformation for the current AC object
                transformStack.TransformLocal(objInfo.Rotation);
                transformStack.TranslateLocal(objInfo.Translation);

                // Build structures material by material
                for (int actMaterialIndex = 0; actMaterialIndex < acMaterials.Count; actMaterialIndex++)
                {
                    ACMaterialInfo actMaterial = acMaterials[actMaterialIndex];

                    VertexStructureSurface actStructSurface = structure.CreateOrGetExistingSurface(actMaterial.CreateMaterialProperties());
                    bool isNewSurface = actStructSurface.CountTriangles == 0;

                    // Create and configure vertex structure
                    actStructSurface.Material   = NamedOrGenericKey.Empty;
                    actStructSurface.TextureKey = !string.IsNullOrEmpty(objInfo.Texture) ? new NamedOrGenericKey(objInfo.Texture) : NamedOrGenericKey.Empty;
                    actStructSurface.MaterialProperties.DiffuseColor  = actMaterial.Diffuse;
                    actStructSurface.MaterialProperties.AmbientColor  = actMaterial.Ambient;
                    actStructSurface.MaterialProperties.EmissiveColor = actMaterial.Emissive;
                    actStructSurface.MaterialProperties.Shininess     = actMaterial.Shininess;
                    actStructSurface.MaterialProperties.SpecularColor = actMaterial.Specular;

                    // Initialize local index table (needed for vertex reuse)
                    int   oneSideVertexCount = objInfo.Vertices.Count;
                    int[] localIndices       = new int[oneSideVertexCount * 2];
                    for (int loop = 0; loop < localIndices.Length; loop++)
                    {
                        localIndices[loop] = int.MaxValue;
                    }

                    // Process all surfaces
                    foreach (ACSurface actSurface in objInfo.Surfaces)
                    {
                        // Get the vertex index on which to start
                        int startVertexIndex   = structure.CountVertices;
                        int startTriangleIndex = actStructSurface.CountTriangles;

                        // Only handle surfaces of the current material
                        if (actSurface.Material != actMaterialIndex)
                        {
                            continue;
                        }

                        // Sort out unsupported surfaces
                        if (actSurface.VertexReferences.Count < 3)
                        {
                            continue;
                        }
                        if (actSurface.IsLine)
                        {
                            continue;
                        }
                        if (actSurface.IsClosedLine)
                        {
                            continue;
                        }

                        // Preprocess referenced vertices
                        int        oneSideSurfaceVertexCount     = actSurface.VertexReferences.Count;
                        int        countSurfaceSides             = actSurface.IsTwoSided ? 2 : 1;
                        int[]      onStructureReferencedVertices = new int[oneSideSurfaceVertexCount * countSurfaceSides];
                        List <int> surfaceVertexReferences       = actSurface.VertexReferences;
                        for (int loop = 0; loop < surfaceVertexReferences.Count; loop++)
                        {
                            Vector2 actTexCoord = actSurface.TextureCoordinates[loop];

                            if (!actSurface.IsFlatShaded)
                            {
                                // Try to reuse vertices on standard shading
                                if (localIndices[surfaceVertexReferences[loop]] == int.MaxValue)
                                {
                                    Vector3 position = Vector3.Transform(
                                        objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                        transformStack.Top);
                                    localIndices[surfaceVertexReferences[loop]] = structure.AddVertex(new Vertex(
                                                                                                          position, Color4.White, actTexCoord, Vector3.Zero));
                                    if (actSurface.IsTwoSided)
                                    {
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount] = structure.AddVertex(new Vertex(
                                                                                                                                   position, Color4.White, actTexCoord, Vector3.Zero));
                                    }
                                }

                                // Store vertex reference for this surface's index
                                onStructureReferencedVertices[loop] = localIndices[surfaceVertexReferences[loop]];
                                if (actSurface.IsTwoSided)
                                {
                                    onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] =
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount];
                                }
                            }
                            else
                            {
                                // Create one vertex for one reference for flat shading
                                Vector3 position = Vector3.Transform(
                                    objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                    transformStack.Top);
                                onStructureReferencedVertices[loop] = structure.AddVertex(new Vertex(
                                                                                              position, Color4.White, actTexCoord, Vector3.Zero));
                                if (actSurface.IsTwoSided)
                                {
                                    onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] = structure.AddVertex(new Vertex(
                                                                                                                              position, Color4.White, actTexCoord, Vector3.Zero));
                                }
                            }
                        }

                        // Build object geometry
                        switch (actSurface.VertexReferences.Count)
                        {
                        case 3:
                            // Front side
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[0],
                                onStructureReferencedVertices[1],
                                onStructureReferencedVertices[2]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[5],
                                    onStructureReferencedVertices[4],
                                    onStructureReferencedVertices[3]);
                            }
                            break;

                        case 4:
                            // Front side
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[0],
                                onStructureReferencedVertices[1],
                                onStructureReferencedVertices[2]);
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[2],
                                onStructureReferencedVertices[3],
                                onStructureReferencedVertices[0]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[6],
                                    onStructureReferencedVertices[5],
                                    onStructureReferencedVertices[4]);
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[4],
                                    onStructureReferencedVertices[7],
                                    onStructureReferencedVertices[6]);
                            }
                            break;

                        default:
                            if (!actSurface.IsTwoSided)
                            {
                                // Front side
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices);
                            }
                            else
                            {
                                // Front and back side
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(0, oneSideSurfaceVertexCount));
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(oneSideSurfaceVertexCount, oneSideSurfaceVertexCount));
                            }
                            break;
                        }

                        // Perform shading
                        if (actSurface.IsFlatShaded)
                        {
                            actStructSurface.CalculateNormalsFlat(
                                startTriangleIndex, actStructSurface.CountTriangles - startTriangleIndex);
                        }
                        else
                        {
                            // Nothing to be done for now..
                            int vertexCount = structure.CountVertices - startVertexIndex;
                            if (vertexCount > 0)
                            {
                                standardShadedVertices.Add(
                                    Tuple.Create((int)startVertexIndex, vertexCount));
                            }
                        }
                    }

                    // Calculate default shading finally (if any)
                    foreach (var actStandardShadedPair in standardShadedVertices)
                    {
                        structure.CalculateNormals(
                            actStandardShadedPair.Item1,
                            actStandardShadedPair.Item2);
                    }
                    standardShadedVertices.Clear();

                    // Append generated VertexStructure to the output collection
                    if ((actStructSurface.CountTriangles <= 0) &&
                        (isNewSurface))
                    {
                        structure.RemoveSurface(actStructSurface);
                    }
                }

                //Fill in all child object data
                foreach (ACObjectInfo actObjInfo in objInfo.Childs)
                {
                    FillVertexStructure(structure, acMaterials, actObjInfo, transformStack);
                }
            }
            finally
            {
                transformStack.Pop();
            }
        }
        /// <summary>
        /// IDWriteTextLayout::Draw calls this function to instruct the client to render a run of glyphs.
        /// </summary>
        /// <param name="clientDrawingContext">The application-defined drawing context passed to  <see cref="M:SharpDX.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" />.</param>
        /// <param name="baselineOriginX">The pixel location (X-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="baselineOriginY">The pixel location (Y-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="measuringMode">The measuring method for glyphs in the run, used with the other properties to determine the rendering mode.</param>
        /// <param name="glyphRun">Pointer to the glyph run instance to render.</param>
        /// <param name="glyphRunDescription">A pointer to the optional glyph run description instance which contains properties of the characters  associated with this run.</param>
        /// <param name="clientDrawingEffect">Application-defined drawing effects for the glyphs to render. Usually this argument represents effects such as the foreground brush filling the interior of text.</param>
        /// <returns>
        /// If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        /// <unmanaged>HRESULT DrawGlyphRun([None] void* clientDrawingContext,[None] FLOAT baselineOriginX,[None] FLOAT baselineOriginY,[None] DWRITE_MEASURING_MODE measuringMode,[In] const DWRITE_GLYPH_RUN* glyphRun,[In] const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,[None] IUnknown* clientDrawingEffect)</unmanaged>
        /// <remarks>
        /// The <see cref="M:SharpDX.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" /> function calls this callback function with all the information about glyphs to render. The application implements this callback by mostly delegating the call to the underlying platform's graphics API such as {{Direct2D}} to draw glyphs on the drawing context. An application that uses GDI can implement this callback in terms of the <see cref="M:SharpDX.DirectWrite.BitmapRenderTarget.DrawGlyphRun(System.Single,System.Single,SharpDX.Direct2D1.MeasuringMode,SharpDX.DirectWrite.GlyphRun,SharpDX.DirectWrite.RenderingParams,SharpDX.Color4)" /> method.
        /// </remarks>
        public override SDX.Result DrawGlyphRun(
            object clientDrawingContext, float baselineOriginX, float baselineOriginY,
            MeasuringMode measuringMode, GlyphRun glyphRun, GlyphRunDescription glyphRunDescription, SDX.ComObject clientDrawingEffect)
        {
            if ((glyphRun.Indices == null) ||
                (glyphRun.Indices.Length == 0))
            {
                return(SDX.Result.Ok);;
            }

            SharpDX.DirectWrite.Factory dWriteFactory = GraphicsCore.Current.FactoryDWrite;
            SharpDX.Direct2D1.Factory   d2DFactory    = GraphicsCore.Current.FactoryD2D;

            // Extrude geometry data out of given glyph run
            SimplePolygon2DGeometrySink geometryExtruder = new SimplePolygon2DGeometrySink(new Vector2(baselineOriginX, baselineOriginY));

            using (PathGeometry pathGeometry = new PathGeometry(d2DFactory))
            {
                // Write all geometry data into a standard PathGeometry object
                using (GeometrySink geoSink = pathGeometry.Open())
                {
                    glyphRun.FontFace.GetGlyphRunOutline(
                        glyphRun.FontSize,
                        glyphRun.Indices,
                        glyphRun.Advances,
                        glyphRun.Offsets,
                        glyphRun.IsSideways,
                        glyphRun.BidiLevel % 2 == 1,
                        geoSink);
                    geoSink.Close();
                }

                // Simplify written geometry and write it into own structure
                pathGeometry.Simplify(GeometrySimplificationOption.Lines, m_geometryOptions.SimplificationFlatternTolerance, geometryExtruder);
            }

            // Structure for caching the result
            VertexStructure        tempStructure = new VertexStructure();
            VertexStructureSurface tempSurface   = tempStructure.CreateSurface();

            // Create the text surface
            if (m_geometryOptions.MakeSurface)
            {
                // Separate polygons by clock direction
                // Order polygons as needed for further hole finding algorithm
                IEnumerable <Polygon2D> fillingPolygons = geometryExtruder.GeneratedPolygons
                                                          .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.CounterClockwise)
                                                          .OrderBy(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y);
                List <Polygon2D> holePolygons = geometryExtruder.GeneratedPolygons
                                                .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.Clockwise)
                                                .OrderByDescending(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y)
                                                .ToList();

                // Build geometry for all polygons
                int loopPolygon = 0;
                foreach (Polygon2D actFillingPolygon in fillingPolygons)
                {
                    // Find all corresponding holes
                    BoundingBox2D           actFillingPolygonBounds = actFillingPolygon.BoundingBox;
                    IEnumerable <Polygon2D> correspondingHoles      = holePolygons
                                                                      .Where(actHolePolygon => actHolePolygon.BoundingBox.IsContainedBy(actFillingPolygonBounds))
                                                                      .ToList();

                    // Two steps here:
                    // - Merge current filling polygon and all its holes.
                    // - Remove found holes from current hole list
                    Polygon2D      polygonForRendering     = actFillingPolygon;
                    Polygon2D      polygonForTriangulation = actFillingPolygon.Clone();
                    List <Vector2> cutPoints = new List <Vector2>();
                    foreach (Polygon2D actHole in correspondingHoles)
                    {
                        holePolygons.Remove(actHole);
                        polygonForRendering     = polygonForRendering.MergeWithHole(actHole, Polygon2DMergeOptions.Default, cutPoints);
                        polygonForTriangulation = polygonForTriangulation.MergeWithHole(actHole, new Polygon2DMergeOptions()
                        {
                            MakeMergepointSpaceForTriangulation = true
                        });
                    }

                    loopPolygon++;
                    int actBaseIndex = (int)tempStructure.CountVertices;

                    EdgeOrder edgeOrder = polygonForRendering.EdgeOrder;
                    float     edgeSize  = edgeOrder == EdgeOrder.CounterClockwise ? 0.1f : 0.4f;

                    // Append all vertices to temporary VertexStructure
                    for (int loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                    {
                        // Calculate 3d location and texture coordinate
                        Vector3 actVertexLocation = new Vector3(
                            polygonForRendering.Vertices[loop].X,
                            0f,
                            polygonForRendering.Vertices[loop].Y);
                        Vector2 actTexCoord = new Vector2(
                            (polygonForRendering.Vertices[loop].X - polygonForRendering.BoundingBox.Location.X) / polygonForRendering.BoundingBox.Size.X,
                            (polygonForRendering.Vertices[loop].Y - polygonForRendering.BoundingBox.Location.Y) / polygonForRendering.BoundingBox.Size.Y);
                        if (float.IsInfinity(actTexCoord.X) || float.IsNaN(actTexCoord.X))
                        {
                            actTexCoord.X = 0f;
                        }
                        if (float.IsInfinity(actTexCoord.Y) || float.IsNaN(actTexCoord.Y))
                        {
                            actTexCoord.Y = 0f;
                        }

                        // Append the vertex to the result
                        tempStructure.AddVertex(
                            new Vertex(
                                actVertexLocation,
                                m_geometryOptions.SurfaceVertexColor,
                                actTexCoord,
                                new Vector3(0f, 1f, 0f)));
                    }

                    // Generate cubes on each vertex if requested
                    if (m_geometryOptions.GenerateCubesOnVertices)
                    {
                        for (int loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                        {
                            Color4 colorToUse      = Color4.GreenColor;
                            float  pointRenderSize = 0.1f;
                            if (cutPoints.Contains(polygonForRendering.Vertices[loop]))
                            {
                                colorToUse      = Color4.RedColor;
                                pointRenderSize = 0.15f;
                            }

                            Vector3 actVertexLocation = new Vector3(
                                polygonForRendering.Vertices[loop].X,
                                0f,
                                polygonForRendering.Vertices[loop].Y);
                            tempSurface.BuildCube24V(actVertexLocation, pointRenderSize, colorToUse);
                        }
                    }

                    // Triangulate the polygon
                    IEnumerable <int> triangleIndices = polygonForTriangulation.TriangulateUsingCuttingEars();
                    if (triangleIndices == null)
                    {
                        continue;
                    }
                    if (triangleIndices == null)
                    {
                        throw new SeeingSharpGraphicsException("Unable to triangulate given PathGeometry object!");
                    }

                    // Append all triangles to the temporary structure
                    using (IEnumerator <int> indexEnumerator = triangleIndices.GetEnumerator())
                    {
                        while (indexEnumerator.MoveNext())
                        {
                            int index1 = indexEnumerator.Current;
                            int index2 = 0;
                            int index3 = 0;

                            if (indexEnumerator.MoveNext())
                            {
                                index2 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }
                            if (indexEnumerator.MoveNext())
                            {
                                index3 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }

                            tempSurface.AddTriangle(
                                (int)(actBaseIndex + index3),
                                (int)(actBaseIndex + index2),
                                (int)(actBaseIndex + index1));
                        }
                    }
                }
            }

            // Make volumetric outlines
            int triangleCountWithoutSide = tempSurface.CountTriangles;

            if (m_geometryOptions.MakeVolumetricText)
            {
                float volumetricTextDepth = m_geometryOptions.VolumetricTextDepth;
                if (m_geometryOptions.VerticesScaleFactor > 0f)
                {
                    volumetricTextDepth = volumetricTextDepth / m_geometryOptions.VerticesScaleFactor;
                }

                // Add all side surfaces
                foreach (Polygon2D actPolygon in geometryExtruder.GeneratedPolygons)
                {
                    foreach (Line2D actLine in actPolygon.Lines)
                    {
                        tempSurface.BuildRect4V(
                            new Vector3(actLine.StartPosition.X, -volumetricTextDepth, actLine.StartPosition.Y),
                            new Vector3(actLine.EndPosition.X, -volumetricTextDepth, actLine.EndPosition.Y),
                            new Vector3(actLine.EndPosition.X, 0f, actLine.EndPosition.Y),
                            new Vector3(actLine.StartPosition.X, 0f, actLine.StartPosition.Y),
                            m_geometryOptions.VolumetricSideSurfaceVertexColor);
                    }
                }
            }

            // Do also make back surface?
            if (m_geometryOptions.MakeBackSurface)
            {
                for (int loop = 0; loop < triangleCountWithoutSide; loop++)
                {
                    Triangle triangle     = tempSurface.Triangles[loop];
                    Vertex   vertex0      = tempStructure.Vertices[triangle.Index1];
                    Vertex   vertex1      = tempStructure.Vertices[triangle.Index2];
                    Vertex   vertex2      = tempStructure.Vertices[triangle.Index3];
                    Vector3  changeVector = new Vector3(0f, -m_geometryOptions.VolumetricTextDepth, 0f);

                    tempSurface.AddTriangle(
                        vertex2.Copy(vertex2.Position - changeVector, Vector3.Negate(vertex2.Normal)),
                        vertex1.Copy(vertex1.Position - changeVector, Vector3.Negate(vertex1.Normal)),
                        vertex0.Copy(vertex0.Position - changeVector, Vector3.Negate(vertex0.Normal)));
                }
            }

            // TODO: Make this configurable
            tempStructure.ToggleCoordinateSystem();

            // Scale the text using given scale factor
            if (m_geometryOptions.VerticesScaleFactor > 0f)
            {
                Matrix4x4 scaleMatrix = Matrix4x4.CreateScale(
                    m_geometryOptions.VerticesScaleFactor,
                    m_geometryOptions.VerticesScaleFactor,
                    m_geometryOptions.VerticesScaleFactor);

                Matrix4Stack transformMatrix = new Matrix4Stack(scaleMatrix);
                transformMatrix.TransformLocal(m_geometryOptions.VertexTransform);

                tempStructure.UpdateVerticesUsingRelocationFunc((actVector) => Vector3.Transform(actVector, transformMatrix.Top));
            }

            // Calculate all normals before adding to target structure
            if (m_geometryOptions.CalculateNormals)
            {
                tempStructure.CalculateNormalsFlat();
            }

            // Merge temporary structure to target structure
            m_targetSurface.AddStructure(tempStructure);

            return(SDX.Result.Ok);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// IDWriteTextLayout::Draw calls this function to instruct the client to render a run of glyphs.
        /// </summary>
        /// <param name="clientDrawingContext">The application-defined drawing context passed to  <see cref="M:Vortice.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" />.</param>
        /// <param name="baselineOriginX">The pixel location (X-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="baselineOriginY">The pixel location (Y-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="measuringMode">The measuring method for glyphs in the run, used with the other properties to determine the rendering mode.</param>
        /// <param name="glyphRun">Pointer to the glyph run instance to render.</param>
        /// <param name="glyphRunDescription">A pointer to the optional glyph run description instance which contains properties of the characters  associated with this run.</param>
        /// <param name="clientDrawingEffect">Application-defined drawing effects for the glyphs to render. Usually this argument represents effects such as the foreground brush filling the interior of text.</param>
        /// <returns>
        /// If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        /// <unmanaged>HRESULT DrawGlyphRun([None] void* clientDrawingContext,[None] FLOAT baselineOriginX,[None] FLOAT baselineOriginY,[None] DWRITE_MEASURING_MODE measuringMode,[In] const DWRITE_GLYPH_RUN* glyphRun,[In] const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,[None] IUnknown* clientDrawingEffect)</unmanaged>
        /// <remarks>
        /// The <see cref="M:Vortice.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" /> function calls this callback function with all the information about glyphs to render. The application implements this callback by mostly delegating the call to the underlying platform's graphics API such as {{Direct2D}} to draw glyphs on the drawing context. An application that uses GDI can implement this callback in terms of the <see cref="M:Vortice.DirectWrite.BitmapRenderTarget.DrawGlyphRun(System.Single,System.Single,SharpDX.Direct2D1.MeasuringMode,Vortice.DirectWrite.GlyphRun,Vortice.DirectWrite.RenderingParams,SharpDX.Color4)" /> method.
        /// </remarks>
        public override void DrawGlyphRun(
            IntPtr clientDrawingContext, float baselineOriginX, float baselineOriginY,
            MeasuringMode measuringMode, DWrite.GlyphRun glyphRun, DWrite.GlyphRunDescription glyphRunDescription, IUnknown clientDrawingEffect)
        {
            if (glyphRun.Indices == null ||
                glyphRun.Indices.Length == 0)
            {
                return;
            }

            GraphicsCore.EnsureGraphicsSupportLoaded();
            var d2DFactory = GraphicsCore.Current.FactoryD2D !;

            // Extrude geometry data out of given glyph run
            var geometryExtruder = new SimplePolygon2DGeometrySink(new Vector2(baselineOriginX, baselineOriginY));

            using (var pathGeometry = d2DFactory.CreatePathGeometry())
            {
                // Write all geometry data into a standard PathGeometry object
                using (var geoSink = pathGeometry.Open())
                {
                    glyphRun.FontFace !.GetGlyphRunOutline(
                        glyphRun.FontSize,
                        glyphRun.Indices,
                        glyphRun.Advances,
                        glyphRun.Offsets,
                        glyphRun.IsSideways,
                        glyphRun.BidiLevel % 2 == 1,
                        geoSink);
                    geoSink.Close();
                }

                // Simplify written geometry and write it into own structure
                pathGeometry.Simplify(D2D.GeometrySimplificationOption.Lines, _geometryOptions.SimplificationFlatternTolerance, geometryExtruder);
            }

            // Geometry for caching the result
            var tempGeometry = new Geometry();
            var tempSurface  = tempGeometry.CreateSurface();

            // Create the text surface
            if (_geometryOptions.MakeSurface)
            {
                // Separate polygons by clock direction
                // Order polygons as needed for further hole finding algorithm
                IEnumerable <Polygon2D> fillingPolygons = geometryExtruder.GeneratedPolygons
                                                          .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.CounterClockwise)
                                                          .OrderBy(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y);
                var holePolygons = geometryExtruder.GeneratedPolygons
                                   .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.Clockwise)
                                   .OrderByDescending(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y)
                                   .ToList();

                // Build geometry for all polygons
                foreach (var actFillingPolygon in fillingPolygons)
                {
                    // Find all corresponding holes
                    var actFillingPolygonBounds = actFillingPolygon.BoundingBox;
                    IEnumerable <Polygon2D> correspondingHoles = holePolygons
                                                                 .Where(actHolePolygon => actHolePolygon.BoundingBox.IsContainedBy(actFillingPolygonBounds))
                                                                 .ToList();

                    // Two steps here:
                    // - Merge current filling polygon and all its holes.
                    // - RemoveObject found holes from current hole list
                    var polygonForRendering     = actFillingPolygon;
                    var polygonForTriangulation = actFillingPolygon.Clone();
                    var cutPoints = new List <Vector2>();

                    foreach (var actHole in correspondingHoles)
                    {
                        holePolygons.Remove(actHole);
                        polygonForRendering     = polygonForRendering.MergeWithHole(actHole, Polygon2DMergeOptions.DEFAULT, cutPoints);
                        polygonForTriangulation = polygonForTriangulation.MergeWithHole(actHole, new Polygon2DMergeOptions {
                            MakeMergepointSpaceForTriangulation = true
                        });
                    }

                    var actBaseIndex = tempGeometry.CountVertices;

                    // Append all vertices to temporary Geometry
                    for (var loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                    {
                        // Calculate 3d location and texture coordinate
                        var actVertexLocation = new Vector3(
                            polygonForRendering.Vertices[loop].X,
                            0f,
                            polygonForRendering.Vertices[loop].Y);
                        var actTexCoord = new Vector2(
                            (polygonForRendering.Vertices[loop].X - polygonForRendering.BoundingBox.Location.X) / polygonForRendering.BoundingBox.Size.X,
                            (polygonForRendering.Vertices[loop].Y - polygonForRendering.BoundingBox.Location.Y) / polygonForRendering.BoundingBox.Size.Y);

                        if (float.IsInfinity(actTexCoord.X) || float.IsNaN(actTexCoord.X))
                        {
                            actTexCoord.X = 0f;
                        }

                        if (float.IsInfinity(actTexCoord.Y) || float.IsNaN(actTexCoord.Y))
                        {
                            actTexCoord.Y = 0f;
                        }

                        // Append the vertex to the result
                        tempGeometry.AddVertex(
                            new VertexBasic(
                                actVertexLocation,
                                _geometryOptions.SurfaceVertexColor,
                                actTexCoord,
                                new Vector3(0f, 1f, 0f)));
                    }

                    // Generate cubes on each vertex if requested
                    if (_geometryOptions.GenerateCubesOnVertices)
                    {
                        for (var loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                        {
                            var colorToUse      = Color4.GreenColor;
                            var pointRenderSize = 0.1f;

                            if (cutPoints.Contains(polygonForRendering.Vertices[loop]))
                            {
                                colorToUse      = Color4.RedColor;
                                pointRenderSize = 0.15f;
                            }

                            var actVertexLocation = new Vector3(
                                polygonForRendering.Vertices[loop].X,
                                0f,
                                polygonForRendering.Vertices[loop].Y);
                            tempSurface.BuildCube(actVertexLocation, pointRenderSize).SetVertexColor(colorToUse);
                        }
                    }

                    // Triangulate the polygon
                    var triangleIndices = polygonForTriangulation.TriangulateUsingCuttingEars();
                    if (triangleIndices == null)
                    {
                        continue;
                    }

                    // Append all triangles to the temporary geometry
                    using (var indexEnumerator = triangleIndices.GetEnumerator())
                    {
                        while (indexEnumerator.MoveNext())
                        {
                            var index1 = indexEnumerator.Current;
                            var index2 = 0;
                            var index3 = 0;

                            if (indexEnumerator.MoveNext())
                            {
                                index2 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }
                            if (indexEnumerator.MoveNext())
                            {
                                index3 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }

                            tempSurface.AddTriangle(
                                actBaseIndex + index3,
                                actBaseIndex + index2,
                                actBaseIndex + index1);
                        }
                    }
                }
            }

            // Make volumetric outlines
            var triangleCountWithoutSide = tempSurface.CountTriangles;

            if (_geometryOptions.MakeVolumetricText)
            {
                var volumetricTextDepth = _geometryOptions.VolumetricTextDepth;

                if (_geometryOptions.VerticesScaleFactor > 0f)
                {
                    volumetricTextDepth = volumetricTextDepth / _geometryOptions.VerticesScaleFactor;
                }

                // AddObject all side surfaces
                foreach (var actPolygon in geometryExtruder.GeneratedPolygons)
                {
                    foreach (var actLine in actPolygon.Lines)
                    {
                        tempSurface.BuildRect(
                            new Vector3(actLine.StartPosition.X, -volumetricTextDepth, actLine.StartPosition.Y),
                            new Vector3(actLine.EndPosition.X, -volumetricTextDepth, actLine.EndPosition.Y),
                            new Vector3(actLine.EndPosition.X, 0f, actLine.EndPosition.Y),
                            new Vector3(actLine.StartPosition.X, 0f, actLine.StartPosition.Y))
                        .SetVertexColor(_geometryOptions.VolumetricSideSurfaceVertexColor);
                    }
                }
            }

            // Do also make back surface?
            if (_geometryOptions.MakeBackSurface)
            {
                for (var loop = 0; loop < triangleCountWithoutSide; loop++)
                {
                    var triangle     = tempSurface.Triangles[loop];
                    var vertex0      = tempGeometry.Vertices[triangle.Index1];
                    var vertex1      = tempGeometry.Vertices[triangle.Index2];
                    var vertex2      = tempGeometry.Vertices[triangle.Index3];
                    var changeVector = new Vector3(0f, -_geometryOptions.VolumetricTextDepth, 0f);

                    tempSurface.AddTriangle(
                        vertex2.Copy(vertex2.Position - changeVector, Vector3.Negate(vertex2.Normal)),
                        vertex1.Copy(vertex1.Position - changeVector, Vector3.Negate(vertex1.Normal)),
                        vertex0.Copy(vertex0.Position - changeVector, Vector3.Negate(vertex0.Normal)));
                }
            }

            // Toggle coordinate system becomes text input comes in opposite direction
            tempGeometry.ToggleCoordinateSystem();

            // Scale the text using given scale factor
            if (_geometryOptions.VerticesScaleFactor > 0f)
            {
                var scaleMatrix = Matrix4x4.CreateScale(
                    _geometryOptions.VerticesScaleFactor,
                    _geometryOptions.VerticesScaleFactor,
                    _geometryOptions.VerticesScaleFactor);

                var transformMatrix = new Matrix4Stack(scaleMatrix);
                transformMatrix.TransformLocal(_geometryOptions.VertexTransform);

                tempGeometry.UpdateVerticesUsingTranslation(actVector => Vector3.Transform(actVector, transformMatrix.Top));
            }

            // Calculate all normals before adding to target geometry
            if (_geometryOptions.CalculateNormals)
            {
                tempGeometry.CalculateNormalsFlat();
            }

            // Merge temporary geometry to target geometry
            _targetSurface.AddGeometry(tempGeometry);
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SceneRelatedUpdateState"/> class.
 /// </summary>
 internal SceneRelatedUpdateState(Scene owner)
 {
     m_owner       = owner;
     m_world       = new Matrix4Stack(Matrix4x4.Identity);
     m_inputFrames = null;
 }