Wesley Mareovich Smith
4 年前
当前提交
9fcf7d7c
共有 13 个文件被更改,包括 426 次插入 和 1439 次删除
-
187com.unity.perception/Editor/Validation/ModelTestUI.cs
-
106com.unity.perception/Runtime/Validation/CharacterTooling.cs
-
305com.unity.perception/Runtime/Validation/CharacterToolingLibrary.cs
-
54com.unity.perception/Runtime/Validation/AIContentData.cs
-
11com.unity.perception/Runtime/Validation/AIContentData.cs.meta
-
496com.unity.perception/Runtime/Validation/AIContentValidation.cs
-
535com.unity.perception/Runtime/Validation/AIContentValidationLibrary.cs
-
11com.unity.perception/Tests/Editor/EditorValidationTests.cs.meta
-
152com.unity.perception/Tests/Editor/EditorValidationTests.cs
-
8com.unity.perception/Tests/Runtime/Validation.meta
-
0/com.unity.perception/Runtime/Validation/CharacterTooling.cs.meta
-
0/com.unity.perception/Runtime/Validation/CharacterToolingLibrary.cs.meta
|
|||
using System.Collections.Generic; |
|||
using static UnityEngine.Perception.Content.CharacterValidation; |
|||
using System.Linq; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEngine.Perception.Content |
|||
{ |
|||
public class CharacterTooling : MonoBehaviour |
|||
{ |
|||
public bool CharacterRequiredBones(Animator animator, out Dictionary<HumanBone, bool> failed) |
|||
{ |
|||
var result = AvatarRequiredBones(animator); |
|||
failed = new Dictionary<HumanBone, bool>(); |
|||
|
|||
for (int i = 0; i < result.Count; i++) |
|||
{ |
|||
var bone = result.ElementAt(i); |
|||
var boneKey = bone.Key; |
|||
var boneValue = bone.Value; |
|||
|
|||
if (boneValue != true) |
|||
failed.Add(boneKey, boneValue); |
|||
} |
|||
|
|||
if (failed.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool CharacterPoseData(GameObject gameObject, out List<GameObject> failedGameObjects) |
|||
{ |
|||
failedGameObjects = new List<GameObject>(); |
|||
|
|||
var componentsParent = gameObject.GetComponents<Transform>(); |
|||
var componentsChild = gameObject.GetComponentsInChildren<Transform>(); |
|||
|
|||
for (int p = 0; p < componentsParent.Length; p++) |
|||
{ |
|||
if (componentsParent[p].GetType() == typeof(Transform)) |
|||
{ |
|||
var pos = componentsParent[p].transform.position; |
|||
var rot = componentsParent[p].transform.rotation.eulerAngles; |
|||
|
|||
if (pos == null || rot == null) |
|||
{ |
|||
failedGameObjects.Add(componentsParent[p].gameObject); |
|||
} |
|||
} |
|||
} |
|||
|
|||
for (int c = 0; c < componentsChild.Length; c++) |
|||
{ |
|||
if (componentsChild[c].GetType() == typeof(Transform)) |
|||
{ |
|||
var pos = componentsChild[c].transform.position; |
|||
var rot = componentsChild[c].transform.rotation.eulerAngles; |
|||
|
|||
if (pos == null || rot == null) |
|||
{ |
|||
failedGameObjects.Add(componentsChild[c].gameObject); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (failedGameObjects.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool CharacterCreateNose(GameObject selection, Animator animator, SkinnedMeshRenderer skinnedMeshRenderer, bool drawRays = false) |
|||
{ |
|||
var model = AvatarCreateNose(selection, animator, skinnedMeshRenderer, drawRays); |
|||
var childCount = model.transform.childCount; |
|||
var nose = false; |
|||
var earRight = false; |
|||
var earLeft = false; |
|||
|
|||
for (int i = 0; i < childCount; i++) |
|||
{ |
|||
if (model.transform.GetChild(i).name == "head") |
|||
{ |
|||
var modelHead = model.transform.GetChild(i); |
|||
var headChildCount = modelHead.transform.childCount; |
|||
|
|||
for (int h = 0; h > headChildCount; h++) |
|||
{ |
|||
var childName = modelHead.transform.GetChild(h).name; |
|||
if (childName.Contains("nose")) |
|||
nose = true; |
|||
if (childName.Contains("earRight")) |
|||
earRight = true; |
|||
if (childName.Contains("earLeft")) |
|||
earLeft = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (nose && earRight && earLeft) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEngine.Perception.Content |
|||
{ |
|||
public static class CharacterValidation |
|||
{ |
|||
public static string[] RequiredBones = |
|||
{ |
|||
"Head", |
|||
"Hips", |
|||
"Spine", |
|||
"LeftUpperArm", |
|||
"LeftLowerArm", |
|||
"LeftHand", |
|||
"RightUpperArm", |
|||
"RightLowerArm", |
|||
"RightHand", |
|||
"LeftUpperLeg", |
|||
"LeftLowerLeg", |
|||
"LeftFoot", |
|||
"RightUpperLeg", |
|||
"RightLowerLeg", |
|||
"RightFoot", |
|||
}; |
|||
|
|||
public static Dictionary<HumanBone, bool> AvatarRequiredBones(Animator animator) |
|||
{ |
|||
var result = new Dictionary<HumanBone, bool>(); |
|||
var human = animator.avatar.humanDescription.human; |
|||
var totalBones = 0; |
|||
|
|||
for(int h = 0; h < human.Length; h++) |
|||
{ |
|||
for (int b = 0; b < RequiredBones.Length; b++) |
|||
{ |
|||
if(human[h].humanName == RequiredBones[b]) |
|||
{ |
|||
var bone = new HumanBone(); |
|||
|
|||
if (human[h].boneName != null) |
|||
{ |
|||
bone.boneName = human[h].boneName; |
|||
totalBones = totalBones = +1; |
|||
result.Add(bone, true); |
|||
} |
|||
else |
|||
{ |
|||
result.Add(bone, false); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static GameObject AvatarCreateNose (GameObject selection, Animator animator, SkinnedMeshRenderer skinnedMeshRenderer, bool drawRays = false) |
|||
{ |
|||
var human = animator.avatar.humanDescription.human; |
|||
var skeleton = animator.avatar.humanDescription.skeleton; |
|||
var verticies = skinnedMeshRenderer.sharedMesh.vertices; |
|||
|
|||
var head = animator.GetBoneTransform(HumanBodyBones.Head); |
|||
var leftEye = animator.GetBoneTransform(HumanBodyBones.RightEye); |
|||
var rightEye = animator.GetBoneTransform(HumanBodyBones.LeftEye); |
|||
var faceCenter = Vector3.zero; |
|||
var earCenter = Vector3.zero; |
|||
var nosePos = Vector3.zero; |
|||
var earRightPos = Vector3.zero; |
|||
var earLeftPos = Vector3.zero; |
|||
var distanceCheck = 1f; |
|||
|
|||
var eyeDistance = Vector3.Distance(leftEye.position, rightEye.position); |
|||
var directionLeft = Quaternion.AngleAxis(-45, -leftEye.right) * -leftEye.up; |
|||
var directionRight = Quaternion.AngleAxis(-45, rightEye.right) * -rightEye.up; |
|||
|
|||
var rayHead = new Ray(); |
|||
var rayLeftEye = new Ray(); |
|||
var rayRightEye = new Ray(); |
|||
var noseRayFor = new Ray(); |
|||
var rayNoseBack = new Ray(); |
|||
var rayEarLeft = new Ray(); |
|||
var rayEarRight = new Ray(); |
|||
|
|||
var foundRightEar = false; |
|||
var foundLeftEar = false; |
|||
|
|||
rayLeftEye.origin = leftEye.position; |
|||
rayLeftEye.direction = directionLeft * eyeDistance; |
|||
|
|||
rayRightEye.origin = rightEye.position; |
|||
rayRightEye.direction = directionRight * eyeDistance; |
|||
|
|||
for (double i = 0; i < distanceCheck; i += 0.01) |
|||
{ |
|||
var point = Convert.ToSingle(i); |
|||
var pointR = rayRightEye.GetPoint(point); |
|||
var pointL = rayLeftEye.GetPoint(point); |
|||
|
|||
var distanceX = Math.Abs(pointR.x - pointL.x); |
|||
var distanceY = Math.Abs(pointR.y - pointL.y); |
|||
|
|||
if (distanceX < 0.01 && distanceY < 0.01 ) |
|||
{ |
|||
faceCenter = pointR; |
|||
} |
|||
} |
|||
|
|||
rayHead.origin = head.position; |
|||
rayHead.direction = Vector3.up * distanceCheck; |
|||
|
|||
noseRayFor.origin = faceCenter; |
|||
noseRayFor.direction = Vector3.forward * distanceCheck; |
|||
|
|||
rayNoseBack.origin = faceCenter; |
|||
rayNoseBack.direction = Vector3.back * distanceCheck; |
|||
|
|||
for (double i = 0; i < distanceCheck; i += 0.01) |
|||
{ |
|||
var point = Convert.ToSingle(i); |
|||
var pointH = rayHead.GetPoint(point); |
|||
var pointF = rayNoseBack.GetPoint(point); |
|||
|
|||
var distanceZ = Math.Abs(pointH.z - pointF.z); |
|||
|
|||
if (distanceZ < 0.01) |
|||
{ |
|||
earCenter = pointF; |
|||
} |
|||
} |
|||
|
|||
for (int v = 0; v < verticies.Length; v++) |
|||
{ |
|||
for (double c = eyeDistance / 2; c < distanceCheck; c += 0.001) |
|||
{ |
|||
var point = Convert.ToSingle(c); |
|||
var pointNoseRay = noseRayFor.GetPoint(point); |
|||
var pointVert = verticies[v]; |
|||
var distHeadZ = Math.Abs(pointNoseRay.z - pointVert.z); |
|||
var distHeadX = Math.Abs(pointNoseRay.x - pointVert.x); |
|||
|
|||
if (distHeadZ < 0.0001 && distHeadX < 0.001) |
|||
{ |
|||
nosePos = pointNoseRay; |
|||
Debug.Log("Found Nose: " + nosePos); |
|||
} |
|||
|
|||
if(nosePos == Vector3.zero) |
|||
{ |
|||
if (distHeadZ < 0.001 && distHeadX < 0.001) |
|||
{ |
|||
nosePos = pointNoseRay; |
|||
Debug.Log("Found Nose: " + nosePos); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
rayEarRight.origin = earCenter; |
|||
rayEarRight.direction = Vector3.right * distanceCheck; |
|||
|
|||
rayEarLeft.origin = earCenter; |
|||
rayEarLeft.direction = Vector3.left * distanceCheck; |
|||
|
|||
for (int v = 0; v < verticies.Length; v++) |
|||
{ |
|||
for (double c = eyeDistance / 2; c < distanceCheck; c += 0.001) |
|||
{ |
|||
var point = Convert.ToSingle(c); |
|||
var pointEarRight = rayEarRight.GetPoint(point); |
|||
var pointEarLeft = rayEarLeft.GetPoint(point); |
|||
var pointVert = verticies[v]; |
|||
|
|||
var distEarRightY = Math.Abs(pointEarRight.y - pointVert.y); |
|||
var distEarRightX = Math.Abs(pointEarRight.x - pointVert.x); |
|||
|
|||
var distEarLeftY = Math.Abs(pointEarLeft.y - pointVert.y); |
|||
var distEarLeftX = Math.Abs(pointEarLeft.x - pointVert.x); |
|||
|
|||
if (distEarRightY < 0.001 && distEarRightX < 0.0001) |
|||
{ |
|||
earRightPos = pointEarRight; |
|||
foundRightEar = true; |
|||
} |
|||
|
|||
if (distEarLeftY < 0.001 && distEarLeftX < 0.0001) |
|||
{ |
|||
earLeftPos = pointEarLeft; |
|||
foundLeftEar = true; |
|||
} |
|||
|
|||
if (!foundRightEar) |
|||
{ |
|||
if (distEarRightY < 0.002 && distEarRightX < 0.001) |
|||
{ |
|||
earRightPos = pointEarRight; |
|||
} |
|||
} |
|||
|
|||
if (!foundLeftEar) |
|||
{ |
|||
if (distEarLeftY < 0.002 && distEarLeftX < 0.001) |
|||
{ |
|||
earLeftPos = pointEarLeft; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
var earLeftCheck = Vector3.Distance(earLeftPos, earCenter); |
|||
var earRightCheck = Vector3.Distance(earRightPos, earCenter); |
|||
var eyeCenterDistance = eyeDistance + 0.01f; |
|||
|
|||
if (earLeftCheck > eyeCenterDistance) |
|||
{ |
|||
earLeftPos.x = (-eyeDistance); |
|||
} |
|||
|
|||
if (earRightCheck > eyeCenterDistance) |
|||
{ |
|||
earRightPos.x = eyeDistance; |
|||
} |
|||
|
|||
if(drawRays) |
|||
{ |
|||
DebugDrawRays(30f, distanceCheck, rightEye, leftEye, head, rayRightEye, rayLeftEye, faceCenter, earCenter); |
|||
} |
|||
|
|||
return CreateNewCharacterPrefab(selection, nosePos, earRightPos, earLeftPos); |
|||
} |
|||
|
|||
public static void DebugDrawRays(float duration, float distanceCheck, Transform rightEye, Transform leftEye, Transform head,Ray rayRightEye, Ray rayLeftEye, Vector3 faceCenter, Vector3 earCenter) |
|||
{ |
|||
Debug.DrawLine(rightEye.position, leftEye.position, Color.magenta, duration); |
|||
Debug.DrawRay(rayLeftEye.origin, rayLeftEye.direction, Color.green, duration); |
|||
Debug.DrawRay(rayRightEye.origin, rayRightEye.direction, Color.blue, duration); |
|||
Debug.DrawRay(faceCenter, Vector3.forward * distanceCheck, Color.cyan, duration); |
|||
Debug.DrawRay(faceCenter, Vector3.back, Color.cyan, duration); |
|||
Debug.DrawRay(head.position, Vector3.up, Color.red, duration); |
|||
Debug.DrawRay(earCenter, Vector3.right, Color.blue, duration); |
|||
Debug.DrawRay(earCenter, Vector3.left, Color.green, duration); |
|||
} |
|||
|
|||
public static GameObject CreateNewCharacterPrefab(GameObject selection, Vector3 nosePosition, Vector3 earRightPosition, Vector3 earLeftPosition) |
|||
{ |
|||
var root = (GameObject)PrefabUtility.InstantiatePrefab(selection); |
|||
List<Transform> children = new List<Transform>(); |
|||
root.GetComponentsInChildren(children); |
|||
|
|||
foreach(var child in children) |
|||
{ |
|||
if (child.name == "head") |
|||
{ |
|||
if (nosePosition != Vector3.zero) |
|||
{ |
|||
var nose = new GameObject(); |
|||
nose.transform.position = nosePosition; |
|||
nose.name = "nose"; |
|||
nose.transform.SetParent(child); |
|||
|
|||
AddJointLabel(nose); |
|||
} |
|||
|
|||
if (earRightPosition != Vector3.zero) |
|||
{ |
|||
var earRight = new GameObject(); |
|||
earRight.transform.position = earRightPosition; |
|||
earRight.name = "earRight"; |
|||
earRight.transform.SetParent(child); |
|||
|
|||
AddJointLabel(earRight); |
|||
} |
|||
|
|||
if (earLeftPosition != Vector3.zero) |
|||
{ |
|||
var earLeft = new GameObject(); |
|||
earLeft.transform.position = earLeftPosition; |
|||
earLeft.name = "earLeft"; |
|||
earLeft.transform.SetParent(child); |
|||
|
|||
AddJointLabel(earLeft); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var model = PrefabUtility.SaveAsPrefabAsset(root, "Assets/" + root.name + ".prefab"); |
|||
|
|||
return model; |
|||
} |
|||
|
|||
private static void AddJointLabel(GameObject gameObject) |
|||
{ |
|||
var jointLabel = gameObject.AddComponent<JointLabel>(); |
|||
var data = new JointLabel.TemplateData(); |
|||
|
|||
data.label = gameObject.name; |
|||
jointLabel.templateInformation.Add(data); |
|||
} |
|||
} |
|||
} |
|
|||
namespace UnityEngine.Perception.Content |
|||
{ |
|||
public class ContentData : MonoBehaviour |
|||
{ |
|||
//UV Count
|
|||
public int TryGetAssetUVCount(MeshFilter mesh) |
|||
{ |
|||
return mesh.sharedMesh.uv.Length; |
|||
} |
|||
|
|||
public void TryGetAssetUVCount(MeshFilter mesh, out int count, out string assetName) |
|||
{ |
|||
assetName = mesh.name; |
|||
count = mesh.sharedMesh.uv.Length; |
|||
} |
|||
|
|||
//Size bounds
|
|||
public void TryGetSizeAsset(MeshRenderer mesh, out Vector3 assetSize, out string assetName) |
|||
{ |
|||
assetName = mesh.name; |
|||
assetSize = new Vector3(mesh.bounds.size.x, mesh.bounds.size.y, mesh.bounds.size.y); |
|||
} |
|||
|
|||
public Vector3 TryGetSizeAsset(MeshRenderer mesh) |
|||
{ |
|||
return new Vector3(mesh.bounds.size.x, mesh.bounds.size.y, mesh.bounds.size.y); |
|||
} |
|||
|
|||
//Vertex Count
|
|||
public void TryGetAssetVertexCount(MeshFilter mesh, out int count, out string assetName) |
|||
{ |
|||
assetName = mesh.name; |
|||
count = mesh.sharedMesh.vertexCount; |
|||
} |
|||
|
|||
public int TryGetAssetVertexCount(MeshFilter mesh) |
|||
{ |
|||
return mesh.sharedMesh.vertexCount; |
|||
} |
|||
|
|||
//Triangles Count for polygon count
|
|||
public void TryGetAssetPolygonCount(MeshFilter mesh, out int count, out string assetName) |
|||
{ |
|||
assetName = mesh.name; |
|||
count = mesh.sharedMesh.triangles.Length / 3; |
|||
} |
|||
|
|||
public int TryGetAssetPolygonCount(MeshFilter mesh) |
|||
{ |
|||
return mesh.sharedMesh.triangles.Length / 3; |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5a82ed528e1016448a8fc750ba7a7b62 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using static UnityEngine.Perception.Content.GeomertryValidation; |
|||
using static UnityEngine.Perception.Content.TextureValidation; |
|||
using static UnityEngine.Perception.Content.CharacterValidation; |
|||
using System.Linq; |
|||
|
|||
namespace UnityEngine.Perception.Content |
|||
{ |
|||
public class ContentValidation : MonoBehaviour |
|||
{ |
|||
public bool TestScale(MeshRenderer[] meshRenderers, float heightMax = 2.44f, float widthMax = 2.44f, float lengthMax = 2.44f) |
|||
{ |
|||
var heightPass = false; |
|||
var widthPass = false; |
|||
var lengthPass = false; |
|||
|
|||
float heightMin = 0.01f; |
|||
float widthMin = 0.01f; |
|||
float lengthMin = 0.01f; |
|||
|
|||
foreach (var meshRenderer in meshRenderers) |
|||
{ |
|||
var height = meshRenderer.bounds.size.y; |
|||
var width = meshRenderer.bounds.size.x; |
|||
var length = meshRenderer.bounds.size.z; |
|||
|
|||
if (height <= heightMax && height >= heightMin) |
|||
{ |
|||
heightPass = true; |
|||
} |
|||
|
|||
if (width <= widthMax && width >= widthMin) |
|||
{ |
|||
widthPass = true; |
|||
} |
|||
|
|||
if (length <= lengthMax && length >= lengthMin) |
|||
{ |
|||
lengthPass = true; |
|||
} |
|||
} |
|||
|
|||
if (heightPass && widthPass && lengthPass) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool TransformTest(GameObject gameObject, out List<GameObject> failedGameObjects) |
|||
{ |
|||
/// Bounding box at Vector.Zero
|
|||
var componentsParent = gameObject.GetComponents<Component>(); |
|||
var componentsChild = gameObject.GetComponentsInChildren<Component>(); |
|||
|
|||
|
|||
|
|||
var posTransformTest = false; |
|||
var rotTransformTest = false; |
|||
|
|||
failedGameObjects = new List<GameObject>(); |
|||
|
|||
foreach (var com in componentsParent) |
|||
{ |
|||
posTransformTest = false; |
|||
rotTransformTest = false; |
|||
|
|||
if (com.GetType() == typeof(Transform)) |
|||
{ |
|||
var rotParent = gameObject.transform.rotation; |
|||
var pos = com.transform.position; |
|||
var rot = rotParent.eulerAngles; |
|||
|
|||
if (pos == Vector3.zero) |
|||
{ |
|||
posTransformTest = true; |
|||
} |
|||
|
|||
if ((rot.x > 269) && (rot.x < 271)) |
|||
rotTransformTest = true; |
|||
else if ((rot.x > 89) && (rot.x < 91)) |
|||
rotTransformTest = true; |
|||
|
|||
if (rotParent == Quaternion.identity) |
|||
rotTransformTest = true; |
|||
|
|||
if (!posTransformTest || !rotTransformTest) |
|||
failedGameObjects.Add(com.gameObject); |
|||
} |
|||
} |
|||
|
|||
foreach (var com in componentsChild) |
|||
{ |
|||
posTransformTest = false; |
|||
rotTransformTest = false; |
|||
|
|||
if (com.GetType() == typeof(Transform)) |
|||
{ |
|||
var pos = com.transform.position; |
|||
var rotEuler = com.transform.rotation.eulerAngles; |
|||
var rot = com.transform.rotation; |
|||
|
|||
if (pos == Vector3.zero) |
|||
{ |
|||
posTransformTest = true; |
|||
} |
|||
|
|||
if ((rotEuler.x > 269) && (rotEuler.x < 271)) |
|||
rotTransformTest = true; |
|||
else if ((rotEuler.x > 89) && (rotEuler.x < 91)) |
|||
rotTransformTest = true; |
|||
|
|||
if (rot == Quaternion.identity) |
|||
rotTransformTest = true; |
|||
|
|||
if (!posTransformTest || !rotTransformTest) |
|||
failedGameObjects.Add(com.gameObject); |
|||
} |
|||
} |
|||
if (failedGameObjects.Count == 0) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
public bool EmptyComponentsTest(GameObject selection) |
|||
{ |
|||
var parentComTest = false; |
|||
var baseComTest = false; |
|||
var parentComponents = selection.GetComponents<Component>(); |
|||
|
|||
foreach (var com in parentComponents) |
|||
{ |
|||
var type = com.GetType(); |
|||
if (type == selection.transform.GetType() || com.name.Contains("MetaData")) |
|||
baseComTest = true; |
|||
else |
|||
baseComTest = false; |
|||
} |
|||
|
|||
if (parentComponents.Length <= 2) |
|||
{ |
|||
parentComTest = true; |
|||
} |
|||
else |
|||
{ |
|||
parentComTest = false; |
|||
} |
|||
|
|||
if (parentComTest && baseComTest) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool AssetCheckPivotPoint(GameObject gameObject, out List<GameObject> failed) |
|||
{ |
|||
failed = new List<GameObject>(); |
|||
|
|||
var posParent = gameObject.transform.position; |
|||
var componentsChild = gameObject.GetComponentsInChildren<Transform>(); |
|||
|
|||
Vector3 attachmentPoint = new Vector3(); |
|||
|
|||
float comparePoints = 0f; |
|||
|
|||
string[] attachmentPoints = { "base", "lamp", "backplate", "frame", "holder" }; |
|||
|
|||
bool attachPointFound = false; |
|||
|
|||
for (int c = 0; c < componentsChild.Length; c++) |
|||
{ |
|||
for (int a = 0; a < attachmentPoints.Length; a++) |
|||
{ |
|||
if (componentsChild[c].name == attachmentPoints[a]) |
|||
{ |
|||
attachmentPoint = componentsChild[c].transform.position; |
|||
comparePoints = Vector3.Distance(attachmentPoint, posParent); |
|||
attachPointFound = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (!attachPointFound) |
|||
{ |
|||
attachmentPoint = Vector3.zero; |
|||
comparePoints = Vector3.Distance(attachmentPoint, posParent); |
|||
} |
|||
|
|||
if (comparePoints > 0f) |
|||
failed.Add(gameObject); |
|||
|
|||
if (failed.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool UVDataTest(MeshFilter[] meshFilters) |
|||
{ |
|||
var uvsNotNull = false; |
|||
var uvsData = false; |
|||
|
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var uvs = mesh.sharedMesh.uv; |
|||
|
|||
if (uvs != null) |
|||
uvsNotNull = true; |
|||
if (uvs.Length > 0) |
|||
uvsData = true; |
|||
} |
|||
|
|||
if (uvsNotNull && uvsData) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool UVRangeTest(MeshFilter[] meshFilters) |
|||
{ |
|||
var failedUvs = new List<Vector2>(); |
|||
var failedMeshes = new Dictionary<MeshFilter, decimal>(); |
|||
decimal uvPassPercentage = 0; |
|||
|
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var uvs = mesh.sharedMesh.uv; |
|||
var uvPassed = 0; |
|||
var uvTotal = uvs.Length; |
|||
|
|||
foreach (var uv in uvs) |
|||
{ |
|||
if (uv.x < 0 || uv.x > 1 && uv.y < 0 || uv.y > 1) |
|||
{ |
|||
failedUvs.Add(uv); |
|||
} |
|||
else |
|||
{ |
|||
uvPassed += 1; |
|||
} |
|||
} |
|||
|
|||
uvPassPercentage = (decimal)uvPassed / uvTotal; |
|||
uvPassPercentage = uvPassPercentage * 100; |
|||
|
|||
failedMeshes.Add(mesh, uvPassPercentage); |
|||
|
|||
if (uvPassPercentage < 20) |
|||
{ |
|||
Debug.Log(string.Format("{0} failed UV range test with a percentage of {1}", mesh.name, uvPassPercentage)); |
|||
} |
|||
} |
|||
|
|||
if (uvPassPercentage < 20) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public bool UVPositiveTest(MeshFilter[] meshFilters) |
|||
{ |
|||
var failedUvs = new List<Vector2>(); |
|||
var failedMeshes = new Dictionary<MeshFilter, decimal>(); |
|||
decimal uvPassPercentage = 0; |
|||
|
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var uvs = mesh.sharedMesh.uv; |
|||
var uvPassed = 0; |
|||
var uvTotal = uvs.Length; |
|||
|
|||
foreach (var uv in uvs) |
|||
{ |
|||
if (uv.x < 0 || uv.y < 0) |
|||
{ |
|||
failedUvs.Add(uv); |
|||
} |
|||
else |
|||
{ |
|||
uvPassed += 1; |
|||
} |
|||
} |
|||
|
|||
uvPassPercentage = (decimal)uvPassed / uvTotal; |
|||
uvPassPercentage = uvPassPercentage * 100; |
|||
|
|||
failedMeshes.Add(mesh, uvPassPercentage); |
|||
} |
|||
|
|||
if (failedMeshes.Count > 0) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public bool MeshInvertedNormalsTest(MeshFilter[] meshFilters, out List<string> failedMeshFilters) |
|||
{ |
|||
failedMeshFilters = new List<string>(); |
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var normals = mesh.sharedMesh.normals; |
|||
|
|||
foreach (var norm in normals) |
|||
{ |
|||
if (norm.normalized.magnitude < 0) |
|||
{ |
|||
failedMeshFilters.Add(mesh.name); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (failedMeshFilters.Count == 0) |
|||
return true; |
|||
else if (failedMeshFilters.Count > 0) |
|||
return false; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool MeshOpenFaceTest(MeshFilter[] meshFilters, out List<string> failedMesh, bool drawMesh = false, bool drawEdges = false) |
|||
{ |
|||
var edges = new List<MeshEdge>(); |
|||
failedMesh = new List<string>(); |
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
edges = GetMeshEdges(mesh.sharedMesh, drawMesh).DetectOpenEdges(drawEdges); |
|||
|
|||
if (edges.Count != 0) |
|||
{ |
|||
failedMesh.Add(mesh.name); |
|||
} |
|||
} |
|||
|
|||
if (failedMesh.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool MeshDetectUnWeldedVerts(MeshFilter[] meshFilters, out List<string> failedMesh) |
|||
{ |
|||
failedMesh = new List<string>(); |
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var verts = DetectUnweldedVerts(mesh.sharedMesh, 0.0001f); |
|||
if (verts.Count != 0) |
|||
{ |
|||
failedMesh.Add(mesh.name); |
|||
} |
|||
} |
|||
|
|||
if (failedMesh.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool MeshDetectSpikes(MeshFilter[] meshFilters, bool DebugDraw) |
|||
{ |
|||
var failedMesh = new List<string>(); |
|||
foreach (var mesh in meshFilters) |
|||
{ |
|||
var edges = GetMeshEdges(mesh.sharedMesh, false).DetectMeshSpikes(DebugDraw); |
|||
if (edges.Count != 0) |
|||
failedMesh.Add(mesh.name); |
|||
} |
|||
|
|||
if (failedMesh.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool AssetTexelDensity(MeshFilter[] meshFilter, MeshRenderer[] meshRenderer, out List<GameObject> failedMeshes, int scale = 4, int targetResolution = 2048) |
|||
{ |
|||
List<TexelDensity> texelDensity = new List<TexelDensity>(); |
|||
failedMeshes = new List<GameObject>(); |
|||
for (int i = 0; i < meshRenderer.Length; i++) |
|||
{ |
|||
texelDensity = GetTexelDensity(meshFilter[i], meshRenderer[i], scale, targetResolution); |
|||
|
|||
foreach (var td in texelDensity) |
|||
{ |
|||
if (td.texelDensity != targetResolution / 100) |
|||
failedMeshes.Add(meshFilter[i].gameObject); |
|||
|
|||
if (td.tilingValue <= scale) |
|||
if (!failedMeshes.Contains(meshFilter[i].gameObject)) |
|||
failedMeshes.Add(meshFilter[i].gameObject); |
|||
} |
|||
} |
|||
|
|||
if (failedMeshes.Count != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public bool CharacterRequiredBones(Animator animator, out Dictionary<HumanBone, bool> failed) |
|||
{ |
|||
var result = AvatarRequiredBones(animator); |
|||
failed = new Dictionary<HumanBone, bool>(); |
|||
|
|||
for (int i = 0; i < result.Count; i++) |
|||
{ |
|||
var bone = result.ElementAt(i); |
|||
var boneKey = bone.Key; |
|||
var boneValue = bone.Value; |
|||
|
|||
if (boneValue != true) |
|||
failed.Add(boneKey, boneValue); |
|||
} |
|||
|
|||
if (failed.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool CharacterPoseData(GameObject gameObject, out List<GameObject> failedGameObjects) |
|||
{ |
|||
failedGameObjects = new List<GameObject>(); |
|||
|
|||
var componentsParent = gameObject.GetComponents<Transform>(); |
|||
var componentsChild = gameObject.GetComponentsInChildren<Transform>(); |
|||
|
|||
for (int p = 0; p < componentsParent.Length; p++) |
|||
{ |
|||
if (componentsParent[p].GetType() == typeof(Transform)) |
|||
{ |
|||
var pos = componentsParent[p].transform.position; |
|||
var rot = componentsParent[p].transform.rotation.eulerAngles; |
|||
|
|||
if (pos == null || rot == null) |
|||
{ |
|||
failedGameObjects.Add(componentsParent[p].gameObject); |
|||
} |
|||
} |
|||
} |
|||
|
|||
for (int c = 0; c < componentsChild.Length; c++) |
|||
{ |
|||
if (componentsChild[c].GetType() == typeof(Transform)) |
|||
{ |
|||
var pos = componentsChild[c].transform.position; |
|||
var rot = componentsChild[c].transform.rotation.eulerAngles; |
|||
|
|||
if (pos == null || rot == null) |
|||
{ |
|||
failedGameObjects.Add(componentsChild[c].gameObject); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (failedGameObjects.Count == 0) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool CharacterCreateNose(GameObject selection, Animator animator, SkinnedMeshRenderer skinnedMeshRenderer, bool drawRays = false) |
|||
{ |
|||
var model = AvatarCreateNose(selection, animator, skinnedMeshRenderer, drawRays); |
|||
var childCount = model.transform.childCount; |
|||
var nose = false; |
|||
var earRight = false; |
|||
var earLeft = false; |
|||
|
|||
for (int i = 0; i < childCount; i++) |
|||
{ |
|||
if (model.transform.GetChild(i).name == "head") |
|||
{ |
|||
var modelHead = model.transform.GetChild(i); |
|||
var headChildCount = modelHead.transform.childCount; |
|||
|
|||
for (int h = 0; h > headChildCount; h++) |
|||
{ |
|||
var childName = modelHead.transform.GetChild(h).name; |
|||
if (childName.Contains("nose")) |
|||
nose = true; |
|||
if (childName.Contains("earRight")) |
|||
earRight = true; |
|||
if (childName.Contains("earLeft")) |
|||
earLeft = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (nose && earRight && earLeft) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
|
|||
namespace UnityEngine.Perception.Content |
|||
{ |
|||
public static class GeomertryValidation |
|||
{ |
|||
public struct MeshEdge |
|||
{ |
|||
public Vector3 v1; |
|||
public Vector3 v2; |
|||
public MeshEdge(Vector3 v1, Vector3 v2) |
|||
{ |
|||
this.v1 = v1; |
|||
this.v2 = v2; |
|||
} |
|||
} |
|||
|
|||
public struct MeshTrianlge |
|||
{ |
|||
public MeshEdge e1; |
|||
public MeshEdge e2; |
|||
public MeshEdge e3; |
|||
public MeshTrianlge(MeshEdge e1, MeshEdge e2, MeshEdge e3) |
|||
{ |
|||
this.e1 = e1; |
|||
this.e2 = e2; |
|||
this.e3 = e3; |
|||
} |
|||
} |
|||
|
|||
public static List<MeshEdge> GetMeshEdges(Mesh mesh, bool drawMesh) |
|||
{ |
|||
List<MeshEdge> result = new List<MeshEdge>(); |
|||
|
|||
for (int i = 0; i < mesh.triangles.Length; i += 3) |
|||
{ |
|||
var v1 = mesh.vertices[mesh.triangles[i]]; |
|||
var v2 = mesh.vertices[mesh.triangles[i + 1]]; |
|||
var v3 = mesh.vertices[mesh.triangles[i + 2]]; |
|||
result.Add(new MeshEdge(v1, v2)); |
|||
result.Add(new MeshEdge(v2, v3)); |
|||
result.Add(new MeshEdge(v3, v1)); |
|||
|
|||
if (drawMesh) |
|||
{ |
|||
Debug.DrawLine(v1, v2, Color.green, 30f); |
|||
Debug.DrawLine(v1, v3, Color.green, 30f); |
|||
Debug.DrawLine(v2, v3, Color.green, 30f); |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public static List<MeshTrianlge> CreateTrianlges(Mesh mesh, bool drawMesh) |
|||
{ |
|||
List<MeshTrianlge> result = new List<MeshTrianlge>(); |
|||
|
|||
for (int i = 0; i < mesh.triangles.Length; i += 3) |
|||
{ |
|||
var v1 = mesh.vertices[mesh.triangles[i]]; |
|||
var v2 = mesh.vertices[mesh.triangles[i + 1]]; |
|||
var v3 = mesh.vertices[mesh.triangles[i + 2]]; |
|||
|
|||
result.Add(new MeshTrianlge(new MeshEdge(v1, v2), new MeshEdge(v2, v3), new MeshEdge(v3, v1))); |
|||
|
|||
if (drawMesh) |
|||
{ |
|||
Debug.DrawLine(v1, v2, Color.green, 30f); |
|||
Debug.DrawLine(v1, v3, Color.green, 30f); |
|||
Debug.DrawLine(v2, v3, Color.green, 30f); |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public static List<MeshEdge> DetectOpenEdges(this List<MeshEdge> Edges, bool drawMesh) |
|||
{ |
|||
List<MeshEdge> result = Edges; |
|||
for (int i = result.Count - 1; i > 0; i--) |
|||
{ |
|||
for (int n = i - 1; n >= 0; n--) |
|||
{ |
|||
if (result[i].v1 == result[n].v2 && result[i].v2 == result[n].v1) |
|||
{ |
|||
// shared edge so remove both
|
|||
result.RemoveAt(i); |
|||
result.RemoveAt(n); |
|||
i--; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (drawMesh) |
|||
{ |
|||
if (result.Count > 0) |
|||
{ |
|||
for (int e = 0; e < result.Count; e++) |
|||
{ |
|||
Debug.DrawLine(result[e].v1, result[e].v2, Color.blue, 30f); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static List<MeshEdge> SortEdges(this List<MeshEdge> Edges) |
|||
{ |
|||
List<MeshEdge> result = new List<MeshEdge>(Edges); |
|||
for (int i = 0; i < result.Count - 2; i++) |
|||
{ |
|||
MeshEdge e = result[i]; |
|||
for (int n = i + 1; n < result.Count; n++) |
|||
{ |
|||
MeshEdge a = result[n]; |
|||
if (e.v2 == a.v1) |
|||
{ |
|||
if (n == i + 1) |
|||
break; |
|||
result[n] = result[i + 1]; |
|||
result[i + 1] = a; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public static List<Vector3> DetectUnweldedVerts(Mesh mesh, float distance) |
|||
{ |
|||
List<Vector3> result = mesh.vertices.ToList(); |
|||
|
|||
for (int i = result.Count - 1; i > 0; i--) |
|||
{ |
|||
for (int p = i - 1; p >= 0; p--) |
|||
{ |
|||
var m = mesh.vertices[i]; |
|||
var a = mesh.vertices[p]; |
|||
var factor = Vector3.Distance(m, a); |
|||
if (factor > distance || factor != 0) |
|||
{ |
|||
result.Remove(m); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static List<MeshEdge> DetectMeshSpikes(this List<MeshEdge> Edges, bool DebugDraw) |
|||
{ |
|||
/// TODO: Doesn't support simple object i.e. a cube because cube all edges z's outside of the bounds
|
|||
/// Can possibly do this by checking each triangle and the angles within to see if it contains a 90 degree
|
|||
|
|||
List<MeshEdge> result = Edges; |
|||
List<MeshEdge> spikes = new List<MeshEdge>(); |
|||
|
|||
for (int i = 0; i < result.Count; i++) |
|||
{ |
|||
var v1 = result[i].v1; |
|||
var v2 = result[i].v2; |
|||
|
|||
var zDiff = v1.z - v2.z; |
|||
var yDiff = v1.y - v2.y; |
|||
var xDiff = v1.x - v2.x; |
|||
|
|||
if (zDiff > 0.0500 || zDiff < -0.0500) |
|||
{ |
|||
spikes.Add(result[i]); |
|||
if(DebugDraw) |
|||
Debug.DrawLine(v1, v2, Color.red, 30f); |
|||
} |
|||
} |
|||
|
|||
return spikes; |
|||
} |
|||
} |
|||
|
|||
public static class TextureValidation |
|||
{ |
|||
public struct TexelDensity |
|||
{ |
|||
public double texelDensity; |
|||
public double tilingValue; |
|||
|
|||
public TexelDensity(double texelDensity, double tilingValue) |
|||
{ |
|||
this.texelDensity = texelDensity; |
|||
this.tilingValue = tilingValue; |
|||
} |
|||
} |
|||
|
|||
public static List<TexelDensity> GetTexelDensity(MeshFilter meshFilter, MeshRenderer meshRenderer, float scale, int targetResolution) |
|||
{ |
|||
// Correct TD for an object is meter x pixel per meter / texture Resolution = tiling value
|
|||
// Find TD is pixel / 100cm = TD
|
|||
List <TexelDensity> result = new List<TexelDensity>(); |
|||
List<Vector2> uvs = meshFilter.sharedMesh.uv.ToList(); |
|||
|
|||
var assetWorldSize = meshRenderer.bounds.size; |
|||
|
|||
// Place a texture, although might need to just make the texture 2048
|
|||
Texture2D testTexture = new Texture2D(targetResolution, targetResolution); |
|||
testTexture.wrapMode = TextureWrapMode.Repeat; |
|||
testTexture.filterMode = FilterMode.Bilinear; |
|||
testTexture.anisoLevel = 1; |
|||
|
|||
AssetDatabase.CreateAsset(testTexture, "Assets/testTexture.renderTexture"); |
|||
var path = AssetDatabase.GetAssetPath(testTexture); |
|||
var test = (Texture2D)AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)); |
|||
|
|||
if(meshRenderer.sharedMaterial != null) |
|||
meshRenderer.sharedMaterial.mainTexture = test; |
|||
|
|||
int textureheight = meshRenderer.sharedMaterial.mainTexture.height; |
|||
int texturewidth = meshRenderer.sharedMaterial.mainTexture.width; |
|||
Vector2 uvSize = new Vector2(); |
|||
float uvScale = 0; |
|||
|
|||
// Scale UV's to scale input
|
|||
for (int i = 0; i < uvs.Count; i++) |
|||
{ |
|||
// UVs support a texel density of 2048x2048px to 4'0''x4'0''
|
|||
uvs[i] = new Vector2(uvs[i].x * scale, uvs[i].y * scale); |
|||
if (i == 0) |
|||
{ |
|||
uvSize = uvs[i]; |
|||
} |
|||
else |
|||
{ |
|||
if (uvs[i].x > uvs[i - 1].x) |
|||
uvSize.x = uvs[i].x; |
|||
if (uvs[i].y > uvs[i - 1].y) |
|||
uvSize.y = uvs[i].y; |
|||
} |
|||
} |
|||
|
|||
// Calculate tile map to see if it is supported as whole number
|
|||
// Calculate TD and check to make sure it is supported version of 20.48 or other rez
|
|||
uvScale = uvSize.x; |
|||
double texelDensity = textureheight / 100.0; |
|||
double tilingValue = uvScale * (texelDensity * 100) / textureheight; |
|||
|
|||
result.Add(new TexelDensity(texelDensity, tilingValue)); |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
public static class CharacterValidation |
|||
{ |
|||
public static string[] RequiredBones = |
|||
{ |
|||
"Head", |
|||
"Hips", |
|||
"Spine", |
|||
"LeftUpperArm", |
|||
"LeftLowerArm", |
|||
"LeftHand", |
|||
"RightUpperArm", |
|||
"RightLowerArm", |
|||
"RightHand", |
|||
"LeftUpperLeg", |
|||
"LeftLowerLeg", |
|||
"LeftFoot", |
|||
"RightUpperLeg", |
|||
"RightLowerLeg", |
|||
"RightFoot", |
|||
}; |
|||
|
|||
public static Dictionary<HumanBone, bool> AvatarRequiredBones(Animator animator) |
|||
{ |
|||
var result = new Dictionary<HumanBone, bool>(); |
|||
var human = animator.avatar.humanDescription.human; |
|||
var totalBones = 0; |
|||
|
|||
for(int h = 0; h < human.Length; h++) |
|||
{ |
|||
for (int b = 0; b < RequiredBones.Length; b++) |
|||
{ |
|||
if(human[h].humanName == RequiredBones[b]) |
|||
{ |
|||
var bone = new HumanBone(); |
|||
|
|||
if (human[h].boneName != null) |
|||
{ |
|||
bone.boneName = human[h].boneName; |
|||
totalBones = totalBones = +1; |
|||
result.Add(bone, true); |
|||
} |
|||
else |
|||
{ |
|||
result.Add(bone, false); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static GameObject AvatarCreateNose (GameObject selection, Animator animator, SkinnedMeshRenderer skinnedMeshRenderer, bool drawRays = false) |
|||
{ |
|||
var human = animator.avatar.humanDescription.human; |
|||
var skeleton = animator.avatar.humanDescription.skeleton; |
|||
var verticies = skinnedMeshRenderer.sharedMesh.vertices; |
|||
|
|||
var head = animator.GetBoneTransform(HumanBodyBones.Head); |
|||
var leftEye = animator.GetBoneTransform(HumanBodyBones.RightEye); |
|||
var rightEye = animator.GetBoneTransform(HumanBodyBones.LeftEye); |
|||
var faceCenter = Vector3.zero; |
|||
var earCenter = Vector3.zero; |
|||
var nosePos = Vector3.zero; |
|||
var earRightPos = Vector3.zero; |
|||
var earLeftPos = Vector3.zero; |
|||
var distanceCheck = 1f; |
|||
|
|||
var eyeDistance = Vector3.Distance(leftEye.position, rightEye.position); |
|||
var directionLeft = Quaternion.AngleAxis(-45, -leftEye.right) * -leftEye.up; |
|||
var directionRight = Quaternion.AngleAxis(-45, rightEye.right) * -rightEye.up; |
|||
|
|||
var rayHead = new Ray(); |
|||
var rayLeftEye = new Ray(); |
|||
var rayRightEye = new Ray(); |
|||
var noseRayFor = new Ray(); |
|||
var rayNoseBack = new Ray(); |
|||
var rayEarLeft = new Ray(); |
|||
var rayEarRight = new Ray(); |
|||
|
|||
var foundRightEar = false; |
|||
var foundLeftEar = false; |
|||
|
|||
rayLeftEye.origin = leftEye.position; |
|||
rayLeftEye.direction = directionLeft * eyeDistance; |
|||
|
|||
rayRightEye.origin = rightEye.position; |
|||
rayRightEye.direction = directionRight * eyeDistance; |
|||
|
|||
for (double i = 0; i < distanceCheck; i += 0.01) |
|||
{ |
|||
var point = Convert.ToSingle(i); |
|||
var pointR = rayRightEye.GetPoint(point); |
|||
var pointL = rayLeftEye.GetPoint(point); |
|||
|
|||
var distanceX = Math.Abs(pointR.x - pointL.x); |
|||
var distanceY = Math.Abs(pointR.y - pointL.y); |
|||
|
|||
if (distanceX < 0.01 && distanceY < 0.01 ) |
|||
{ |
|||
faceCenter = pointR; |
|||
} |
|||
} |
|||
|
|||
rayHead.origin = head.position; |
|||
rayHead.direction = Vector3.up * distanceCheck; |
|||
|
|||
noseRayFor.origin = faceCenter; |
|||
noseRayFor.direction = Vector3.forward * distanceCheck; |
|||
|
|||
rayNoseBack.origin = faceCenter; |
|||
rayNoseBack.direction = Vector3.back * distanceCheck; |
|||
|
|||
for (double i = 0; i < distanceCheck; i += 0.01) |
|||
{ |
|||
var point = Convert.ToSingle(i); |
|||
var pointH = rayHead.GetPoint(point); |
|||
var pointF = rayNoseBack.GetPoint(point); |
|||
|
|||
var distanceZ = Math.Abs(pointH.z - pointF.z); |
|||
|
|||
if (distanceZ < 0.01) |
|||
{ |
|||
earCenter = pointF; |
|||
} |
|||
} |
|||
|
|||
for (int v = 0; v < verticies.Length; v++) |
|||
{ |
|||
for (double c = eyeDistance / 2; c < distanceCheck; c += 0.001) |
|||
{ |
|||
var point = Convert.ToSingle(c); |
|||
var pointNoseRay = noseRayFor.GetPoint(point); |
|||
var pointVert = verticies[v]; |
|||
var distHeadZ = Math.Abs(pointNoseRay.z - pointVert.z); |
|||
var distHeadX = Math.Abs(pointNoseRay.x - pointVert.x); |
|||
|
|||
if (distHeadZ < 0.0001 && distHeadX < 0.001) |
|||
{ |
|||
nosePos = pointNoseRay; |
|||
Debug.Log("Found Nose: " + nosePos); |
|||
} |
|||
|
|||
if(nosePos == Vector3.zero) |
|||
{ |
|||
if (distHeadZ < 0.001 && distHeadX < 0.001) |
|||
{ |
|||
nosePos = pointNoseRay; |
|||
Debug.Log("Found Nose: " + nosePos); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
rayEarRight.origin = earCenter; |
|||
rayEarRight.direction = Vector3.right * distanceCheck; |
|||
|
|||
rayEarLeft.origin = earCenter; |
|||
rayEarLeft.direction = Vector3.left * distanceCheck; |
|||
|
|||
for (int v = 0; v < verticies.Length; v++) |
|||
{ |
|||
for (double c = eyeDistance / 2; c < distanceCheck; c += 0.001) |
|||
{ |
|||
var point = Convert.ToSingle(c); |
|||
var pointEarRight = rayEarRight.GetPoint(point); |
|||
var pointEarLeft = rayEarLeft.GetPoint(point); |
|||
var pointVert = verticies[v]; |
|||
|
|||
var distEarRightY = Math.Abs(pointEarRight.y - pointVert.y); |
|||
var distEarRightX = Math.Abs(pointEarRight.x - pointVert.x); |
|||
|
|||
var distEarLeftY = Math.Abs(pointEarLeft.y - pointVert.y); |
|||
var distEarLeftX = Math.Abs(pointEarLeft.x - pointVert.x); |
|||
|
|||
if (distEarRightY < 0.001 && distEarRightX < 0.0001) |
|||
{ |
|||
earRightPos = pointEarRight; |
|||
foundRightEar = true; |
|||
} |
|||
|
|||
if (distEarLeftY < 0.001 && distEarLeftX < 0.0001) |
|||
{ |
|||
earLeftPos = pointEarLeft; |
|||
foundLeftEar = true; |
|||
} |
|||
|
|||
if (!foundRightEar) |
|||
{ |
|||
if (distEarRightY < 0.002 && distEarRightX < 0.001) |
|||
{ |
|||
earRightPos = pointEarRight; |
|||
} |
|||
} |
|||
|
|||
if (!foundLeftEar) |
|||
{ |
|||
if (distEarLeftY < 0.002 && distEarLeftX < 0.001) |
|||
{ |
|||
earLeftPos = pointEarLeft; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
var earLeftCheck = Vector3.Distance(earLeftPos, earCenter); |
|||
var earRightCheck = Vector3.Distance(earRightPos, earCenter); |
|||
var eyeCenterDistance = eyeDistance + 0.01f; |
|||
|
|||
if (earLeftCheck > eyeCenterDistance) |
|||
{ |
|||
earLeftPos.x = (-eyeDistance); |
|||
} |
|||
|
|||
if (earRightCheck > eyeCenterDistance) |
|||
{ |
|||
earRightPos.x = eyeDistance; |
|||
} |
|||
|
|||
if(drawRays) |
|||
{ |
|||
DebugDrawRays(30f, distanceCheck, rightEye, leftEye, head, rayRightEye, rayLeftEye, faceCenter, earCenter); |
|||
} |
|||
|
|||
return CreateNewCharacterPrefab(selection, nosePos, earRightPos, earLeftPos); |
|||
} |
|||
|
|||
public static void DebugDrawRays(float duration, float distanceCheck, Transform rightEye, Transform leftEye, Transform head,Ray rayRightEye, Ray rayLeftEye, Vector3 faceCenter, Vector3 earCenter) |
|||
{ |
|||
Debug.DrawLine(rightEye.position, leftEye.position, Color.magenta, duration); |
|||
Debug.DrawRay(rayLeftEye.origin, rayLeftEye.direction, Color.green, duration); |
|||
Debug.DrawRay(rayRightEye.origin, rayRightEye.direction, Color.blue, duration); |
|||
Debug.DrawRay(faceCenter, Vector3.forward * distanceCheck, Color.cyan, duration); |
|||
Debug.DrawRay(faceCenter, Vector3.back, Color.cyan, duration); |
|||
Debug.DrawRay(head.position, Vector3.up, Color.red, duration); |
|||
Debug.DrawRay(earCenter, Vector3.right, Color.blue, duration); |
|||
Debug.DrawRay(earCenter, Vector3.left, Color.green, duration); |
|||
} |
|||
|
|||
public static GameObject CreateNewCharacterPrefab(GameObject selection, Vector3 nosePosition, Vector3 earRightPosition, Vector3 earLeftPosition) |
|||
{ |
|||
var root = (GameObject)PrefabUtility.InstantiatePrefab(selection); |
|||
List<Transform> children = new List<Transform>(); |
|||
root.GetComponentsInChildren(children); |
|||
|
|||
foreach(var child in children) |
|||
{ |
|||
if (child.name == "head") |
|||
{ |
|||
if (nosePosition != Vector3.zero) |
|||
{ |
|||
var nose = new GameObject(); |
|||
nose.transform.position = nosePosition; |
|||
nose.name = "nose"; |
|||
nose.transform.SetParent(child); |
|||
} |
|||
|
|||
if (earRightPosition != Vector3.zero) |
|||
{ |
|||
var earRight = new GameObject(); |
|||
earRight.transform.position = earRightPosition; |
|||
earRight.name = "earRight"; |
|||
earRight.transform.SetParent(child); |
|||
} |
|||
|
|||
if (earLeftPosition != Vector3.zero) |
|||
{ |
|||
var earLeft = new GameObject(); |
|||
earLeft.transform.position = earLeftPosition; |
|||
earLeft.name = "earLeft"; |
|||
earLeft.transform.SetParent(child); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var model = PrefabUtility.SaveAsPrefabAsset(root, "Assets/" + root.name + ".prefab"); |
|||
|
|||
return model; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f5aa501b7f8ea7643a9e87db785ac439 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using NUnit.Framework; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception; |
|||
|
|||
namespace ValidationTests |
|||
{ |
|||
//[Ignore("Test Freezing right now")]
|
|||
public class EditorValidationTests : ContentTestBaseSetup |
|||
{ |
|||
[Test] |
|||
public void AssetsUVDataTests() |
|||
{ |
|||
Assert.IsTrue(tests.UVDataTest(meshFilters.ToArray()), "UV Data contains errors or is empty"); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetsUVRangeTests() |
|||
{ |
|||
var test = tests.UVRangeTest(meshFilters.ToArray()); |
|||
Assert.IsTrue(test, string.Format("UV(s) have range test has failed due to coordinates not in a range of 0 , 1")); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetsInvertedNormalsTests() |
|||
{ |
|||
var failedMeshfilters = new List<string>(); |
|||
var test = tests.MeshInvertedNormalsTest(meshFilters.ToArray(), out failedMeshfilters); |
|||
foreach (var mesh in failedMeshfilters) |
|||
{ |
|||
Debug.Log(string.Format("{0} mesh has inverted normals", mesh)); |
|||
} |
|||
Assert.IsTrue(test, "Normals are inverted"); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetsScaleTest() |
|||
{ |
|||
Assert.IsTrue(tests.TestScale(meshRenderers.ToArray()), "Asset scale is outside the bounds"); |
|||
} |
|||
|
|||
[Ignore("Test Freezing right now")] |
|||
[Test] |
|||
public void AssetMeshUnweldedVerts() |
|||
{ |
|||
var fail = new List<string>(); |
|||
tests.MeshDetectUnWeldedVerts(meshFilters.ToArray(), out fail); |
|||
|
|||
foreach (var mesh in fail) |
|||
{ |
|||
Debug.Log(string.Format("{0} mesh has un-welded vertices", mesh)); |
|||
} |
|||
|
|||
Assert.AreEqual(0, fail.Count, "Meshes have un-welded vertices!"); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetTransformsTest() |
|||
{ |
|||
var failedGameObjects = new List<GameObject>(); |
|||
foreach (var o in selectionLists) |
|||
{ |
|||
var transformsResult = tests.TransformTest(o, out failedGameObjects); |
|||
} |
|||
|
|||
foreach (var fail in failedGameObjects) |
|||
{ |
|||
var failedCount = fail.GetComponentsInParent<Component>(); |
|||
Debug.Log(string.Format("{0} Parent Transforms are not correct", fail.name)); |
|||
} |
|||
|
|||
Assert.AreEqual(0, failedGameObjects.Count, "GameObjects failed transforms test"); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetsParentComponentTest() |
|||
{ |
|||
var failedGameObjects = new List<GameObject>(); |
|||
foreach (var o in selectionLists) |
|||
{ |
|||
var transformsResult = tests.EmptyComponentsTest(o); |
|||
if (!transformsResult) |
|||
{ |
|||
failedGameObjects.Add(o); |
|||
} |
|||
} |
|||
|
|||
foreach (var fail in failedGameObjects) |
|||
{ |
|||
Debug.Log(string.Format("{0} Parent GameObject is not empty", fail.name)); |
|||
} |
|||
|
|||
Assert.AreEqual(0, failedGameObjects.Count, "Assets Parent GameObjects Contain more then Transform and Metadata components"); |
|||
} |
|||
|
|||
[Test] |
|||
public void AssetPivotPoint() |
|||
{ |
|||
var failed = new List<GameObject>(); |
|||
foreach (var o in selectionLists) |
|||
{ |
|||
var pivotPoints = tests.AssetCheckPivotPoint(o, out failed); |
|||
} |
|||
|
|||
if (failed.Count != 0) |
|||
{ |
|||
foreach (var o in failed) |
|||
{ |
|||
Debug.Log(string.Format("{0} Pivot point is not in the correct position!", o.name)); |
|||
} |
|||
} |
|||
|
|||
Assert.IsEmpty(failed, "Assets pivot point is not in the correct position!"); |
|||
} |
|||
|
|||
[Ignore("Test Freezing right now")] |
|||
[Test] |
|||
public void AssetTexelDensity() |
|||
{ |
|||
var scale = 4; |
|||
var targetResolution = 2048; |
|||
var failedMeshes = new List<GameObject>(); |
|||
|
|||
var texelDensity = tests.AssetTexelDensity(meshFilters.ToArray(), meshRenderers.ToArray(), out failedMeshes, scale, targetResolution); |
|||
|
|||
for (int i = 0; i < failedMeshes.Count; i++) |
|||
{ |
|||
Debug.Log(string.Format("{0}doesn't support 20.48 texel density!", failedMeshes[i].name)); |
|||
} |
|||
|
|||
Assert.IsTrue(texelDensity, "Assets currently don't support 2048 texel density"); |
|||
} |
|||
|
|||
[Ignore("Test Freezing right now")] |
|||
[Test] |
|||
public void AssetsOpenMeshTest() |
|||
{ |
|||
var failed = new List<string>(); |
|||
var openMesh = tests.MeshOpenFaceTest(meshFilters.ToArray(), out failed); |
|||
|
|||
if (failed.Count != 0) |
|||
{ |
|||
foreach (var mesh in failed) |
|||
{ |
|||
Debug.Log(string.Format("{0} has open faces in the mesh!", mesh)); |
|||
} |
|||
} |
|||
|
|||
Assert.IsTrue(openMesh, "Assets currently have holes in the Mesh"); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d83e5825e9a96484aa0918f2b6f69247 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue