Files
Zombie/Assets/MeshBaker/scripts/core/MB_Utility.cs

497 lines
15 KiB
C#

//----------------------------------------------
// MeshBaker
// Copyright © 2011-2012 Ian Deane
//----------------------------------------------
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using Unity.Collections;
namespace DigitalOpus.MB.Core{
public class MB_Utility{
public static bool DO_INTEGRITY_CHECKS = false;
public struct MeshAnalysisResult{
public Rect uvRect;
public bool hasOutOfBoundsUVs;
public bool hasOverlappingSubmeshVerts;
// public bool hasOverlappingSubmeshTris;
public bool hasUVs;
public float submeshArea;
}
public static Texture2D createTextureCopy(Texture2D source, bool expectedToBeGammaCorrectedHint){
Texture2D newTex = new Texture2D(source.width,source.height,TextureFormat.ARGB32,true, ! MBVersion.IsTexture_sRGBgammaCorrected(source, expectedToBeGammaCorrectedHint));
newTex.SetPixels(source.GetPixels());
return newTex;
}
public static bool ArrayBIsSubsetOfA(System.Object[] a, System.Object[] b){
for (int i = 0; i < b.Length; i++){
bool foundBinA = false;
for (int j = 0; j < a.Length; j++){
if (a[j] == b[i]){
foundBinA = true;
break;
}
}
if (foundBinA == false) return false;
}
return true;
}
public static Material[] GetGOMaterials(GameObject go){
if (go == null) return new Material[0];
Material[] sharedMaterials = null;
Mesh mesh = null;
MeshRenderer mr = go.GetComponent<MeshRenderer>();
if (mr != null){
sharedMaterials = mr.sharedMaterials;
MeshFilter mf = go.GetComponent<MeshFilter>();
if (mf == null){
throw new Exception("Object " + go + " has a MeshRenderer but no MeshFilter.");
}
mesh = mf.sharedMesh;
}
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null){
sharedMaterials = smr.sharedMaterials;
mesh = smr.sharedMesh;
}
if (sharedMaterials == null){
Debug.LogError("Object " + go.name + " does not have a MeshRenderer or a SkinnedMeshRenderer component");
return new Material[0];
} else if (mesh == null){
Debug.LogError("Object " + go.name + " has a MeshRenderer or SkinnedMeshRenderer but no mesh.");
return new Material[0];
} else {
if (mesh.subMeshCount < sharedMaterials.Length){
Debug.LogWarning("Object " + go + " has only " + mesh.subMeshCount + " submeshes and has " + sharedMaterials.Length + " materials. Extra materials do nothing.");
Material[] newSharedMaterials = new Material[mesh.subMeshCount];
Array.Copy(sharedMaterials,newSharedMaterials,newSharedMaterials.Length);
sharedMaterials = newSharedMaterials;
}
return sharedMaterials;
}
}
public static Mesh GetMesh(GameObject go){
if (go == null) return null;
MeshFilter mf = go.GetComponent<MeshFilter>();
if (mf != null){
return mf.sharedMesh;
}
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null){
return smr.sharedMesh;
}
return null;
}
public static void SetMesh(GameObject go, Mesh m)
{
if (go == null) return;
MeshFilter mf = go.GetComponent<MeshFilter>();
if (mf != null)
{
mf.sharedMesh = m;
}
else
{
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null)
{
smr.sharedMesh = m;
}
}
}
public static Renderer GetRenderer(GameObject go){
if (go == null) return null;
MeshRenderer mr = go.GetComponent<MeshRenderer>();
if (mr != null) return mr;
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null) return smr;
return null;
}
public static void DisableRendererInSource(GameObject go){
if (go == null) return;
MeshRenderer mf = go.GetComponent<MeshRenderer>();
if (mf != null){
mf.enabled = false;
return;
}
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr != null){
smr.enabled = false;
return;
}
}
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds){
MeshAnalysisResult mar = new MeshAnalysisResult();
bool outVal = hasOutOfBoundsUVs(m, ref mar);
uvBounds = mar.uvRect;
return outVal;
}
public static bool hasOutOfBoundsUVs(Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1, int uvChannel = 0)
{
if (m == null)
{
putResultHere.hasOutOfBoundsUVs = false;
return putResultHere.hasOutOfBoundsUVs;
}
Vector2[] uvs;
if (uvChannel == 0) {
uvs = m.uv;
} else if (uvChannel == 1)
{
uvs = m.uv2;
} else if (uvChannel == 2)
{
uvs = m.uv3;
} else {
uvs = m.uv4;
}
return hasOutOfBoundsUVs(uvs, m, ref putResultHere, submeshIndex);
}
public static bool hasOutOfBoundsUVs(Vector2[] uvs, Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1)
{
putResultHere.hasUVs = true;
if (uvs.Length == 0)
{
putResultHere.hasUVs = false;
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
float minx, miny, maxx, maxy;
if (submeshIndex >= m.subMeshCount)
{
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
else if (submeshIndex >= 0)
{
//checking specific submesh
int[] tris = m.GetTriangles(submeshIndex);
if (tris.Length == 0)
{
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
minx = maxx = uvs[tris[0]].x;
miny = maxy = uvs[tris[0]].y;
for (int idx = 0; idx < tris.Length; idx++)
{
int i = tris[idx];
if (uvs[i].x < minx) minx = uvs[i].x;
if (uvs[i].x > maxx) maxx = uvs[i].x;
if (uvs[i].y < miny) miny = uvs[i].y;
if (uvs[i].y > maxy) maxy = uvs[i].y;
}
}
else {
//checking all UVs
minx = maxx = uvs[0].x;
miny = maxy = uvs[0].y;
for (int i = 0; i < uvs.Length; i++)
{
if (uvs[i].x < minx) minx = uvs[i].x;
if (uvs[i].x > maxx) maxx = uvs[i].x;
if (uvs[i].y < miny) miny = uvs[i].y;
if (uvs[i].y > maxy) maxy = uvs[i].y;
}
}
Rect uvBounds = new Rect();
uvBounds.x = minx;
uvBounds.y = miny;
uvBounds.width = maxx - minx;
uvBounds.height = maxy - miny;
if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f)
{
putResultHere.hasOutOfBoundsUVs = true;
}
else
{
putResultHere.hasOutOfBoundsUVs = false;
}
putResultHere.uvRect = uvBounds;
return putResultHere.hasOutOfBoundsUVs;
}
public static bool hasOutOfBoundsUVs(NativeArray<Vector2> uvs, Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1)
{
putResultHere.hasUVs = true;
if (uvs.Length == 0)
{
putResultHere.hasUVs = false;
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
float minx, miny, maxx, maxy;
if (submeshIndex >= m.subMeshCount)
{
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
else if (submeshIndex >= 0)
{
//checking specific submesh
int[] tris = m.GetTriangles(submeshIndex);
if (tris.Length == 0)
{
putResultHere.hasOutOfBoundsUVs = false;
putResultHere.uvRect = new Rect();
return putResultHere.hasOutOfBoundsUVs;
}
minx = maxx = uvs[tris[0]].x;
miny = maxy = uvs[tris[0]].y;
for (int idx = 0; idx < tris.Length; idx++)
{
int i = tris[idx];
if (uvs[i].x < minx) minx = uvs[i].x;
if (uvs[i].x > maxx) maxx = uvs[i].x;
if (uvs[i].y < miny) miny = uvs[i].y;
if (uvs[i].y > maxy) maxy = uvs[i].y;
}
}
else
{
//checking all UVs
minx = maxx = uvs[0].x;
miny = maxy = uvs[0].y;
for (int i = 0; i < uvs.Length; i++)
{
if (uvs[i].x < minx) minx = uvs[i].x;
if (uvs[i].x > maxx) maxx = uvs[i].x;
if (uvs[i].y < miny) miny = uvs[i].y;
if (uvs[i].y > maxy) maxy = uvs[i].y;
}
}
Rect uvBounds = new Rect();
uvBounds.x = minx;
uvBounds.y = miny;
uvBounds.width = maxx - minx;
uvBounds.height = maxy - miny;
if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f)
{
putResultHere.hasOutOfBoundsUVs = true;
}
else
{
putResultHere.hasOutOfBoundsUVs = false;
}
putResultHere.uvRect = uvBounds;
return putResultHere.hasOutOfBoundsUVs;
}
public static void setSolidColor(Texture2D t, Color c)
{
Color[] cs = t.GetPixels();
for (int i = 0; i < cs.Length; i++)
{
cs[i] = c;
}
t.SetPixels(cs);
t.Apply();
}
public static Texture2D resampleTexture(Texture2D source, bool expectToBeGammaCorrectedHint, int newWidth, int newHeight){
TextureFormat f = source.format;
if (f == TextureFormat.ARGB32 ||
f == TextureFormat.RGBA32 ||
f == TextureFormat.BGRA32 ||
f == TextureFormat.RGB24 ||
f == TextureFormat.Alpha8 ||
f == TextureFormat.DXT1)
{
Texture2D newTex = new Texture2D(newWidth,newHeight,TextureFormat.ARGB32,true, ! MBVersion.IsTexture_sRGBgammaCorrected( source, expectToBeGammaCorrectedHint ));
float w = newWidth;
float h = newHeight;
for (int i = 0; i < newWidth; i++){
for (int j = 0; j < newHeight; j++){
float u = i/w;
float v = j/h;
newTex.SetPixel(i,j,source.GetPixelBilinear(u,v));
}
}
newTex.Apply();
return newTex;
} else {
Debug.LogError("Can only resize textures in formats ARGB32, RGBA32, BGRA32, RGB24, Alpha8 or DXT. texture:" + source + " was in format: " + source.format);
return null;
}
}
class MB_Triangle{
int submeshIdx;
int[] vs = new int[3];
public bool isSame(object obj){
MB_Triangle tobj = (MB_Triangle) obj;
if (vs[0] == tobj.vs[0] &&
vs[1] == tobj.vs[1] &&
vs[2] == tobj.vs[2] &&
submeshIdx != tobj.submeshIdx){
return true;
}
return false;
}
public bool sharesVerts(MB_Triangle obj){
if (vs[0] == obj.vs[0] ||
vs[0] == obj.vs[1] ||
vs[0] == obj.vs[2]){
if (submeshIdx != obj.submeshIdx) return true;
}
if (vs[1] == obj.vs[0] ||
vs[1] == obj.vs[1] ||
vs[1] == obj.vs[2]){
if (submeshIdx != obj.submeshIdx) return true;
}
if (vs[2] == obj.vs[0] ||
vs[2] == obj.vs[1] ||
vs[2] == obj.vs[2]){
if (submeshIdx != obj.submeshIdx) return true;
}
return false;
}
public void Initialize(int[] ts, int idx, int sIdx){
vs[0] = ts[idx];
vs[1] = ts[idx + 1];
vs[2] = ts[idx + 2];
submeshIdx = sIdx;
Array.Sort(vs);
}
}
public static bool AreAllSharedMaterialsDistinct(Material[] sharedMaterials){
for (int i = 0; i < sharedMaterials.Length; i++){
for (int j = i + 1; j < sharedMaterials.Length; j++){
if (sharedMaterials[i] == sharedMaterials[j]){
return false;
}
}
}
return true;
}
public static void doSubmeshesShareVertsOrTris(Mesh m, ref MeshAnalysisResult mar)
{
//Get all triangles
int[][] tris = new int[m.subMeshCount][];
for (int submeshIdx = 0; submeshIdx < m.subMeshCount; submeshIdx++)
{
tris[submeshIdx] = m.GetTriangles(submeshIdx);
}
int[] usedVerts = new int[m.vertexCount];
for (int i = 0; i < usedVerts.Length; i++)
{
usedVerts[i] = -1;
}
bool sharesVerts = false;
for (int submeshIdx = 0; submeshIdx < m.subMeshCount; submeshIdx++)
{
int[] smA = tris[submeshIdx];
for (int triIdx = 0; triIdx < smA.Length; triIdx++)
{
int vertIdx = smA[triIdx];
if (usedVerts[vertIdx] != -1 &&
usedVerts[vertIdx] != submeshIdx)
{
sharesVerts = true;
break;
}
usedVerts[vertIdx] = submeshIdx; // This vertex is used by submesh_Idx
}
}
if (sharesVerts)
{
mar.hasOverlappingSubmeshVerts = true;
}
else
{
//mar.hasOverlappingSubmeshTris = false;
mar.hasOverlappingSubmeshVerts = false;
}
}
public static bool GetBounds(GameObject go, out Bounds b){
if (go == null){
Debug.LogError("go paramater was null");
b = new Bounds(Vector3.zero,Vector3.zero);
return false;
}
Renderer r = GetRenderer(go);
if (r == null){
Debug.LogError("GetBounds must be called on an object with a Renderer");
b = new Bounds(Vector3.zero,Vector3.zero);
return false;
}
if (r is MeshRenderer){
b = r.bounds;
return true;
} else if (r is SkinnedMeshRenderer){
b = r.bounds;
return true;
}
Debug.LogError("GetBounds must be called on an object with a MeshRender or a SkinnedMeshRenderer.");
b = new Bounds(Vector3.zero,Vector3.zero);
return false;
}
public static void Destroy(UnityEngine.Object o){
if (Application.isPlaying){
MonoBehaviour.Destroy(o);
} else {
// string p = AssetDatabase.GetAssetPath(o);
// if (p != null && p.Equals("")) // don't try to destroy assets
MonoBehaviour.DestroyImmediate(o,false);
}
}
public static string ConvertAssetsRelativePathToFullSystemPath(string pth)
{
string aPth = Application.dataPath.Replace("Assets", "");
return aPth + pth;
}
public static bool IsSceneInstance(GameObject go)
{
// go.scene.name
// - is the name of the scene if in a scene
// - is the name of the prefab if in prefab edit scene
// - is null if is a prefab assigned from the project folder
return go.scene.name != null;
}
public static string BoneWeightToString(BoneWeight bw)
{
return String.Format("BoneWeight {0}:{1}, {2}:{3}, {4}:{5}, {6}:{7}", bw.boneIndex0, bw.weight0, bw.boneIndex1, bw.weight1, bw.boneIndex2, bw.weight2, bw.boneIndex3, bw.weight3);
}
}
}