VectorGraphics Unity3d - get reference to imported SVG in code - unity3d

I am using Unity's Vector Graphics package to import a simple svg with 3 shapes.
Importing works successfully:
However, once imported - how do I get a reference to the svg - so that I can modify shapes and fills?
The documentation shows how to render (after making changes) but I don't understand how to first get the reference to the imported svg?
Even seeing some sample code that has been implemented would be enough but I can't find any online.

The way to do this would be to parse the SVG file to get a vector representation of the file (vector Scene), then you can change any properties before tessellation. For example:
string svg =
#"<svg xmlns=""http://www.w3.org/2000/svg"" xmlns:xlink=""http://www.w3.org/1999/xlink"" viewBox=""0 0 216 216"">
<g>
<polygon id=""Poly1"" points=""...""/>
</g>
</svg>";
// Import the SVG at runtime
var sceneInfo = SVGParser.ImportSVG(new StringReader(svg));
var shape = sceneInfo.NodeIDs["Poly1"].Shapes[0];
shape.Fill = new SolidFill() { Color = Color.red };
// Tessellate
var geoms = VectorUtils.TessellateScene(sceneInfo.Scene, tessOptions);
// Build a sprite
var sprite = VectorUtils.BuildSprite(geoms, 10.0f, VectorUtils.Alignment.Center, Vector2.zero, 128, true);
GetComponent<SpriteRenderer>().sprite = sprite;
See source answer

Related

Is there a way to import a texture in a specific format?

I'm trying to load a rendered image from Blender into Unity. But I saved the image with a color depth of 16 bits per channel, and now I want to have the same accuracy inside Unity. However, when I put the texture on a material and zoom in a bit, it looks like this:
As far as I can tell, this is only 8 bits per channel. What fixed it for me was overriding the format in the Texture Import Settings (from the default RGBA Compressed DXT5 to RGBA64, because my image also has an alpha channel):
And now the image looks nice again:
However, I would like to be able to import the image at runtime. So far I've been doing it like this:
Texture2D tex = new Texture2D(0, 0);
byte[] bytes = File.ReadAllBytes(path);
tex.LoadImage(bytes);
The problem is that, according to the documentation for Texture2D.LoadImage, "PNG files are loaded into ARGB32 format" by default. And even if I set the format when creating the Texture2D, it seems to get overitten when I call LoadImage ("After LoadImage, texture size and format might change").
Is there a way to import an image in a specific format (at runtime)? Thanks in advance
Subclass AssetPostprocessor:
public class MyPostProcessor : AssetPostprocessor {
public void OnPreprocessTexture() {
if (assetPath.Contains("SomeFileName")) {
TextureImporter textureImporter = (TextureImporter)assetImporter;
TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings();
settings.textureCompression = TextureImporterCompression.Uncompressed;
settings.format = TextureImporterFormat.RGBA64;
textureImporter.SetPlatformTextureSettings(settings);
}
}
}

Can you export sliced sprites (PNG images) in Unity?

So I have a Sprite 2d and UI in unity. (Png image) That contains many small images like buttons. So I slice them and I can use them individualy in unity. But the thing is that I want to export each of the png Images that I got while slicing them for another use. So can I do that? And have them as separate pngs?
And what I want is these Images:
To export them in my (lets say) desktop as individual pngs.
Thank you!
I had a need for this too, I ended up solving it with a simple editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ExportSubSprites : Editor {
[MenuItem("Assets/Export Sub-Sprites")]
public static void DoExportSubSprites() {
var folder = EditorUtility.OpenFolderPanel("Export subsprites into what folder?", "", "");
foreach (var obj in Selection.objects) {
var sprite = obj as Sprite;
if (sprite == null) continue;
var extracted = ExtractAndName(sprite);
SaveSubSprite(extracted, folder);
}
}
[MenuItem("Assets/Export Sub-Sprites", true)]
private static bool CanExportSubSprites()
{
return Selection.activeObject is Sprite;
}
// Since a sprite may exist anywhere on a tex2d, this will crop out the sprite's claimed region and return a new, cropped, tex2d.
private static Texture2D ExtractAndName(Sprite sprite) {
var output = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
var r = sprite.textureRect;
var pixels = sprite.texture.GetPixels((int)r.x, (int)r.y, (int)r.width, (int)r.height);
output.SetPixels(pixels);
output.Apply();
output.name = sprite.texture.name + " " + sprite.name;
return output;
}
private static void SaveSubSprite(Texture2D tex, string saveToDirectory) {
if (!System.IO.Directory.Exists(saveToDirectory)) System.IO.Directory.CreateDirectory(saveToDirectory);
System.IO.File.WriteAllBytes(System.IO.Path.Combine(saveToDirectory, tex.name + ".png"), tex.EncodeToPNG());
}
}
First, drop this into a script file named EditorSubSprites.cs and make sure that it resides in an Editor folder. If you have no editor folder you can simply create at /Assets/Editor/
To use, expand a texture asset's sprites, and select as many of the sprites as you wish to export. Right-click and select "Export SubSprites".
Use Photoshop, Crop it, a Lot of Cut and Paste is going to happen save as PNG.
Import it to unity inside the folder, i like your designs. Also Watch Brackeys Tutorial on Youtube, https://www.youtube.com/user/Brackeys , he save me from my school years.
(edit : i recommend Photoshop because its the only thing i know.)

