Exemple #1
0
            public void Read(Reader reader)
            {
                offset = Pointer.Current(reader);

                off_0   = Pointer.Read(reader);
                off_geo = Pointer.Read(reader);
                geo     = Load.FromOffsetOrRead <GeometricObject>(reader, off_geo);
            }
Exemple #2
0
        public GameObject GetGameObject(out GameObject[] boneGaos, GeometricObject morphObject = null, float morphProgress = 0f)
        {
            GameObject parentGao = new GameObject(Offset.ToString());

            // Bones
            boneGaos = null;
            if (bones != null && bones.Length > 0)
            {
                GameObject rootBone = new GameObject("Root bone");
                boneGaos = new GameObject[] { rootBone };
                boneGaos[0].transform.SetParent(parentGao.transform);
                boneGaos[0].transform.localPosition = Vector3.zero;
                boneGaos[0].transform.localRotation = Quaternion.identity;
                boneGaos[0].transform.localScale    = Vector3.one;
                boneGaos = boneGaos.Concat(bones.Select(b => b.GetGameObject(parentGao))).ToArray();
            }

            // Morph
            Vector3[] mainVertices = vertices.Select(s => new Vector3(
                                                         s.x / 256f,
                                                         s.z / 256f,
                                                         s.y / 256f)).ToArray();
            Color[] mainColors = vertices.Select(s => new Color(
                                                     s.r / (float)0x80,
                                                     s.g / (float)0x80,
                                                     s.b / (float)0x80,
                                                     1f)).ToArray();
            if (morphProgress > 0f && morphObject != null && morphObject.vertices.Length == vertices.Length)
            {
                Vector3[] morphVertices = morphObject.vertices.Select(s => new Vector3(
                                                                          s.x / 256f,
                                                                          s.z / 256f,
                                                                          s.y / 256f)).ToArray();
                Color[] morphColors = morphObject.vertices.Select(s => new Color(
                                                                      s.r / (float)0x80,
                                                                      s.g / (float)0x80,
                                                                      s.b / (float)0x80,
                                                                      1f)).ToArray();
                for (int i = 0; i < vertices.Length; i++)
                {
                    mainVertices[i] = Vector3.Lerp(mainVertices[i], morphVertices[i], morphProgress);
                    mainColors[i]   = Color.Lerp(mainColors[i], morphColors[i], morphProgress);
                }
            }

            // First pass

            Dictionary <VisualMaterial, List <IPS1Polygon> > textured = new Dictionary <VisualMaterial, List <IPS1Polygon> >();
            List <IPS1Polygon> untextured = new List <IPS1Polygon>();

            for (int i = 0; i < triangleLists.Length; i++)
            {
                PolygonList polys = triangleLists[i];
                if (polys.polygons != null)
                {
                    foreach (IPS1Polygon p in polys.polygons)
                    {
                        if (p is QuadLOD && (p as QuadLOD).quads?.Length > 0)
                        {
                            Quad[] quads = (p as QuadLOD).quads;
                            foreach (Quad q in quads)
                            {
                                VisualMaterial b = q.Material;
                                if (b == null)
                                {
                                    untextured.Add(q);
                                }
                                else
                                {
                                    if (!textured.ContainsKey(b))
                                    {
                                        textured[b] = new List <IPS1Polygon>();
                                    }
                                    textured[b].Add(q);
                                }
                            }
                        }
                        else
                        {
                            VisualMaterial b = p.Material;
                            if (b == null)
                            {
                                untextured.Add(p);
                            }
                            else
                            {
                                if (!textured.ContainsKey(b))
                                {
                                    textured[b] = new List <IPS1Polygon>();
                                }
                                textured[b].Add(p);
                            }
                        }
                    }
                }
            }

            // Second pass
            VisualMaterial[] textures = textured.Keys.ToArray();
            for (int i = 0; i < textures.Length; i++)
            {
                VisualMaterial vm = textures[i];
                TextureBounds  b  = vm.texture;

                float alpha = 1f;
                //if (!vm.IsLight) {

                /*switch (vm.BlendMode) {
                 *      case VisualMaterial.SemiTransparentMode.Point25:
                 *              alpha = 0.25f * 4f;
                 *              break;
                 *      case VisualMaterial.SemiTransparentMode.Point5:
                 *              alpha = 0.5f * 4f;
                 *              break;
                 * }*/
                //}

                IPS1Polygon pf  = textured[vm].FirstOrDefault();
                GameObject  gao = new GameObject(Offset.ToString()
                                                 + " - " + i
                                                 + " - " + pf?.Offset
                                                 + " - " + pf?.GetType()
                                                 + " - " + string.Format("{0:X2}", vm.materialFlags)
                                                 + "|" + string.Format("{0:X2}", vm.scroll)
                                                 + " - " + vm.BlendMode);
                gao.transform.SetParent(parentGao.transform);
                gao.layer = LayerMask.NameToLayer("Visual");
                gao.transform.localPosition = Vector3.zero;

                List <int>     vertIndices = new List <int>();
                List <int>     triIndices  = new List <int>();
                List <Vector2> uvs         = new List <Vector2>();
                foreach (IPS1Polygon p in textured[vm])
                {
                    int currentCount = vertIndices.Count;
                    switch (p)
                    {
                    case Triangle t:
                        vertIndices.Add(t.v0);
                        vertIndices.Add(t.v1);
                        vertIndices.Add(t.v2);

                        uvs.Add(b.CalculateUV(t.x0, t.y0));
                        uvs.Add(b.CalculateUV(t.x1, t.y1));
                        uvs.Add(b.CalculateUV(t.x2, t.y2));

                        /*Vector2 uv0 = b.CalculateUV(t.x0, t.y0);
                         * Vector2 uv1 = b.CalculateUV(t.x1, t.y1);
                         * Vector2 uv2 = b.CalculateUV(t.x2, t.y2);
                         * uvs.Add(uv0);
                         * uvs.Add(uv1);
                         * uvs.Add(uv2);*/

                        triIndices.Add(currentCount);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 2);
                        break;

                    case Quad q:
                        vertIndices.Add(q.v0);
                        vertIndices.Add(q.v1);
                        vertIndices.Add(q.v2);
                        vertIndices.Add(q.v3);

                        uvs.Add(b.CalculateUV(q.x0, q.y0));
                        uvs.Add(b.CalculateUV(q.x1, q.y1));
                        uvs.Add(b.CalculateUV(q.x2, q.y2));
                        uvs.Add(b.CalculateUV(q.x3, q.y3));

                        triIndices.Add(currentCount);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 2);

                        triIndices.Add(currentCount + 2);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 3);
                        break;

                    case Sprite s:

                        GameObject spr_gao = new GameObject("Sprite");
                        spr_gao.transform.SetParent(gao.transform);
                        spr_gao.transform.localPosition = mainVertices[s.v0];
                        BillboardBehaviour billboard = spr_gao.AddComponent <BillboardBehaviour>();
                        billboard.mode = BillboardBehaviour.LookAtMode.ViewRotation;
                        MeshFilter   sprites_mf = spr_gao.AddComponent <MeshFilter>();
                        MeshRenderer sprites_mr = spr_gao.AddComponent <MeshRenderer>();

                        spr_gao.layer = LayerMask.NameToLayer("Visual");

                        //Material unityMat = sprites[i].visualMaterial.MaterialBillboard;

                        sprites_mr.receiveShadows = false;
                        sprites_mr.material       = vm.CreateMaterial();

                        var       meshUnity = new Mesh();
                        Vector3[] vertices  = new Vector3[4];

                        float scale_x = 1.0f;
                        float scale_y = 1.0f;

                        scale_x = ((float)s.height / 256f) / 2.0f;
                        scale_y = ((float)s.width / 256f) / 2.0f;

                        BoxCollider bc = spr_gao.AddComponent <BoxCollider>();
                        bc.size = new Vector3(0, scale_y * 2, scale_x * 2);

                        vertices[0] = new Vector3(0, -scale_y, -scale_x);
                        vertices[1] = new Vector3(0, -scale_y, scale_x);
                        vertices[2] = new Vector3(0, scale_y, -scale_x);
                        vertices[3] = new Vector3(0, scale_y, scale_x);
                        Vector3[] normals = new Vector3[4];
                        normals[0] = Vector3.forward;
                        normals[1] = Vector3.forward;
                        normals[2] = Vector3.forward;
                        normals[3] = Vector3.forward;
                        Vector3[] sprite_uvs = new Vector3[4];

                        bool mirrorX = false;
                        bool mirrorY = false;

                        sprite_uvs[0] = new Vector3(0, 0 - (mirrorY ? 1 : 0), alpha);
                        sprite_uvs[1] = new Vector3(1 + (mirrorX ? 1 : 0), 0 - (mirrorY ? 1 : 0), alpha);
                        sprite_uvs[2] = new Vector3(0, 1, alpha);
                        sprite_uvs[3] = new Vector3(1 + (mirrorX ? 1 : 0), 1, alpha);
                        int[] triangles = new int[] { 0, 2, 1, 1, 2, 3 };

                        meshUnity.vertices  = vertices;
                        meshUnity.normals   = normals;
                        meshUnity.triangles = triangles;
                        meshUnity.SetUVs(0, sprite_uvs.ToList());
                        sprites_mf.sharedMesh = meshUnity;

                        break;
                    }
                }
                //Vertex[] v = vertIndices.Select(vi => vertices[vi]).ToArray();
                BoneWeight[] w = null;
                if (bones != null && bones.Length > 0 && boneWeights != null)
                {
                    w = new BoneWeight[vertIndices.Count];
                    for (int vi = 0; vi < w.Length; vi++)
                    {
                        DeformVertexWeights dvw = boneWeights.FirstOrDefault(bw => bw.ind_vertex == vertIndices[vi]);
                        if (dvw != null)
                        {
                            w[vi] = dvw.UnityWeight;
                        }
                        else
                        {
                            w[vi] = new BoneWeight()
                            {
                                boneIndex0 = 0, weight0 = 1f
                            };
                        }
                    }
                }
                if (vertIndices.Any())
                {
                    MeshFilter mf = gao.AddComponent <MeshFilter>();
                    gao.AddComponent <ExportableModel>();
                    MeshRenderer        mr        = null;
                    SkinnedMeshRenderer smr       = null;
                    Matrix4x4[]         bindPoses = null;
                    if (bones == null || bones.Length <= 0)
                    {
                        mr = gao.AddComponent <MeshRenderer>();
                    }
                    else
                    {
                        smr = gao.AddComponent <SkinnedMeshRenderer>();
                        //smr = (SkinnedMeshRenderer)mr;
                        smr.bones = boneGaos.Select(bo => bo.transform).ToArray();
                        bindPoses = new Matrix4x4[smr.bones.Length];
                        for (int bi = 0; bi < smr.bones.Length; bi++)
                        {
                            bindPoses[bi] = smr.bones[bi].worldToLocalMatrix * parentGao.transform.localToWorldMatrix;
                        }
                        smr.rootBone = smr.bones[0];
                    }

                    Mesh m = new Mesh();
                    m.vertices = vertIndices.Select(vi => mainVertices[vi]).ToArray();
                    m.colors   = vertIndices.Select(vi => mainColors[vi]).ToArray();
                    m.SetUVs(0, uvs.Select(s => new Vector4(s.x, s.y, alpha, 0f)).ToList());
                    m.triangles = triIndices.ToArray();
                    m.RecalculateNormals();
                    if (w != null)
                    {
                        m.boneWeights = w;
                        m.bindposes   = bindPoses;
                    }
                    mf.mesh = m;

                    if (mr != null)
                    {
                        mr.material = vm.CreateMaterial();
                    }
                    else if (smr != null)
                    {
                        smr.material   = vm.CreateMaterial();
                        smr.sharedMesh = m;
                    }
                    try {
                        MeshCollider mc = gao.AddComponent <MeshCollider>();
                        mc.isTrigger = false;
                        //mc.cookingOptions = MeshColliderCookingOptions.None;
                        //mc.sharedMesh = mesh;
                    } catch (Exception) { }
                }
            }
            // Untextured (some skyboxes, etc)
            if (untextured.Count > 0)
            {
                GameObject gao = new GameObject(Offset.ToString() + " - Untextured");
                gao.transform.SetParent(parentGao.transform);
                gao.layer = LayerMask.NameToLayer("Visual");
                gao.transform.localPosition = Vector3.zero;
                MeshFilter mf = gao.AddComponent <MeshFilter>();
                gao.AddComponent <ExportableModel>();
                MeshRenderer mr          = gao.AddComponent <MeshRenderer>();
                List <int>   vertIndices = new List <int>();
                List <int>   triIndices  = new List <int>();

                foreach (IPS1Polygon p in untextured)
                {
                    int currentCount = vertIndices.Count;
                    switch (p)
                    {
                    case TriangleNoTexture t:
                        vertIndices.Add(t.v0);
                        vertIndices.Add(t.v1);
                        vertIndices.Add(t.v2);

                        triIndices.Add(currentCount);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 2);
                        break;

                    case QuadNoTexture q:
                        vertIndices.Add(q.v0);
                        vertIndices.Add(q.v1);
                        vertIndices.Add(q.v2);
                        vertIndices.Add(q.v3);

                        triIndices.Add(currentCount);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 2);

                        triIndices.Add(currentCount + 2);
                        triIndices.Add(currentCount + 1);
                        triIndices.Add(currentCount + 3);
                        break;

                    default:
                        Debug.LogWarning(p.GetType()); break;
                    }
                }
                //Vertex[] v = vertIndices.Select(vi => vertices[vi]).ToArray();
                Mesh m = new Mesh();
                m.vertices = vertIndices.Select(vi => mainVertices[vi]).ToArray();
                m.colors   = vertIndices.Select(vi => mainColors[vi]).ToArray();
                m.SetUVs(0, vertIndices.Select(s => new Vector4(0.5f, 0.5f, 1f, 1f)).ToList());
                m.triangles = triIndices.ToArray();
                m.RecalculateNormals();
                mf.mesh = m;

                Material baseMaterial;

                /*if (m.colors.Any(c => c.a != 1f)) {
                 *      baseMaterial = Load.baseTransparentMaterial;
                 * } else {*/
                baseMaterial = Load.baseMaterial;
                //}
                Material mat = new Material(baseMaterial);
                mat.SetInt("_NumTextures", 1);
                string    textureName = "_Tex0";
                Texture2D tex         = Util.GrayTexture();
                mat.SetTexture(textureName, tex);
                mat.SetVector("_AmbientCoef", Vector4.one);
                mat.SetFloat("_Prelit", 1f);
                mr.material = mat;

                try {
                    MeshCollider mc = gao.AddComponent <MeshCollider>();
                    mc.isTrigger = false;
                    //mc.cookingOptions = MeshColliderCookingOptions.None;
                    //mc.sharedMesh = mesh;
                } catch (Exception) { }
            }

            return(parentGao);
        }