JsonMesh makeJsonMesh(MeshStorageKey meshKey, ResId id) { var result = new JsonMesh(meshKey, id, this); if (!meshKey.skeletonRoot || !meshKey.prefab) { return(result); } if (!isSkeletalMesh(meshKey.mesh)) { return(result); } /* * Doing this in steps, as it is possible to have root transform issue and then somehow no bindpose issues. * I mean, miracles can happen, right? */ result = fixSkinMeshRootBoneTransform(meshKey, result); //Currently disabled //result = fixSkinMeshPosedBones(meshKey, result); return(result); }
//public ResId getOrRegMeshId(SkinnedMeshRenderer meshRend, Transform skeletonRoot){ public void tryRegisterMeshSkeleton(MeshStorageKey meshKey, SkinnedMeshRenderer meshRend, Transform skeletonRoot) { Sanity.nullCheck(meshKey.mesh, "mesh cannot be null"); //var meshKey = buildMeshKey(meshRend, true); //TODO - this needs to be moved into a subroutine of SkeletonRepository if (!meshDefaultSkeletonData.ContainsKey(meshKey)) { var rootTransform = skeletonRoot; //JsonSkeletonBuilder.findSkeletonRoot(meshRend); if (!rootTransform) { rootTransform = JsonSkeletonBuilder.findSkeletonRoot(meshRend); } if (!rootTransform) { throw new System.ArgumentException( string.Format("Could not find skeleton root transform for {0}", meshRend)); } var boneNames = meshRend.bones.Select((arg) => arg.name).ToList(); var meshNode = Utility.getSrcPrefabAssetObject(meshRend.gameObject.transform, false); var defaultData = new MeshDefaultSkeletonData(rootTransform, meshNode, boneNames); meshDefaultSkeletonData.Add(meshKey, defaultData); registerSkeleton(rootTransform, false); } //return getOrRegMeshId(meshKey, meshRend.gameObject, mesh); }
public ResId getDefaultSkeletonId(MeshStorageKey key) { var skel = getDefaultSkeleton(key); if (skel == null) { return(ResId.invalid); //ExportUtility.invalidId; } return(skel.id); }
public List <string> getDefaultBoneNames(MeshStorageKey key) { var tmp = meshDefaultSkeletonData.getValOrDefault( key, null); if (tmp == null) { return(new List <string>()); } return(tmp.defaultBoneNames.ToList()); }
public string getDefaultMeshNodePath(MeshStorageKey key) { var tmp = meshDefaultSkeletonData.getValOrDefault( key, null); if ((tmp != null) && (tmp.meshNodeTransform)) { return(tmp.meshNodeTransform.getScenePath(tmp.defaultRoot)); } return(""); }
public string getDefaultMeshNodeName(MeshStorageKey key) { var tmp = meshDefaultSkeletonData.getValOrDefault( key, null); if ((tmp != null) && (tmp.meshNodeTransform)) { return(tmp.meshNodeTransform.name); } return(""); }
public Matrix4x4 getDefaultMeshNodeMatrix(MeshStorageKey key) { var tmp = meshDefaultSkeletonData.getValOrDefault( key, null); if ((tmp != null) && (tmp.meshNodeTransform)) { Utility.getRelativeMatrix(tmp.meshNodeTransform, tmp.defaultRoot); } return(Matrix4x4.identity); }
public JsonSkeleton getDefaultSkeleton(MeshStorageKey key) { var defaultData = getDefaultSkeletonData(key); if (defaultData == null) { return(null); } //var skel = jsonSkeletons.getValOrDefault(defaultData.defaultRoot, null); //var skel = skeletons.getValOrDefault(defaultData.defaultRoot, null); var skel = findSkeleton(defaultData.defaultRoot); return(skel); }
public ResId getOrRegMeshId(MeshStorageKey meshKey, GameObject obj, Mesh mesh) { if (!mesh) { return(ResId.invalid); } ResId result = meshes.getId(meshKey, true, null); if (meshMaterials.ContainsKey(mesh)) { return(result); } var r = obj.GetComponent <Renderer>(); if (r) { meshMaterials[mesh] = new List <Material>(r.sharedMaterials); } return(result); }
public MeshDefaultSkeletonData getDefaultSkeletonData(MeshStorageKey key) { return(meshDefaultSkeletonData.getValOrDefault(key, null)); }
public JsonMesh(MeshStorageKey meshKey, ResId id_, ResourceMapper resMap){ id = id_; usageFlags = meshKey.usageFlags; convexCollider = meshKey.usageFlags.HasFlag(MeshUsageFlags.ConvexCollider); triangleCollider = meshKey.usageFlags.HasFlag(MeshUsageFlags.TriangleCollider); var mesh = meshKey.mesh; if (mesh == null) { Debug.LogError("Mesh is null, name!"); return; } name = mesh.name; var filePath = AssetDatabase.GetAssetPath(mesh); resMap.registerAssetPath(filePath); path = filePath; uniqueName = resMap.createUniqueAssetName(filePath, name, meshKey.getMeshAssetSuffix()); var foundMaterials = resMap.findMeshMaterials(mesh); if (foundMaterials != null){ foreach(var cur in foundMaterials){ materials.Add(resMap.getMaterialId(cur)); } } #if !UNITY_EDITOR readable = mesh.isReadable; if (!readable){ Debug.LogErrorFormat(string.Format("Mesh {0} is not marked as readable. Cannot proceed", name); return; } #endif vertexCount = mesh.vertexCount; if (vertexCount <= 0) return; colors = mesh.colors32.toByteArray(); verts = mesh.vertices.toFloatArray(); normals = mesh.normals.toFloatArray(); tangents = mesh.tangents.toFloatArray(); uv0 = mesh.uv.toFloatArray(); uv1 = mesh.uv2.toFloatArray(); uv2 = mesh.uv3.toFloatArray(); uv3 = mesh.uv4.toFloatArray(); uv4 = mesh.uv5.toFloatArray(); uv5 = mesh.uv6.toFloatArray(); uv6 = mesh.uv7.toFloatArray(); uv7 = mesh.uv8.toFloatArray(); subMeshCount = mesh.subMeshCount; for(int i = 0; i < subMeshCount; i++){ var subMesh = new SubMesh(); subMesh.triangles = Utility.copyArray(mesh.GetTriangles(i)); subMeshes.Add(subMesh); } boneWeights.Clear(); boneIndexes.Clear(); defaultSkeletonId = resMap.skelRegistry.getDefaultSkeletonId(meshKey); defaultBoneNames = resMap.skelRegistry.getDefaultBoneNames(meshKey); defaultMeshNodeName = resMap.skelRegistry.getDefaultMeshNodeName(meshKey); defaultMeshNodePath = resMap.skelRegistry.getDefaultMeshNodePath(meshKey); defaultMeshNodeMatrix = resMap.skelRegistry.getDefaultMeshNodeMatrix(meshKey); var srcWeights = mesh.boneWeights; if ((srcWeights != null) && (srcWeights.Length > 0)){ foreach(var cur in srcWeights){ boneIndexes.Add(cur.boneIndex0); boneIndexes.Add(cur.boneIndex1); boneIndexes.Add(cur.boneIndex2); boneIndexes.Add(cur.boneIndex3); boneWeights.Add(cur.weight0); boneWeights.Add(cur.weight1); boneWeights.Add(cur.weight2); boneWeights.Add(cur.weight3); } } blendShapeCount = mesh.blendShapeCount; blendShapes.Clear(); for(int i = 0; i < blendShapeCount; i++){ blendShapes.Add(new JsonBlendShape(mesh, i)); } bindPoses = mesh.bindposes.ToList(); }
//Looks like I can't move this out of here for now... JsonMesh fixSkinMeshRootBoneTransform(MeshStorageKey meshKey, JsonMesh srcMesh) { //return srcMesh; //let's check if we even NEED transformation. //Root bool largeRootTransformFound = false; { var desired = Matrix4x4.identity; var current = meshKey.skeletonRoot.localToWorldMatrix; var maxRootDiff = SkeletalMeshTools.getMaxDifference(desired, current); if (maxRootDiff > SkeletalMeshTools.matrixEpsilon) { Debug.LogFormat( string.Format("Large root matrix transform difference foune on mesh {0}, mesh will be transformed to accomodate." + "\ncurrent:\n{1}\ndesired:\n{2}\n", meshKey.mesh.name, current, desired)); largeRootTransformFound = true; } } if (!largeRootTransformFound) { return(srcMesh); } /* * We're now bringing skleletal mesh into rootSpace. */ var srcRootTransform = meshKey.prefab.transform.localToWorldMatrix; var srcRootInvTransform = meshKey.prefab.transform.worldToLocalMatrix; /* * Aw, damn it. Sksleton root is not going to cut it. We need mesh node itself. * * So, in unity it is, by default: (Right to left notation) * ResultTransform = targetBoneTransform * bindPose * meshTransform. */ var skelData = skelRegistry.getDefaultSkeletonData(meshKey); if (skelData == null) { throw new System.ArgumentException( string.Format("Coudl not locate default skeleton data for {0}", meshKey)); } if (!skelData.meshNodeTransform) { throw new System.ArgumentException( string.Format("mesh node transform is not set for {0}", meshKey) ); } var nodeMatrix = skelData.meshNodeTransform.localToWorldMatrix; var nodeInvMatrix = skelData.meshNodeTransform.worldToLocalMatrix; //var relativeMatrix = Utility.getRelativeMatrix(skelData.meshNodeTransform, meshKey.prefab.transform); var transformMatrix = srcRootInvTransform * nodeMatrix; var newMesh = new JsonMesh(srcMesh); newMesh.transformMeshWith(transformMatrix); var meshMatrix = Utility.getRelativeMatrix(skelData.meshNodeTransform, meshKey.prefab.transform); var meshInvMatrix = Utility.getRelativeInverseMatrix(skelData.meshNodeTransform, meshKey.prefab.transform); newMesh.processBindPoses((bindPose, index) => { /* * Givent that i'm getting error that's squarely factor of 10 while bones themselves have scale factor of 100 * (thanks, fbx exporter), it means I failed to accomodate for removal of mesh transform. Let's see... */ var newTransform = meshInvMatrix * bindPose; Debug.LogFormat("Converting bindpose {0}:\noriginal:\n{1}\nnew:\n{2}\nmesh:\n{3}\nmeshInv:\n{4}\nroot:\n{5}\nrootInv:\n{6}", index, bindPose, newTransform, meshMatrix, meshInvMatrix, srcRootTransform, srcRootInvTransform); return(newTransform); }); return(newMesh); }
public ResId findMeshId(Mesh obj, MeshUsageFlags useFlags) { var key = new MeshStorageKey(obj, useFlags); return(meshes.getId(key, false)); }
public bool Equals(MeshStorageKey other) { return((mesh == other.mesh) && (prefab == other.prefab) && (skeletonRoot == other.skeletonRoot)); }
public static readonly float matrixEpsilon = 0.00001f; //I'll consider matrices equivalent if this is below this threshold public static JsonMesh fixSkinMeshPosedBones(MeshStorageKey meshKey, JsonMesh srcMesh) { var result = srcMesh; var boneTransforms = Utility.findNamedTransforms(result.defaultBoneNames, meshKey.skeletonRoot); for (int i = 0; i < boneTransforms.Count; i++) { if (!boneTransforms[i]) { Debug.LogWarningFormat( string.Format("Could not locate bone {0}({1}) on mesh {2}", result.defaultBoneNames[i], i, meshKey.mesh) ); } } var rootNode = meshKey.prefab.transform; bool largeBoneTransformFound = false; { var srcRootTransform = meshKey.skeletonRoot.localToWorldMatrix; //var srcRootInvTransform = meshKey.skeletonRoot.worldToLocalMatrix; for (int boneIndex = 0; boneIndex < boneTransforms.Count; boneIndex++) { var curBone = boneTransforms[boneIndex]; var curBoneMatrix = Utility.getRelativeMatrix(curBone, rootNode); var curBoneInvMatrix = Utility.getRelativeInverseMatrix(curBone, rootNode); var bindPose = srcMesh.bindPoses[boneIndex]; Debug.LogFormat("curBone: {0}({1})\nmatrix:\n{2}\ninvMatrix:\n{3}\nbindPose:\n{4}\ninvBindPose:\n{5}\nroot:\n{6}\ninvRoot:\n{7}\n", boneIndex, curBone.name, curBoneMatrix, curBoneInvMatrix, bindPose, bindPose.inverse, srcRootTransform, srcRootTransform.inverse); /* * var curBone = Utility.getRelativeMatrix(boneTransforms[boneIndex], ; * var inverseMatrix = curBone.worldToLocalMatrix * srcRootTransform; * var bindPose = srcMesh.bindPoses[boneIndex];//meshKey.mesh.bindposes[i]; ///NOPE. We're done tweaking the mesh at this point. * var diff = getMaxDifference(inverseMatrix, bindPose); * Debug.LogFormat("index:{0}({1})\ninverseMatrix:\n{2}\nbindPose:\n{3}\nboneMatrix:\n{4}\nsrcRoot:\n{5}\ndiff: {6}\nepsilon: {7}", * boneIndex, curBone.name, inverseMatrix, bindPose, curBone.worldToLocalMatrix, srcRootTransform, diff, matrixEpsilon); */ var curPose = bindPose; var desiredPose = curBoneInvMatrix; var diff = getMaxDifference(curPose, desiredPose); Debug.LogFormat("bindPose:\n{0}\ndesiredPose:\n{1}\ndiff: {2}; epsilon: {3}\n", curPose, desiredPose, diff, matrixEpsilon); if (diff > matrixEpsilon) { largeBoneTransformFound = true; Debug.LogFormat("Large transform found"); //break; } } } if (!largeBoneTransformFound) { return(result); } else { Debug.LogFormat( string.Format("Large transform difference found on mesh {0}, mesh will be transformed to accomodate", meshKey.mesh.name)); } return(result); //disable it for now. //Oooh boy. Here it comes. The transformation. /* * The fact the mesh has both prefab and skeleton root specified indicats that it is skeletal. * * To accomodate for unreal approach to skinning, we now need to transform it into root space of our prefab. */ var transformed = new JsonMesh(result); var transformMatrices = new List <Matrix4x4>(); var rootTransform = meshKey.skeletonRoot.transform.localToWorldMatrix; var invRootTransform = meshKey.skeletonRoot.transform.worldToLocalMatrix; var oldBindPoses = meshKey.mesh.bindposes; var rootParentTransform = Matrix4x4.identity; var rootParentInvTransform = Matrix4x4.identity; if (meshKey.skeletonRoot.parent) { var rootParent = meshKey.skeletonRoot.parent; rootParentTransform = rootParent.localToWorldMatrix; rootParentInvTransform = rootParent.worldToLocalMatrix; } for (int boneIndex = 0; boneIndex < transformed.bindPoses.Count; boneIndex++) { var newTransformMatrix = Matrix4x4.identity; var curBone = boneTransforms[boneIndex]; if (curBone) { newTransformMatrix = rootParentInvTransform * curBone.localToWorldMatrix * srcMesh.bindPoses[boneIndex]; //meshKey.mesh.bindposes[boneIndex]; //invRootTransform * curBone.localToWorldMatrix * meshKey.mesh.bindposes[boneIndex]; } transformMatrices.Add(newTransformMatrix); } transformed.transformSkeletalMesh(transformMatrices); transformed.setBindPosesFromTransforms(boneTransforms, meshKey.skeletonRoot); // return(transformed); }