render of low poly model tris showing very hard/marked in three.js compared to sketchfab/unit3d/Iray

I've edited this post with a clean edge flow model and maps you can access if that helps in getting feedback. I can replicate the hard marked edges issue for this case too:
I'm finding the rendering result in three.js shows very hard marked polygons of the low poly object, I'm comparing this to sketchfab , unity3d and Iray render results.
Here's a snapshot of the edge flow shown in maya : https://drive.google.com/open?id=1qNA4VoZf-rSyq3_MQdeZqdFC6BxsE3un
Here's what the model looks in maya's view panel (not subdivided): https://drive.google.com/open?id=1US-fv5-v2ygReqjRPgcsQSusrAXTxVG5
Here's a snapshot of the three.js render (marked in red box more noticeable)
https://drive.google.com/open?id=1K3CIBLvA7skVUPWL0qInLcFrK74DtriK
here sketchfabs without shadows/post-processing filters
https://drive.google.com/open?id=1rozZyBSU1HwPPk4EnKFyc7SVvFNXQBwz
here Iray render in substance painter:
https://drive.google.com/open?id=1cXJzw780-kWH0nANy5ekM0HjRKAdaVQ2
Here's Unity render: https://drive.google.com/open?id=1lLFLd8UT48OSvxJcp7arwygZZISsaHkS
Here is the fbx if you'd need to inspect mesh / edge flow: https://drive.google.com/open?id=1BwljZNKL3dWJSSca6WYlqSK7os1Hp4pT
I'm also adding the normal map as I thought the problem may relate to my three.js setup for this(?): https://drive.google.com/open?id=149r3n9JGnb9xEJkf9Eh7ELK2bM83bJX_
albedo map: https://drive.google.com/open?id=1rGgDUOKbbeE6mrAlTG_6C7b8LgqQ1DF0
I'm reusing envmap hdr example and hdr setting.
Can someone please share some thoughts on what I can try differently?
Thank you for your help, Sergio.
I tried the following:
I softened edges in maya.
I also tried the lines below separately and combined but there was not result.
//vaseMesh.geometry.mergeVertices(); and //vaseMesh.geometry.computeVertexNormals();
normalScale appears to be best at material.normalScale.x = -1;
I also tried but had same result without hdr or tonemapping settings as per displacement three.js example https://threejs.org/examples/?q=displ#webgl_materials_displacementmap
renderer = new THREE.WebGLRenderer();
renderer.toneMapping = THREE.LinearToneMapping;
//load vase material textures once loaded
manager.onLoad=function () {
material = new THREE.MeshStandardMaterial( {
color: 0xffffff,
roughness: params.roughness,
metalness: params.metalness,
map: albedoM,
normalMap: normalMap,
normalScale: new THREE.Vector2( 1, -1 ),
aoMap: aoMap,
aoMapIntensity: 1,
flatShading: true,
side: THREE.DoubleSide
} );
var myObjectLoader = new THREE.FBXLoader( );
myObjectLoader.load( "Piece1.fbx", function ( group ) {
console.log("On object loading");
var geometry = group.children[ 0 ].geometry;
geometry.attributes.uv2 = geometry.attributes.uv;
geometry.center();
vaseMesh = new THREE.Mesh( geometry, material );
vaseMesh.material=material;
//vaseMesh.geometry.mergeVertices();
//vaseMesh.geometry.computeVertexNormals();
material.normalScale.x = -1;
scene.add( vaseMesh );
console.log("Finished adding to scene");
vaseMesh.position.set(0,0,0);
animate();
} );
}
var textureLoader = new THREE.TextureLoader(manager);
var albedoM = textureLoader.load( "vaseTextures/albedo.png");
var normalMap = textureLoader.load( "vaseTextures/normal.png");
var aoMap = textureLoader.load( "vaseTextures/ao.png");
Giving credit to #Mugen87 for the answer, removing the setting flatShading to true did it!
https://discourse.threejs.org/t/render-of-low-poly-model-tris-showing-very-hard-marked-in-three-js-compared-to-sketchfab-unit3d-iray/6829/2?u=mugen87
Cheers, Sergio

