示例#1
0
        private void Render(GeometryModel3D model)
        {
            if (model.Geometry is MeshGeometry3D)
            {
                // Project geometry into a list of triangles
                ProjectedGeometry pg = MeshToProjectedGeometry((MeshGeometry3D)model.Geometry, model.Transform);

                // Remember the view matrix for view space lighting
                Matrix3D view = MatrixUtils.ViewMatrix(camera);

                // Render back faces
                RenderGeometry(pg, view, model.BackMaterial, VisibleFaces.Back);

                // Render front faces
                RenderGeometry(pg, view, model.Material, VisibleFaces.Front);
            }
            else if (model.Geometry == null)
            {
                // do nothing
            }
            else
            {
                throw new NotSupportedException("I cannot render Geometry3D of type: " + model.Geometry.GetType());
            }
        }
示例#2
0
        private void Render(ScreenSpaceLines3D lines)
        {
            ProjectedGeometry geometry = MagicLinesToProjectedGeometry(lines, lines.Transform);
            Shader            shader   = new ScreenSpaceLinesShader(geometry.FrontFaceTriangles, buffer);

            shader.Rasterize(bounds.RenderBounds);

            // SSL are always front facing ( CCW winding ) triangles
            RenderSilhouetteTolerance(geometry, buffer, VisibleFaces.Front);
        }
示例#3
0
        private void RenderGeometry(ProjectedGeometry pg, Matrix3D view, Material material, VisibleFaces faces)
        {
            if (material == null)
            {
                return;
            }

            Triangle[] triangles = null;

            // Choose list based on triangle winding/facing
            switch (faces)
            {
            case VisibleFaces.Front:
                triangles = pg.FrontFaceTriangles;
                break;

            case VisibleFaces.Back:
                triangles = pg.BackFaceTriangles;
                break;

            default:
                throw new NotSupportedException("Cannot render these type of faces: " + faces.ToString());
            }

            // We should only look into materials if we have any geometry to render.
            // Doing otherwise will throw exceptions when trying to use screen-space
            // bounds or UV coordinates.
            if (triangles.Length > 0)
            {
                // Create a flat, ordered list of textures to apply to this model
                List <Material> materials = ExtractMaterials(material);

                // Create a list of textures from the materials
                TextureFilter[] textures = TextureFilter.CreateTextures(
                    materials, pg.OriginalMinUV, pg.OriginalMaxUV, Rect.Intersect(bounds.RenderBounds, pg.ScreenSpaceBounds));

                // Use a precomputed light shader
                Shader shader = null;
                if (interpolation == InterpolationMode.Phong)
                {
                    shader = new PrecomputedPhongShader(triangles, buffer, lights, textures, view);
                }
                else
                {
                    shader = new PrecomputedGouraudShader(triangles, buffer, lights, textures, view);
                }
                shader.Rasterize(bounds.RenderBounds);
                RenderSilhouetteTolerance(pg, buffer, faces);
            }
        }
示例#4
0
        private void RenderSilhouetteTolerance(ProjectedGeometry geometry, RenderBuffer rasterization, VisibleFaces faces)
        {
            List <Edge> silhouetteEdges = null;

            // Choose list based on triangle winding/facing
            switch (faces)
            {
            case VisibleFaces.Front:
                silhouetteEdges = geometry.FrontFaceSilhouetteEdges;
                break;

            case VisibleFaces.Back:
                silhouetteEdges = geometry.BackFaceSilhouetteEdges;
                break;

            default:
                throw new NotSupportedException("Cannot render these type of faces: " + faces);
            }

            // Outline edge detection
            if (RenderTolerance.SilhouetteEdgeTolerance > 0)
            {
                // Create a set of triangles that will draw lines on the tolerance buffer
                SilhouetteEdgeTriangle[] edgeTriangles = new SilhouetteEdgeTriangle[2 * silhouetteEdges.Count];
                int count = 0;

                //double the silhouette pixel tolerance in nonstandard DPI scenario.
                //This compensates for differences in anti-aliasing sampling patterns in high and low DPI
                double tolerance = RenderTolerance.SilhouetteEdgeTolerance;
                if (!RenderTolerance.IsSquare96Dpi)
                {
                    tolerance *= 4;
                }

                foreach (Edge edge in silhouetteEdges)
                {
                    // FWD triangle
                    edgeTriangles[count++] = new SilhouetteEdgeTriangle(edge.Start, edge.End, tolerance);

                    // BWD triangle
                    edgeTriangles[count++] = new SilhouetteEdgeTriangle(edge.End, edge.Start, tolerance);
                }

                // Render our ignore geometry onto the tolerance buffer.
                RenderToToleranceShader edgeIgnore = new RenderToToleranceShader(edgeTriangles, rasterization);
                edgeIgnore.Rasterize(bounds.RenderBounds);
            }
        }
示例#5
0
        internal MeshGeometry3D ExtractTrianglesAtPoints(
            MeshGeometry3D mesh,
            Transform3D tx,
            Point[] selectionPoints)
        {
            ProjectedGeometry pg         = MeshToProjectedGeometry(mesh, tx);
            MeshGeometry3D    outputMesh = new MeshGeometry3D();

            foreach (Triangle t in pg.FrontFaceTriangles)
            {
                foreach (Point p in selectionPoints)
                {
                    if (t.Bounds.Contains(p.X + pixelCenterX, p.Y + pixelCenterY) &&
                        t.Contains(p.X + pixelCenterX, p.Y + pixelCenterY))
                    {
                        t.SaveToMesh(outputMesh);
                        // saving the triangle once is enough
                        break;
                    }
                }
            }
            foreach (Triangle t in pg.BackFaceTriangles)
            {
                foreach (Point p in selectionPoints)
                {
                    if (t.Bounds.Contains(p.X + pixelCenterX, p.Y + pixelCenterY) &&
                        t.Contains(p.X + pixelCenterX, p.Y + pixelCenterY))
                    {
                        // Back facing ... flip normals
                        t.vertex1.Normal *= -1;
                        t.vertex2.Normal *= -1;
                        t.vertex3.Normal *= -1;
                        t.SaveToMesh(outputMesh);
                        // saving the triangle once is enough
                        break;
                    }
                }
            }
            return(outputMesh);
        }