Skip to content

Commit

Permalink
Updated documentation. Using vector graphics 1.0.0-preview.7.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcoted committed Apr 30, 2018
1 parent 7787f36 commit 3ecfe93
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 89 deletions.
173 changes: 86 additions & 87 deletions Documentation/vectorgraphics.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,109 +20,109 @@ The SVG importer from this package implements a subset of the SVG 1.1 specificat

# Using Vector Graphics

## SVG Importer
## SVG importer

This package provides an SVG importer that reads and interprets SVG documents and generates 2D sprites to be used by the Unity engine.
This package provides an SVG importer that reads and interprets SVG documents and generates 2D sprites for use in Unity.

You import SVG files like any other assets. You either drop them directly into the Assets Browser, or you use the `Assets > Import New Asset...` menu item. Once imported, you can instantiate the resulting assets in the Hierarchy View or the Scene View.
You import SVG files like any other assets. Either drop them directly into the Assets Browser, or select `Assets > Import New Asset` in the Editor. When imported, you can instantiate the resulting assets in the Hierarchy View or the Scene View.

The SVG importer has the following properties:

![SVG importer properties](images/svg_inspector.png)

**Pixels Per Unit**: How many SVG units correspond to 1 scene unit.
**Pixels Per Unit**: Number of SVG units that correspond to 1 scene unit.

**Tessellation Step Distance**: At which distance are triangles generated when tessellating the paths. A smaller step distance will result in smoother curves at the expense of more triangles.
**Tessellation Step Distance**: Distance at which Unity generates triangles when tessellating the paths. A smaller step distance results in smoother curves at the expense of more triangles.

**Gradient Resolution**: The texture size used to store gradients.
**Gradient Resolution**: Texture size used to store gradients.

**Pivot**: The location of the pivot for the generated sprite. This follows the same convention as regular sprites, with an additional "SVG Origin" pivot value. When using "SVG Origin", the pivot will be the (0,0) position of the SVG document.
**Pivot**: Location of the pivot for the generated sprite. This follows the same convention as regular sprites, with an additional **SVG Origin** pivot value. When using **SVG Origin**, the pivot will be the (0,0) position of the SVG document.

The tessellation settings can be provided in two ways: **Basic** or **Advanced**. When using **Basic**, you only need to provide a **Target Resolution** and a **Zoom Factor**. The importer will automatically configure the advanced settings to make sure your SVG document will render at a high enough tessellation for that resolution at that zoom factor.
You can provide tessellation settings in two ways: **Basic** or **Advanced**. When using **Basic**, you only need to provide a **Target Resolution** and a **Zoom Factor**. The importer then automatically configures the advanced settings to make sure your SVG document renders at a high enough tessellation for that resolution at that zoom factor.

![SVG importer advanced properties](images/svg_inspector_advanced.png)

<a name="advanced-importer-settings"></a>If you want full control over the tessellation of the SVG document, you can specify the following advanced settings:

**Step Distance**: Distance at which vertices will be generated along the paths. Lower values will result in a more dense tesselation.
**Step Distance**: Distance at which the importer generates vertices along the paths. Lower values result in a more dense tessellation.

**Sampling Steps**: Number of samples evaluated on paths. More samples may lead to more precise curves, especially when they have sharp corners.
**Sampling Steps**: Number of samples evaluated on paths. More samples may lead to more precise curves, especially when they have sharp corners.

**Max Cord Deviation**: When enabled, specifies the distance on the cord to a straight line between two points after which more tesselation will be generated.
**Max Cord Deviation**: When enabled, specifies the distance on the cord to a straight line between two points after which the importer generates more tessellation.

**Max Tangent Angle**: When enabled, specifies the max tangent angle (in degrees) after which more tesselation will be generated.
**Max Tangent Angle**: When enabled, specifies the max tangent angle (in degrees) after which the importer generates more tessellation.

![Max Cord](images/constraints.png)

The curves will subdivide for as long as every enabled constraints aren't satisfied.
The curves will subdivide for as long as every enabled constraint isn't satisfied.

The **Sprite Editor** is also available and works exactly the same way as regular sprite assets.
The **Sprite Editor** is also available and works in exactly the same way as when using regular sprite assets.

## Vector Graphics API

Classes and methods are provided to work with vector data directly in code. The SVG importer internally uses these APIs to generate and tessellate the resulting sprites. The same APIs are available to users.
The provided Vector Graphics API classes and methods enable you to work with vector data directly in code. The SVG importer uses these APIs internally to generate and tessellate the resulting sprites.

