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 void rebuildMesh()
        {
            if (!skinMeshRend)
            {
                return;
            }
            var resMap = new ResourceMapper();
            //jsonMesh = new JsonMesh(new Mesh)

            var prefabRoot        = ExportUtility.getLinkedRootPrefabAsset(skinMeshRend.gameObject);
            var assetSkeletonRoot = JsonSkeletonBuilder.findSkeletonRoot(skinMeshRend);
            var mesh = skinMeshRend.sharedMesh;

            jsonMesh = new JsonMesh(new MeshStorageKey(mesh, prefabRoot, assetSkeletonRoot), 0, resMap);

            var boneNames = skinMeshRend.bones.Select((arg) => arg.name).ToList();

            origTransforms = skinMeshRend.bones.ToList();
            if (skeletonRoot)
            {
                debugTransforms = Utility.findNamedTransforms(boneNames, skeletonRoot);
            }
            else
            {
                debugTransforms = null;
            }
            //var foundTransforms = boneNames.Select((arg) => ;
        }
Exemple #3
0
		public JsonMesh(JsonMesh other){
			if (other == null)
				throw new System.ArgumentNullException();
			id = other.id;
			name = other.name;
			uniqueName = other.uniqueName;
			usageFlags = other.usageFlags;
			convexCollider = other.convexCollider;
			triangleCollider = other.triangleCollider;

			path = other.path;
			materials = other.materials.ToList();
			readable = other.readable;

			vertexCount = other.vertexCount;
			
			colors = other.colors.copyArray();
			verts = other.verts.copyArray();
			tangents = other.tangents.copyArray();
			
			uv0 = other.uv0.copyArray();
			uv1 = other.uv1.copyArray();
			uv2 = other.uv2.copyArray();
			uv3 = other.uv3.copyArray();
			uv4 = other.uv4.copyArray();
			uv5 = other.uv5.copyArray();
			uv6 = other.uv6.copyArray();
			uv7 = other.uv7.copyArray();
			
			boneWeights = other.boneWeights.ToList();
			boneIndexes = other.boneIndexes.ToList();
			
			defaultSkeletonId = other.defaultSkeletonId;
			
			defaultBoneNames = other.defaultBoneNames.ToList();
			
			defaultMeshNodeName = other.defaultMeshNodeName;
			defaultMeshNodePath = other.defaultMeshNodePath;
			defaultMeshNodeMatrix = other.defaultMeshNodeMatrix;
			
			blendShapeCount = other.blendShapeCount;
			blendShapes = other.blendShapes.Select((arg) => new JsonBlendShape(arg)).ToList();
			
			bindPoses = other.bindPoses.ToList();
			
			subMeshes = other.subMeshes.Select((arg) => new SubMesh(arg)).ToList();
			
			subMeshCount = other.subMeshCount;
		}
        //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 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);
        }