1
This commit is contained in:
@@ -0,0 +1,422 @@
|
||||
#if GRIFFIN
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pinwheel.Griffin.BillboardTool
|
||||
{
|
||||
public static class GBillboardCreator
|
||||
{
|
||||
private static MaterialPropertyBlock materialProperties;
|
||||
private static MaterialPropertyBlock MaterialProperties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (materialProperties == null)
|
||||
materialProperties = new MaterialPropertyBlock();
|
||||
return materialProperties;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PrepareRenderTexture(ref RenderTexture rt, GBillboardCreatorArgs args)
|
||||
{
|
||||
int width = args.Column * args.CellSize;
|
||||
int height = args.Row * args.CellSize;
|
||||
if (args.Mode == GBillboardRenderMode.Flipbook)
|
||||
{
|
||||
width = args.CellSize;
|
||||
height = args.CellSize;
|
||||
}
|
||||
|
||||
int depth = 16;
|
||||
RenderTextureFormat format = args.Mode == GBillboardRenderMode.Normal ? RenderTextureFormat.ARGBFloat : RenderTextureFormat.ARGB32;
|
||||
if (rt == null ||
|
||||
rt.width != width ||
|
||||
rt.height != height ||
|
||||
rt.depth != depth ||
|
||||
rt.format != format)
|
||||
{
|
||||
if (rt != null)
|
||||
{
|
||||
rt.Release();
|
||||
}
|
||||
rt = new RenderTexture(width, height, depth, format, RenderTextureReadWrite.Linear);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderPreview(RenderTexture rt, GBillboardCreatorArgs args)
|
||||
{
|
||||
if (args.Mode == GBillboardRenderMode.Atlas)
|
||||
RenderPreviewAtlas(rt, args);
|
||||
else if (args.Mode == GBillboardRenderMode.Normal)
|
||||
RenderPreviewNormal(rt, args);
|
||||
else if (args.Mode == GBillboardRenderMode.Flipbook)
|
||||
RenderPreviewFlipbook(rt, args);
|
||||
}
|
||||
|
||||
private static void RenderPreviewAtlas(RenderTexture rt, GBillboardCreatorArgs args)
|
||||
{
|
||||
Clear(rt, Color.clear);
|
||||
|
||||
if (args.AtlasMaterial == null)
|
||||
return;
|
||||
args.Mode = GBillboardRenderMode.Atlas;
|
||||
|
||||
Vector2 viewPortSize = new Vector2(1f / args.Column, 1f / args.Row);
|
||||
Vector2 viewPortPosition = new Vector2(0, 0);
|
||||
RenderTexture tempRt = new RenderTexture(Mathf.RoundToInt(viewPortSize.x * rt.width), Mathf.RoundToInt(viewPortSize.y * rt.height), 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
Camera cam = CreatePreviewCamera(args);
|
||||
cam.targetTexture = tempRt;
|
||||
GameObject g = CreatePreviewGameObject(cam.transform, args);
|
||||
|
||||
int imageCount = args.Row * args.Column;
|
||||
float angleStep = 360f / imageCount;
|
||||
|
||||
for (int y = 0; y < args.Row; ++y)
|
||||
{
|
||||
for (int x = 0; x < args.Column; ++x)
|
||||
{
|
||||
Clear(tempRt, Color.clear);
|
||||
g.transform.rotation = Quaternion.Euler(0, GUtilities.To1DIndex(x, y, args.Column) * angleStep - 90, 0);
|
||||
cam.Render();
|
||||
|
||||
viewPortPosition = new Vector2(x * viewPortSize.x, y * viewPortSize.y);
|
||||
GCommon.DrawTexture(rt, tempRt, new Rect(viewPortPosition, viewPortSize), GInternalMaterials.UnlitTransparentMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
cam.targetTexture = null;
|
||||
GUtilities.DestroyGameobject(cam.gameObject);
|
||||
GUtilities.DestroyGameobject(g);
|
||||
tempRt.Release();
|
||||
GUtilities.DestroyObject(tempRt);
|
||||
}
|
||||
|
||||
private static void RenderPreviewNormal(RenderTexture rt, GBillboardCreatorArgs args)
|
||||
{
|
||||
Clear(rt, new Color(0.5f, 0.5f, 1f, 1f));
|
||||
|
||||
if (args.NormalMaterial == null)
|
||||
return;
|
||||
args.Mode = GBillboardRenderMode.Normal;
|
||||
|
||||
Vector2 viewPortSize = new Vector2(1f / args.Column, 1f / args.Row);
|
||||
Vector2 viewPortPosition = new Vector2(0, 0);
|
||||
RenderTexture tempRt = new RenderTexture(Mathf.RoundToInt(viewPortSize.x * rt.width), Mathf.RoundToInt(viewPortSize.y * rt.height), 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
Camera cam = CreatePreviewCamera(args);
|
||||
cam.targetTexture = tempRt;
|
||||
GameObject g = CreatePreviewGameObject(cam.transform, args);
|
||||
|
||||
int imageCount = args.Row * args.Column;
|
||||
float angleStep = 360f / imageCount;
|
||||
|
||||
for (int y = 0; y < args.Row; ++y)
|
||||
{
|
||||
for (int x = 0; x < args.Column; ++x)
|
||||
{
|
||||
Clear(tempRt, new Color(0.5f, 0.5f, 1f, 1f));
|
||||
g.transform.rotation = Quaternion.Euler(0, GUtilities.To1DIndex(x, y, args.Column) * angleStep, 0);
|
||||
cam.Render();
|
||||
|
||||
viewPortPosition = new Vector2(x * viewPortSize.x, y * viewPortSize.y);
|
||||
GCommon.DrawTexture(rt, tempRt, new Rect(viewPortPosition, viewPortSize), GInternalMaterials.UnlitTransparentMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
cam.targetTexture = null;
|
||||
GUtilities.DestroyGameobject(cam.gameObject);
|
||||
GUtilities.DestroyGameobject(g);
|
||||
tempRt.Release();
|
||||
GUtilities.DestroyObject(tempRt);
|
||||
}
|
||||
|
||||
private static void RenderPreviewFlipbook(RenderTexture rt, GBillboardCreatorArgs args)
|
||||
{
|
||||
Clear(rt, Color.clear);
|
||||
|
||||
if (args.AtlasMaterial == null)
|
||||
return;
|
||||
args.Mode = GBillboardRenderMode.Flipbook;
|
||||
|
||||
Camera cam = CreatePreviewCamera(args);
|
||||
cam.targetTexture = rt;
|
||||
GameObject g = CreatePreviewGameObject(cam.transform, args);
|
||||
|
||||
int imageCount = args.Row * args.Column;
|
||||
float angleStep = 360f / imageCount;
|
||||
|
||||
g.transform.rotation = Quaternion.Euler(0, args.CellIndex * angleStep, 0);
|
||||
cam.rect = new Rect(0, 0, 1, 1);
|
||||
cam.Render();
|
||||
|
||||
cam.targetTexture = null;
|
||||
GUtilities.DestroyGameobject(cam.gameObject);
|
||||
GUtilities.DestroyGameobject(g);
|
||||
}
|
||||
|
||||
private static Camera CreatePreviewCamera(GBillboardCreatorArgs args)
|
||||
{
|
||||
GameObject previewCam = new GameObject("~BillboardEditorCam");
|
||||
//previewCam.hideFlags = HideFlags.HideAndDontSave;
|
||||
previewCam.transform.position = -Vector3.one * 10000;
|
||||
previewCam.transform.rotation = Quaternion.identity;
|
||||
previewCam.transform.localScale = Vector3.one;
|
||||
|
||||
Camera cam = previewCam.AddComponent<Camera>();
|
||||
cam.orthographic = true;
|
||||
cam.orthographicSize = args.CameraSize;
|
||||
cam.clearFlags = CameraClearFlags.SolidColor;
|
||||
cam.backgroundColor = args.Mode == GBillboardRenderMode.Normal ? new Color(0.5f, 0.5f, 1f, 1f) : Color.clear;
|
||||
cam.depth = -1000;
|
||||
cam.aspect = 1;
|
||||
cam.farClipPlane = 2 * Mathf.Abs(args.CameraOffset.z);
|
||||
cam.enabled = false;
|
||||
return cam;
|
||||
}
|
||||
|
||||
private static GameObject CreatePreviewGameObject(Transform cameraTransform, GBillboardCreatorArgs args)
|
||||
{
|
||||
if (args.Target == null)
|
||||
{
|
||||
return new GameObject("~EmptyBillboardCreatorTarget");
|
||||
}
|
||||
GameObject g = GameObject.Instantiate(args.Target) as GameObject;
|
||||
g.name = "~BillboardCreatorTarget";
|
||||
//g.hideFlags = HideFlags.HideAndDontSave;
|
||||
g.transform.position = cameraTransform.transform.TransformPoint(args.CameraOffset);
|
||||
g.transform.rotation = cameraTransform.rotation;
|
||||
g.transform.localScale = Vector3.one;
|
||||
|
||||
Material baseMaterial = args.Mode == GBillboardRenderMode.Normal ? args.NormalMaterial : args.AtlasMaterial;
|
||||
MeshRenderer[] renderers = g.GetComponentsInChildren<MeshRenderer>();
|
||||
for (int i = 0; i < renderers.Length; ++i)
|
||||
{
|
||||
Material[] sharedMaterials = renderers[i].sharedMaterials;
|
||||
for (int j = 0; j < sharedMaterials.Length; ++j)
|
||||
{
|
||||
//Material mat = Object.Instantiate<Material>(baseMaterial);
|
||||
Material mat = new Material(baseMaterial.shader);
|
||||
mat.SetColor(args.DesColorProps, Color.white);
|
||||
mat.SetTexture(args.DesTextureProps, null);
|
||||
//mat.CopyPropertiesFromMaterial(sharedMaterials[j]);
|
||||
try
|
||||
{
|
||||
if (sharedMaterials[j].HasProperty(args.SrcColorProps))
|
||||
{
|
||||
Color color = sharedMaterials[j].GetColor(args.SrcColorProps);
|
||||
color.a = 1;
|
||||
if (mat.HasProperty(args.DesColorProps))
|
||||
{
|
||||
mat.SetColor(args.DesColorProps, color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mat.HasProperty(args.DesColorProps))
|
||||
{
|
||||
mat.SetColor(args.DesColorProps, Color.white);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
if (sharedMaterials[j].HasProperty(args.SrcTextureProps))
|
||||
{
|
||||
Texture tex = sharedMaterials[j].GetTexture(args.SrcTextureProps);
|
||||
if (mat.HasProperty(args.DesTextureProps))
|
||||
{
|
||||
mat.SetTexture(args.DesTextureProps, tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
sharedMaterials[j] = mat;
|
||||
}
|
||||
renderers[i].sharedMaterials = sharedMaterials;
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
private static void Clear(RenderTexture rt, Color backgroundColor)
|
||||
{
|
||||
RenderTexture.active = rt;
|
||||
// bool isGammaSpace = true;
|
||||
//#if UNITY_EDITOR
|
||||
// if (UnityEditor.PlayerSettings.colorSpace != ColorSpace.Gamma)
|
||||
// {
|
||||
// isGammaSpace = false;
|
||||
// }
|
||||
//#endif
|
||||
|
||||
// GL.Clear(true, true, isGammaSpace ? backgroundColor : backgroundColor.linear);
|
||||
GL.Clear(true, true, backgroundColor);
|
||||
RenderTexture.active = null;
|
||||
}
|
||||
|
||||
public static ushort[] Triangulate(Vector2[] vertices)
|
||||
{
|
||||
List<ushort> tris = new List<ushort>();
|
||||
for (ushort x = 0; x < vertices.Length; ++x)
|
||||
{
|
||||
for (ushort y = 0; y < vertices.Length; ++y)
|
||||
{
|
||||
for (ushort z = 0; z < vertices.Length; ++z)
|
||||
{
|
||||
Vector2 v0 = vertices[x];
|
||||
Vector2 v1 = vertices[y];
|
||||
Vector2 v2 = vertices[z];
|
||||
|
||||
Vector3 cross = Vector3.Cross(v1 - v0, v2 - v0);
|
||||
if (cross.z < 0 && !IsTriangleAdded(tris, new ushort[] { x, y, z }))
|
||||
{
|
||||
tris.Add(x);
|
||||
tris.Add(y);
|
||||
tris.Add(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<ushort> result = new List<ushort>();
|
||||
int trisCount = tris.Count / 3;
|
||||
for (ushort i = 0; i < trisCount; ++i)
|
||||
{
|
||||
ushort t0 = tris[i * 3 + 0];
|
||||
ushort t1 = tris[i * 3 + 1];
|
||||
ushort t2 = tris[i * 3 + 2];
|
||||
|
||||
bool isValidTriangle = true;
|
||||
for (ushort vIndex = 0; vIndex < vertices.Length; ++vIndex)
|
||||
{
|
||||
if (vIndex == t0 || vIndex == t1 || vIndex == t2)
|
||||
continue;
|
||||
if (GUtilities.IsPointInCircumcircle(vertices[t0], vertices[t1], vertices[t2], vertices[vIndex]))
|
||||
{
|
||||
isValidTriangle = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValidTriangle)
|
||||
{
|
||||
result.Add(t0);
|
||||
result.Add(t1);
|
||||
result.Add(t2);
|
||||
}
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private static bool IsTriangleAdded(List<ushort> tris, ushort[] newTris)
|
||||
{
|
||||
int trisCount = tris.Count / 3;
|
||||
for (ushort i = 0; i < trisCount; ++i)
|
||||
{
|
||||
ushort i0 = tris[i * 3 + 0];
|
||||
ushort i1 = tris[i * 3 + 1];
|
||||
ushort i2 = tris[i * 3 + 2];
|
||||
if (GUtilities.AreSetEqual(new ushort[] { i0, i1, i2 }, newTris))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static GBillboardCreatorArgs FitCameraToTarget(GBillboardCreatorArgs args)
|
||||
{
|
||||
if (args.Target == null)
|
||||
return args;
|
||||
Renderer[] renderers = args.Target.GetComponentsInChildren<Renderer>();
|
||||
|
||||
if (renderers.Length > 0)
|
||||
{
|
||||
Bounds b = new Bounds();
|
||||
b.SetMinMax(
|
||||
renderers[0].bounds.min,
|
||||
renderers[0].bounds.max);
|
||||
for (int i = 1; i < renderers.Length; ++i)
|
||||
{
|
||||
Bounds bi = renderers[i].bounds;
|
||||
b.Encapsulate(bi.min);
|
||||
b.Encapsulate(bi.max);
|
||||
}
|
||||
b.Encapsulate(args.Target.transform.position);
|
||||
|
||||
Vector3 center = args.Target.transform.position;
|
||||
float dWidth = 2 * Mathf.Max(
|
||||
Vector3.Distance(center, new Vector3(b.min.x, center.y, b.min.z)),
|
||||
Vector3.Distance(center, new Vector3(b.max.x, center.y, b.max.z)));
|
||||
float dHeight = b.size.y;
|
||||
float bottom = b.min.y - center.y;
|
||||
args.CameraSize = Mathf.Max(dWidth, dHeight) * 0.5f;
|
||||
args.CameraOffset = -(b.center - center) + Vector3.forward * dWidth * 2;
|
||||
|
||||
args.Height = dHeight - bottom;
|
||||
args.Bottom = bottom;
|
||||
args.Width = dHeight;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
public static BillboardAsset CreateBillboardAsset(GBillboardCreatorArgs args)
|
||||
{
|
||||
BillboardAsset billboard = new BillboardAsset();
|
||||
billboard.SetVertices(args.Vertices);
|
||||
billboard.SetIndices(Triangulate(args.Vertices));
|
||||
billboard.width = args.Width;
|
||||
billboard.height = args.Height;
|
||||
billboard.bottom = args.Bottom;
|
||||
|
||||
Vector4[] texcoords = new Vector4[args.Row * args.Column];
|
||||
Vector2 imageSize = new Vector2(1f / args.Column, 1f / args.Row);
|
||||
Vector2 imageTopLeft = new Vector2(0, 0);
|
||||
|
||||
for (int y = 0; y < args.Row; ++y)
|
||||
{
|
||||
for (int x = 0; x < args.Column; ++x)
|
||||
{
|
||||
imageTopLeft = new Vector2(x * imageSize.x, y * imageSize.y);
|
||||
texcoords[GUtilities.To1DIndex(x, y, args.Column)] = new Vector4(imageTopLeft.x, imageTopLeft.y, imageSize.x, imageSize.y);
|
||||
}
|
||||
}
|
||||
billboard.SetImageTexCoords(texcoords);
|
||||
billboard.name = args.Target.name + "_Billboard";
|
||||
return billboard;
|
||||
}
|
||||
|
||||
public static Texture2D RenderAtlas(GBillboardCreatorArgs args)
|
||||
{
|
||||
args.Mode = GBillboardRenderMode.Atlas;
|
||||
RenderTexture rt = null;
|
||||
PrepareRenderTexture(ref rt, args);
|
||||
RenderPreviewAtlas(rt, args);
|
||||
Texture2D atlas = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, true, true);
|
||||
GCommon.CopyFromRT(atlas, rt);
|
||||
rt.Release();
|
||||
GUtilities.DestroyObject(rt);
|
||||
atlas.name = args.Target.name + "_Atlas";
|
||||
return atlas;
|
||||
}
|
||||
|
||||
public static Texture2D RenderNormal(GBillboardCreatorArgs args)
|
||||
{
|
||||
args.Mode = GBillboardRenderMode.Normal;
|
||||
RenderTexture rt = null;
|
||||
PrepareRenderTexture(ref rt, args);
|
||||
RenderPreviewNormal(rt, args);
|
||||
Texture2D atlas = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, true, true);
|
||||
GCommon.CopyFromRT(atlas, rt);
|
||||
rt.Release();
|
||||
GUtilities.DestroyObject(rt);
|
||||
atlas.name = args.Target.name + "_Normal";
|
||||
return atlas;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db76d4feb5c2d6d4c852d0826f6a8f85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
#if GRIFFIN
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pinwheel.Griffin.BillboardTool
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct GBillboardCreatorArgs
|
||||
{
|
||||
public GBillboardRenderMode Mode { get; set; }
|
||||
public GameObject Target { get; set; }
|
||||
public int Row { get; set; }
|
||||
public int Column { get; set; }
|
||||
public int CellSize { get; set; }
|
||||
public Vector3 CameraOffset { get; set; }
|
||||
public float CameraSize { get; set; }
|
||||
public Material AtlasMaterial { get; set; }
|
||||
public Material NormalMaterial { get; set; }
|
||||
public string SrcColorProps { get; set; }
|
||||
public string DesColorProps { get; set; }
|
||||
public string SrcTextureProps { get; set; }
|
||||
public string DesTextureProps { get; set; }
|
||||
public int CellIndex { get; set; }
|
||||
public Vector2[] Vertices { get; set; }
|
||||
public float Width { get; set; }
|
||||
public float Height { get; set; }
|
||||
public float Bottom { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75ae88b99b408784b98a6aa4aa284d7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
#if GRIFFIN
|
||||
namespace Pinwheel.Griffin.BillboardTool
|
||||
{
|
||||
public enum GBillboardRenderMode
|
||||
{
|
||||
Atlas, Normal, Flipbook
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c1899d241a3f334db77c960024ddb3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user