The whole API is designed as a set of simple classes and structures that holds the vector data together. This is accompanied by static methods to manipulate and transform this data.
The whole API is designed as a set of simple classes and structures that holds the vector data together. This is accompanied by static methods which manipulate and transform this data.

At the core of the Vector Graphics package lives the `Scene` class, which stores a graph of vector objects. Its `root` property is an instance of `SceneNode`, which contains a list of drawable items, a list of child nodes, a transform and a clipper (see [clipping](#clipping)).
At the core of the Vector Graphics package lives the `Scene` class, which stores a graph of vector objects. Its `Root` property is an instance of `SceneNode`, which contains a list of drawable items, a list of child nodes, a transform and a clipper (see [clipping](#clipping)).

```
public class SceneNode
{
public List<SceneNode> children { get; set; }
public List<IDrawable> drawables { get; set; }
public Matrix2D transform { get; set; }
public SceneNode clipper { get; set; }
public List<SceneNode> Children { get; set; }
public List<IDrawable> Drawables { get; set; }
public Matrix2D Transform { get; set; }
public SceneNode Clipper { get; set; }
}
```

There are two main kind of drawable instances: paths and shapes.

### Paths

Paths are drawables that are defined by a `BezierContour`, which contains an array of `BezierPathSegment` and a flag that tells if the contour is closed or not.
Paths are drawables that are defined by a `BezierContour`, which contains an array of `BezierPathSegment` and a flag that indicates whether the contour is closed or not.

```
public class Path : IDrawable
{
public BezierContour contour { get; set; }
public PathProperties pathProps { get; set; }
public BezierContour Contour { get; set; }
public PathProperties PathProps { get; set; }
}
public struct BezierContour
{
public BezierPathSegment[] segments { get; set; }
public bool closed { get; set; }
public BezierPathSegment[] Segments { get; set; }
public bool Closed { get; set; }
}
public struct BezierPathSegment
{
public Vector2 p0;
public Vector2 p1;
public Vector2 p2;
public Vector2 P0;
public Vector2 P1;
public Vector2 P2;
}
```

The `BezierPathSegment` is used to define a chain of cubic Bézier curves. For a given segment, only the first point `p0` and the two control points `p1` and `p2` are specified. The `p0` value of the next segment in the array is used to complete the curve. So, you will always need at least two segments to define a valid `BezierContour. Using this approach allows the chaining of multiple segments and guarantees the continuity of the curve. For example, consider this path:
The `BezierPathSegment` defines a chain of cubic Bézier curves. For a given segment, only the first point `P0` and the two control points `P1` and `P2` are specified. The `P0` value of the next segment in the array completes the curve. So, you will always need at least two segments to define a valid `BezierContour`. Using this approach allows the chaining of multiple segments and guarantees the continuity of the curve. For example, consider this path:

![Contour](images/contour.png)

This path could be constructed like so:
You could construct this path like so:

```
var s = new BezierPathSegment[] {
new BezierPathSegment() { p0 = a, p1 = b, p2 = c },
new BezierPathSegment() { p0 = d, p1 = e, p2 = f },
new BezierPathSegment() { p0 = g }
new BezierPathSegment() { P0 = a, P1 = b, P2 = c },
new BezierPathSegment() { P0 = d, P1 = e, P2 = f },
new BezierPathSegment() { P0 = g }
};
var path = new Path() {
contour = new BezierContour() {
segments = s,
closed = false
Contour = new BezierContour() {
Segments = s,
Closed = false
},
pathProps = new PathProperties() {
stroke = new Stroke() { color = Color.red, halfThickness = 1.0f }
PathProps = new PathProperties() {
Stroke = new Stroke() { Color = Color.red, HalfThickness = 1.0f }
}
};
```
Expand All @@ -134,69 +134,69 @@ Just like paths, shapes are defined by a `BezierContour`, but they also provide
```
public class Shape : Filled
{
public BezierContour[] contours { get; set; }
public BezierContour[] Contours { get; set; }
}
public abstract class Filled : IDrawable
{
public IFill fill { get; set; }
public Matrix2D fillTransform { get; set; }
public PathProperties pathProps { get; set; }
public IFill Fill { get; set; }
public Matrix2D FillTransform { get; set; }
public PathProperties PathProps { get; set; }
}
```

There are several classes that implements the `IFill` interface:
There are several classes that implement the `IFill` interface:

* `SolidFill` for a simple colored fillings
* `TextureFill` for a texture fillings
* `SolidFill` for a simple colored filling
* `TextureFill` for a texture filling
* `GradientFill` for linear or radial gradient fillings


**Gradients**

Gradient fills are defined by a type (`Linear` or `Radial`) and a series of colors/percentage pairs, called `stops`:
Gradient fills are defined by a `Linear` or `Radial` type, and a series of colors/percentage pairs called `stops`:

```
public class GradientFill : IFill
{
public GradientFillType type { get; set; }
public GradientStop[] stops { get; set; }
public FillMode mode { get; set; }
public AddressMode addressing { get; set; }
public Vector2 radialFocus { get; set; }
public GradientFillType Type { get; set; }
public GradientStop[] Stops { get; set; }
public FillMode Mode { get; set; }
public AddressMode Addressing { get; set; }
public Vector2 RadialFocus { get; set; }
}
public struct GradientStop
{
public Color color { get; set; }
public float stopPercentage { get; set; }
public Color Color { get; set; }
public float StopPercentage { get; set; }
}
```

Consider the following linear fill, as well as the `GradientFill` instance to generate it:
Consider the following linear fill, and the `GradientFill` instance to generate it:

![Linear Fill](images/linear_gradient.png)

```
var fill = new GradientFill() {
type = GradientFillType.Linear,
stops = new GradientFillStop[] {
new GradientFillStop() { color = Color.blue, stopPercentage = 0.0f },
new GradientFillStop() { color = Color.red, stopPercentage = 0.5f },
new GradientFillStop() { color = Color.yellow, stopPercentage = 1.0f }
Type = GradientFillType.Linear,
Stops = new GradientFillStop[] {
new GradientFillStop() { Color = Color.blue, StopPercentage = 0.0f },
new GradientFillStop() { Color = Color.red, StopPercentage = 0.5f },
new GradientFillStop() { Color = Color.yellow, StopPercentage = 1.0f }
}
};
```

The gradient addressing modes define how the colors will be chosen when the gradient coordinates fall outside of the range, as illustrated here:
The gradient addressing modes define how Unity displays the gradient when the gradient coordinates fall outside of the range, as illustrated here:

![Addressing Modes](images/addressing.png)

**Fill Mode**

The filling classes also provide a fill mode, which determines how holes are defined inside the shapes.

`FillMode.NonZero` determines which points are inside shape by intersecting the contour segments with an horizontal line. The direction of the contour determines if the points are inside or outside the shape:
`FillMode.NonZero` determines which points are inside the shape by intersecting the contour segments with an horizontal line. The direction of the contour determines whether the points are inside or outside the shape:

![NonZero Fill](images/fill_nonzero.png)

Expand All @@ -206,60 +206,59 @@ The filling classes also provide a fill mode, which determines how holes are def

### <a name="clipping"></a> Clipping

The `SceneNode` class has a `clipper` member which will clip the content of the node.
The `SceneNode` class has a `Clipper` member which clips the content of the node.

![Clipper](images/clipper.png)

In the above example, the repeating square shapes are clipped by an ellipse. In code, this can be done like so:
In the above example, the repeating square shapes are clipped by an ellipse. You can do this in code, like this:

```
var ellipse = new SceneNode() {
drawables = new List<IDrawable> { VectorUtils.MakeEllipse(ellipse, Vector2.zero, 50, 100) }
Drawables = new List<IDrawable> { VectorUtils.MakeEllipse(ellipse, Vector2.zero, 50, 100) }
};
var squaresPattern = ...;
var squaresClipped = new SceneNode() {
children = new List<SceneNode> { squaresPattern },
clipper = ellipse
Children = new List<SceneNode> { squaresPattern },
Clipper = ellipse
};
```

Note that only shapes can act as a clipper (any strokes defined in the clipper will be ignored). The content being clipped can be any shapes and/or strokes.
Note that only shapes can act as a clipper (the clipping process ignores any strokes defined in the clipper). The content being clipped can be any shapes and/or strokes.

*Warning: The clipping process may be an expensive operation. Clipping simple shapes with a simple clipper may perform reasonably, but any complex shape and/or clipper may cause the framerate to drop significantly.*
*Warning: The clipping process may be an expensive operation. Clipping simple shapes with a simple clipper may perform reasonably, but any complex shape and/or clipper may cause the frame rate to drop significantly.*

### Vector Graphics Rendering
### Vector graphics rendering

The vector graphics elements can be rendered on screen by first getting a tessellated (triangulated) version of the scene. Once you have a `VectorScene` instance in hand, you can tessellate it using the following `VectorUtils` method:
To render vector graphics elements on screen, first get a tessellated (triangulated) version of the scene. When you have a `VectorScene` instance in hand, you can tessellate it using the following `VectorUtils` method:

```
public static List<Geometry> TessellateScene(Scene scene, TesselationOptions options);
```

The `TesselationOptions` are reminiscent of the [advanced importer settings](#advanced-importer-settings) discussed earlier:
The `TesselationOptions` are similar to the [advanced importer settings](#advanced-importer-settings):

```
public struct TesselationOptions
{
public float stepDistance { get; set; }
public float maxCordDeviation { get; set; }
public float maxTanAngleDeviation { get; set; }
public float samplingStepSize { get; set; }
public float StepDistance { get; set; }
public float MaxCordDeviation { get; set; }
public float MaxTanAngleDeviation { get; set; }
public float SamplingStepSize { get; set; }
}
```

Note that `maxTanAngleDeviation` is specified in radians.
Note that `MaxTanAngleDeviation` is specified in radians.

To disable the `maxCordDeviation` constraint, set it to `float.MaxValue`. To disable the `maxTanAngleDeviation` constraint, set it to `Mathf.PI/2.0f`. Disabling the constraints will make the tessellation faster, but may generate more vertices.
To disable the `MaxCordDeviation` constraint, set it to `float.MaxValue`. To disable the `MaxTanAngleDeviation` constraint, set it to `Mathf.PI/2.0f`. Disabling the constraints makes the tessellation faster, but may generate more vertices.

The resulting list of `Geometry` objects contains all the vertices and accompanying information required to render the scene properly.

#### Texture and gradient atlases

#### Textures and gradients atlases

If the scene has any texture and/or gradients, you will have to generate a texture atlas and fill the UVs of the geometry. These methods are part of the `VectorUtils` class:
If the scene has any textures and/or gradients, you need to generate a texture atlas and fill the UVs of the geometry. These methods are part of the `VectorUtils` class:

```
public static TextureAtlas GenerateAtlas(
Expand All @@ -272,9 +271,9 @@ public static void FillUVs(
TextureAtlas texAtlas); // The texture atlas generated by the GenerateAtlas method
```

The `GenerateAtlas` method is an expensive operation. Therefore, the resulting `Texture2D` object should be cached whenever possible. You only need to regenerate the atlas if any texture and/or gradient changed inside the scene.
The `GenerateAtlas` method is an expensive operation, so cache the resulting `Texture2D` object whenever possible. You only need to regenerate the atlas if any texture and/or gradient changes inside the scene.

The `FillUVs` method is cheap, and should be called if the vertices changed inside the geometry.
The `FillUVs` method is cheap, and you should call it if vertices change inside the geometry.

#### Drawing a tessellated scene

Expand All @@ -296,7 +295,7 @@ Otherwise, you can use:
var mat = new Material(Shader.Find("Unlit/Vector"));
```

Filling a mesh asset can be done by the following `VectorUtils` method:
To fill a mesh asset, use the following `VectorUtils` method:

```
public static void FillMesh(
Expand All @@ -306,7 +305,7 @@ public static void FillMesh(
bool flipYAxis = false); // If true, the Y-axis will point downward
```

Building a sprite asset can be done by the following `VectorUtils` method:
To build a sprite asset, use the following `VectorUtils` method:

```
public static Sprite BuildSprite(
Expand All @@ -317,7 +316,7 @@ public static Sprite BuildSprite(
UInt16 gradientResolution); // The resolution used for the gradient texture
```

You can render a sprite to a `Texture2D` by using the following `VectorUtils` method:
To render a sprite to a `Texture2D`, use the following `VectorUtils` method:

```
public static Texture2D RenderSpriteToTexture2D(
Expand All @@ -327,7 +326,7 @@ public static Texture2D RenderSpriteToTexture2D(
int antiAliasing = 1); // The number of samples per pixel
```

We also provide a method to render the generated sprite using immediate mode `GL` commands. The vertex coordinates to draw in a unit square (between 0 and 1 in both X and Y directions). This is in the `VectorUtils` class:
To render the generated sprite using immediate mode `GL` commands, use the `RenderSprite` method in the `VectorUtils` class to draw the sprite into a unit square (a box between 0 and 1 in both X and Y directions):

```
public static void RenderSprite(
Expand Down
2 changes: 1 addition & 1 deletion Packages/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"dependencies": {
"com.unity.vectorgraphics": "1.0.0-preview.6"
"com.unity.vectorgraphics": "1.0.0-preview.7"
},
"registry": "https://staging-packages.unity.com"
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ If you want to activate these features in another project:
```javascript
{
"dependencies": {
"com.unity.vectorgraphics": "1.0.0-preview.6"
"com.unity.vectorgraphics": "1.0.0-preview.7"
},
"registry": "https://staging-packages.unity.com"
}
Expand Down

0 comments on commit 3ecfe93

Please sign in to comment.