예제 #1
0
        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);
        }
예제 #2
0
        //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);
        }
예제 #3
0
        public ResId getDefaultSkeletonId(MeshStorageKey key)
        {
            var skel = getDefaultSkeleton(key);

            if (skel == null)
            {
                return(ResId.invalid);               //ExportUtility.invalidId;
            }
            return(skel.id);
        }
예제 #4
0
        public List <string> getDefaultBoneNames(MeshStorageKey key)
        {
            var tmp = meshDefaultSkeletonData.getValOrDefault(
                key, null);

            if (tmp == null)
            {
                return(new List <string>());
            }
            return(tmp.defaultBoneNames.ToList());
        }
예제 #5
0
        public string getDefaultMeshNodePath(MeshStorageKey key)
        {
            var tmp = meshDefaultSkeletonData.getValOrDefault(
                key, null);

            if ((tmp != null) && (tmp.meshNodeTransform))
            {
                return(tmp.meshNodeTransform.getScenePath(tmp.defaultRoot));
            }

            return("");
        }
예제 #6
0
        public string getDefaultMeshNodeName(MeshStorageKey key)
        {
            var tmp = meshDefaultSkeletonData.getValOrDefault(
                key, null);

            if ((tmp != null) && (tmp.meshNodeTransform))
            {
                return(tmp.meshNodeTransform.name);
            }

            return("");
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #10
0
 public MeshDefaultSkeletonData getDefaultSkeletonData(MeshStorageKey key)
 {
     return(meshDefaultSkeletonData.getValOrDefault(key, null));
 }
예제 #11
0
		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);
        }