Exemplo n.º 1
0
    /*
     *
     * Convert Meshes
     */
    public Dictionary <long, Mesh> ConvertMeshes(AMF amf, Dictionary <string, Material> mats, Dictionary <string, AMFShaderInfo> matHelpers, GameObject root)
    {
        //List<Mesh> meshList = new List<Mesh>();
        Dictionary <long, Mesh> meshCache = new Dictionary <long, Mesh>();
        float             meshComplete    = 0;
        float             totalMeshCount  = 0;
        List <GameObject> meshNodes       = new List <GameObject>();
        List <Transform>  nodes           = null;

        if (CreateSkinnedMeshes)
        {
            nodes           = CreateRigging(amf);
            nodes[0].parent = root.transform;
            Animator anim = root.AddComponent <Animator>();
            //Transform rigRoot=root.GetComponentInChildren<SkinnedMeshRenderer>().rootBone;
            if (copyAvatar)
            {
                //ctx.AddObjectToAsset(m_LastHumanDescriptionAvatarSource.name,m_LastHumanDescriptionAvatarSource);
                anim.avatar = m_LastHumanDescriptionAvatarSource;
            }
            else
            {
                //EditorUtility.DisplayProgressBar("Parsing "+ctx.assetPath,"Creating Avatar",(5f/5f));
                List <string>    reports = new List <string>();
                HumanDescription hd      = new HumanDescription();
                AvatarSetupTool.SkeletonBone[] skeletonBones;
                bool hasTranslationDOF;
                reports = AvatarSetupTool.SetupHumanSkeleton(nodes[0].parent.gameObject, ref hd.human, out skeletonBones, out hasTranslationDOF);
                hd.hasTranslationDoF = hasTranslationDOF;
                SkeletonBone[] sb = new SkeletonBone[skeletonBones.Length + 1];
                Array.Copy(Array.ConvertAll(skeletonBones, (p => (SkeletonBone)p)), sb, sb.Length - 1);
                sb[sb.Length - 1].name     = nodes[0].parent.name;
                sb[sb.Length - 1].position = nodes[0].parent.localPosition;
                sb[sb.Length - 1].rotation = nodes[0].parent.localRotation;
                sb[sb.Length - 1].scale    = nodes[0].parent.localScale;
                hd.skeleton = sb;
                Avatar a;
                if (rigType == RigType.Humanoid)
                {
                    a = AvatarBuilder.BuildHumanAvatar(nodes[0].parent.gameObject, hd);
                }
                else
                {
                    a = AvatarBuilder.BuildGenericAvatar(nodes[0].parent.gameObject, nodes[0].parent.name);
                }
                a.name = root.name + "Avatar";
                //ctx.AddObjectToAsset(a.name,a);
                anim.avatar = a;
            }
        }


        foreach (AMF_RegionInfo ri in amf.regionInfo)
        {
            totalMeshCount += ri.permutations.Count;
        }

        for (int ri = 0; ri < amf.regionInfo.Count; ri++)
        {
            GameObject riNode = new GameObject(amf.regionInfo[ri].name);
            GameObjectUtility.SetParentAndAlign(riNode, root);
            foreach (AMF_Permutations perm in amf.regionInfo[ri].permutations)
            {
                EditorUtility.DisplayProgressBar("Creating Meshes", perm.pName, (meshComplete / totalMeshCount));
                Mesh temp;
                if (createDuplicateInstances || !meshCache.ContainsKey(perm.vAddress))
                {
                    temp = ConvertInstanceToMesh(perm);
                    //we have to flip the normals due to the coordinate system translation
                    temp.FlipNormals();
                    temp.RecalculateNormals();
                    if (GenerateLightmapUVs)
                    {
                        EditorUtility.DisplayProgressBar("Generating Lightmap UVs", perm.pName, (meshComplete / totalMeshCount));
                        uvSettings.angleError = angleError;
                        uvSettings.areaError  = areaError;
                        uvSettings.hardAngle  = hardAngle;
                        uvSettings.packMargin = packMargin;
                        Unwrapping.GenerateSecondaryUVSet(temp, uvSettings);
                    }
                    meshCache.Add(perm.vAddress, temp);
                }
                else
                {
                    temp = meshCache[perm.vAddress];
                }
                GameObject meshNode = new GameObject(perm.pName);
                Matrix4x4  matr     = Matrix4x4.identity;
                if (!float.IsNaN(perm.mult))
                {
                    Matrix4x4 scalerM = new Matrix4x4();
                    scalerM.SetRow(0, new Vector4(100f * m_FileScaleFactor, 0));
                    scalerM.SetRow(1, new Vector4(0, 100f * m_FileScaleFactor));
                    scalerM.SetRow(2, new Vector4(0, 0, 100f * m_FileScaleFactor));
                    scalerM.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr.SetRow(0, new Vector4(perm.mult, 0));
                    matr.SetRow(1, new Vector4(0, perm.mult));
                    matr.SetRow(2, new Vector4(0, 0, perm.mult));
                    matr.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr *= perm.matrix4x4;
                    matr *= scalerM;
                    Matrix4x4 unityMatr = matr.Convert3DSMatrixToUnity();
                    meshNode.transform.localScale    = unityMatr.ExtractScale();
                    meshNode.transform.localRotation = unityMatr.GetRotation();
                    meshNode.transform.localPosition = unityMatr.ExtractPosition();
                }
                else
                {
                    meshNode.transform.localScale = new Vector3(m_FileScaleFactor, m_FileScaleFactor, m_FileScaleFactor);
                }

                //GameObjectUtility.SetParentAndAlign(meshNode,riNode);

                //meshNode.transform.localToWorldMatrix=matr;


                Renderer mr;
                if (temp.boneWeights.Length > 0 && CreateSkinnedMeshes)
                {
                    mr = meshNode.AddComponent <SkinnedMeshRenderer>();
                    meshNode.transform.localRotation = Quaternion.Euler(0, 90, 0);
                    Matrix4x4[] bindPoses = new Matrix4x4[nodes.Count];
                    for (int m = 0; m < bindPoses.Length; m++)
                    {
                        bindPoses[m] = nodes[m].worldToLocalMatrix * meshNode.transform.localToWorldMatrix;
                    }
                    temp.bindposes = bindPoses;
                    ((SkinnedMeshRenderer)mr).sharedMesh = temp;
                    ((SkinnedMeshRenderer)mr).bones      = nodes.ToArray();
                    ((SkinnedMeshRenderer)mr).rootBone   = nodes[0];
                }
                else
                {
                    MeshFilter mf = meshNode.AddComponent <MeshFilter>();
                    mf.sharedMesh = temp;
                    mr            = meshNode.AddComponent <MeshRenderer>();
                    if (RecenterPivots && !splitSubmeshes)
                    {
                        //for safety, lets guard this against splitting submeshes.
                        mf.RecenterPivot();
                    }
                }


                meshNode.transform.parent = riNode.transform;
                if (GenerateMeshCollidersOnClusters && amf.regionInfo[ri].name.Equals("Clusters"))
                {
                    MeshCollider mc = meshNode.AddComponent <MeshCollider>();
                    mc.sharedMesh = temp;
                }
                Material[]           materials = new Material[temp.subMeshCount];
                List <AMFShaderInfo> si        = new List <AMFShaderInfo>();
                for (int i = 0; i < materials.Length; i++)
                {
                    materials[i] = mats[amf.shaderInfos[perm.meshes[i].shaderIndex].sName];
                    si.Add(matHelpers[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]);
                    //si[i].SaveData(amf.shaderInfos[perm.meshes[i].shaderIndex]);
                }
                mr.sharedMaterials = materials;



                AMFMaterialHelper mh = meshNode.AddComponent <AMFMaterialHelper>();
                mh.shaderSettings = si;

                //mh.SaveData(amf.shaderInfos[perm.meshes[0].shaderIndex]);
                //Debug.LogFormat("Transform: Pos:{0} Rot:{1} Scale:{2}",perm.matrix4x4.ExtractPosition(),perm.matrix4x4.ExtractRotation(),perm.matrix4x4.ExtractScale());
                meshComplete++;
                meshNodes.Add(meshNode);
            }
        }

        //This is annoying to do this here, but we have to wait until after the mesh cache is fully populated before we start splitting submeshes out.
        if (splitSubmeshes)
        {
            meshCache.Clear();
            long fakeKey = 0;
            foreach (GameObject go in meshNodes)
            {
                MeshFilter mf = go.GetComponent <MeshFilter>();
                if (mf != null && mf.sharedMesh.subMeshCount > 1)
                {
                    Renderer r = go.GetComponent <MeshRenderer>();
                    for (int i = 0; i < mf.sharedMesh.subMeshCount; i++)
                    {
                        int        matIndex = Mathf.Min(i, r.sharedMaterials.Length);
                        GameObject tempGo   = new GameObject(go.name + "_" + r.sharedMaterials[matIndex].name);
                        MeshFilter tempMF   = tempGo.AddComponent <MeshFilter>();
                        tempMF.sharedMesh = mf.sharedMesh.ExtractSubmesh(i);

                        tempGo.AddComponent <MeshRenderer>().sharedMaterial = r.sharedMaterials[matIndex];
                        GameObjectUtility.SetParentAndAlign(tempGo, go);
                        if (RecenterPivots)
                        {
                            tempMF.RecenterPivot();
                        }
                        meshCache.Add(fakeKey, tempGo.GetComponent <MeshFilter>().sharedMesh);
                        fakeKey++;
                    }
                    DestroyImmediate(mf);
                    DestroyImmediate(r);
                }
                else
                {
                    if (RecenterPivots)
                    {
                        go.GetComponent <MeshFilter>().RecenterPivot();
                    }
                    meshCache.Add(fakeKey, go.GetComponent <MeshFilter>().sharedMesh);
                    fakeKey++;
                }
            }
        }

        return(meshCache);
    }