remove graphics from inside a class as3

When I click a button in my game it draws shapes using the graphics in as3. simple shapes such as circles and rectangles.
I want to remove the graphics that have been drawn when something happens in one of my classes.
Basically when there is a hitTestObject (which works fine) I want all graphics on stage to be cleared.
if (gb2.hitTestObject(h1s2))
{
trace ("holed")
ySpeed2=0;
xSpeed2=0;
this.visible=false;
var mcSplash:MovieClip =parent.getChildByName("mcSplash") as MovieClip;
mcSplash.visible=true;
//parent.drawings.graphics.clear();
}
My attempt using parent.drawings.graphics.clear(); was unsuccessful, it gives me this error:
Line 481 1119: Access of possibly undefined property drawings through a reference with static type flash.display:DisplayObjectContainer.
Anyone have any suggestions
UPDATE:
this is how, on the min time line, the drawings occur.
var drawings:Shape = new Shape;
for (i=0; i<numRecs; i++)
{
recStartX = Number(xmlContent.rec[i].startpoint.#ptx);
recStartY = Number(xmlContent.rec[i].startpoint.#pty);
recWidth = Number(xmlContent.rec[i].dimensions.#w);
recHeight = Number(xmlContent.rec[i].dimensions.#h);
fillColor=int(xmlContent.rec[i].look.fillhex);
lineThick = Number(xmlContent.rec[i].look.strokethick);
lineColor = int(xmlContent.rec[i].look.strokehex);
drawings.graphics.lineStyle(lineThick, lineColor);
drawings.graphics.beginFill(fillColor);
drawings.graphics.drawRect(recStartX,recStartY,recWidth,recHeight);
drawings.graphics.endFill();
}
Create an array and push in each shape/rect.
Then iterate through this and remove..
for(var iteration:int = 0; iteration < rectArray.length; iteration++)
this.removeChild(rectArray[iteration]);
or if you are calling this from a class, use
MovieClip(this.root).removeChild(rectArray[iteration]);
Hopefully this is helpful :)
Z
What's drawings?! If you draw in mcSplash, you should use mcSplash.graphics.clear(). If you draw in a child called drawings, you should first get it as a child (after mcSplash get): var drawings = mcSplash.getChildByName('drawings); drawings.graphics.clear();. You could write checks to see what's going on: if (mcSlpash) { if (drawings) {, etc..

How to create a Away3d Infinite tiling floor?

I am trying to create a scene with a infinite floor that seems to fade away in the distance in Away3d. I want the floor to have a texture. Prob is -- I can't seem to find any clear examples or tutorials that demonstrate this.
Ok you need to set your scene up, import local libs etc here we go
//Away3d
import away3d.containers.Scene3D;
import away3d.containers.View3D;
//etc
////////3D ModelScenes, Textures CLASS Exported 3DS/////////////////////
[Embed("assets/Images/grass1.jpg")]
var GrassTexture:Class;
var groundMaterial = new BitmapTexture(new GrassTexture().bitmapData);
////////GROUND MESH/////////////////////////////////////////////////////
var plane = new Mesh(new PlaneGeometry(3000,3000,30,30),new TextureMaterial(Cast.bitmapTexture(groundMaterial)));
plane.geometry.scaleUV(25, 25);
plane.material.repeat = true;
plane.material.alpha = 1;
container.addChild(plane);
Instead of tiling mesh/planes your better off having a really big plane and using the vertexes/polygons as tile locations...
Hope it helps