public GameObject GetGameObject(GeometricObject.Type type, GeometricObject go, CollideType collideType = CollideType.None)
        {
            GameObject gao = null;

            if (type == GeometricObject.Type.Collide)
            {
                gao       = new GameObject("Element Spheres @ " + Offset);
                gao.layer = LayerMask.NameToLayer("Collide");
                gao.transform.localPosition = Vector3.zero;
                if (spheres.Value != null)
                {
                    Vector3[] verts = go.verticesCollide.Value?.GetVectors(go.ScaleFactor);
                    GeometricObjectElementCollideSphereArray.GeometricElementCollideSphere[] sphere = spheres.Value.spheres;
                    for (int i = 0; i < num_spheres; i++)
                    {
                        GameObject sphere_gao = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                        sphere_gao.name = "Sphere " + i;
                        sphere_gao.transform.SetParent(gao.transform);
                        MeshRenderer mr = sphere_gao.GetComponent <MeshRenderer>();
                        sphere_gao.transform.localPosition = verts[sphere[i].centerPoint];
                        sphere_gao.transform.localScale    = Vector3.one * sphere[i].radius * 2;                      // default Unity sphere radius is 0.5
                        sphere_gao.layer = LayerMask.NameToLayer("Collide");

                        BillboardBehaviour bill = sphere_gao.AddComponent <BillboardBehaviour>();
                        bill.mode = BillboardBehaviour.LookAtMode.CameraPosXYZ;

                        mr.material = MapLoader.Loader.collideMaterial;
                        GameMaterial gmt = spheres.Value.spheres[i].material.Value;
                        if (gmt != null && gmt.collideMaterial.Value != null)
                        {
                            gmt.collideMaterial.Value.SetMaterial(mr);
                        }
                        if (collideType != CollideType.None)
                        {
                            Color col = mr.material.color;
                            mr.material       = MapLoader.Loader.collideTransparentMaterial;
                            mr.material.color = new Color(col.r, col.g, col.b, col.a * 0.7f);
                            switch (collideType)
                            {
                            case CollideType.ZDD:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdd")); break;

                            case CollideType.ZDE:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zde")); break;

                            case CollideType.ZDM:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdm")); break;

                            case CollideType.ZDR:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdr")); break;
                            }
                        }
                    }
                }
            }
            return(gao);
        }
        public GameObject GetGameObject(GeometricObject.Type type, GeometricObject go, CollideType collideType = CollideType.None)
        {
            GameObject gao = null;

            if (type == GeometricObject.Type.Collide)
            {
                gao       = new GameObject("Element Boxes @ " + Offset);
                gao.layer = LayerMask.NameToLayer("Collide");
                gao.transform.localPosition = Vector3.zero;
                if (boxes.Value != null)
                {
                    Vector3[] verts = go.verticesCollide.Value?.GetVectors(go.ScaleFactor);
                    GeometricObjectElementCollideAlignedBoxArray.GeometricElementCollideAlignedBox[] b = boxes.Value.boxes;
                    for (int i = 0; i < num_boxes; i++)
                    {
                        GameObject box_gao = GameObject.CreatePrimitive(PrimitiveType.Cube);
                        box_gao.layer = LayerMask.NameToLayer("Collide");
                        box_gao.name  = "Box " + i;
                        box_gao.transform.SetParent(gao.transform);
                        MeshFilter   mf     = box_gao.GetComponent <MeshFilter>();
                        MeshRenderer mr     = box_gao.GetComponent <MeshRenderer>();
                        Vector3      center = Vector3.Lerp(verts[b[i].minVertex], verts[b[i].maxVertex], 0.5f);
                        box_gao.transform.localPosition = center;
                        box_gao.transform.localScale    = verts[b[i].maxVertex] - verts[b[i].minVertex];

                        mr.material = MapLoader.Loader.collideMaterial;
                        GameMaterial gmt = boxes.Value.boxes[i].material.Value;
                        if (gmt != null && gmt.collideMaterial.Value != null)
                        {
                            gmt.collideMaterial.Value.SetMaterial(mr);
                        }
                        if (collideType != CollideType.None)
                        {
                            Color col = mr.material.color;
                            mr.material       = MapLoader.Loader.collideTransparentMaterial;
                            mr.material.color = new Color(col.r, col.g, col.b, col.a * 0.7f);
                            switch (collideType)
                            {
                            case CollideType.ZDD:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdd")); break;

                            case CollideType.ZDE:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zde")); break;

                            case CollideType.ZDM:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdm")); break;

                            case CollideType.ZDR:
                                mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdr")); break;
                            }
                        }
                    }
                }
            }
            return(gao);
        }
        public GameObject GetGameObject(GeometricObject.Type type, GeometricObject go)
        {
            if (type == GeometricObject.Type.Visual)
            {
                GameObject gao = new GameObject("ElementTriangles @ " + Offset);
                gao.layer = LayerMask.NameToLayer("Visual");
                bool backfaceCulling = !visualMaterial.Value.RenderBackFaces;
                gao.transform.localPosition = Vector3.zero;
                MeshRenderer mr = gao.AddComponent <MeshRenderer>();
                mr.material = visualMaterial.Value.GetMaterial(VisualMaterial.Hint.None, gao: gao);

                /*if (visualMaterial.Value.num_textures > 0
                 *      && visualMaterial.Value.textures.Value.vmTex[0].texRef.Value != null
                 *      && visualMaterial.Value.textures.Value.vmTex[0].texRef.Value.texInfo.Value != null) {
                 *      TextureInfo ti = visualMaterial.Value.textures.Value.vmTex[0].texRef.Value.texInfo.Value;
                 *      gao.name += " " + string.Format("0x{0:X4}", ti.flags) + " " + string.Format("0x{0:X4}", ti.flags2);
                 * }*/
                MeshFilter mf   = gao.AddComponent <MeshFilter>();
                Mesh       mesh = new Mesh();
                if (Settings.s.platform == Settings.Platform._3DS)
                {
                    if (sz_vertices == 0)
                    {
                        mesh.vertices = go.verticesVisual.Value.GetVectors(go.ScaleFactor);
                        if (go.hasVertexColors == 0)
                        {
                            mesh.normals = go.normals.Value.GetVectors(Int16.MaxValue);
                        }
                        else
                        {
                            mesh.SetColors(go.normals.Value.GetVectors(255f, switchAxes: false).Select(v => new Color(v.x, v.y, v.z, 1f)).ToList());
                            //mesh.SetUVs(1, go.normals.Value.GetVectors(Int16.MaxValue).Select(v => new Vector4(v.x, v.y, v.z, 1f)).ToList());
                        }
                    }
                    else
                    {
                        // Use vertices located in element
                        mesh.vertices = triangles.Value.verts.Select(v => v.GetVector(go.ScaleFactor)).ToArray();
                        if (go.hasVertexColors == 0)
                        {
                            mesh.normals = triangles.Value.colors.Select(v => v.GetVector(Int16.MaxValue)).ToArray();
                        }
                        else
                        {
                            mesh.SetColors(triangles.Value.colors.Select(v => {
                                Vector3 v3 = v.GetVector(255f, switchAxes: false);
                                return(new Color(v3.x, v3.y, v3.z, 1f));
                            }).ToList());
                        }
                    }
                    mesh.SetUVs(0, triangles.Value.uvs.Select(u => new Vector3(u.x, u.y, 1f)).ToList());
                    mesh.triangles = triangles.Value.triangles.SelectMany(t => backfaceCulling ? new int[] { t.v2, t.v1, t.v3 } : new int[] { t.v2, t.v1, t.v3, t.v1, t.v2, t.v3 }).ToArray();
                    if (go.hasVertexColors != 0)
                    {
                        mesh.RecalculateNormals();
                    }
                }
                else if (Settings.s.platform == Settings.Platform.N64)
                {
                    mesh = RSP.RSPParser.Parse(triangles.Value.rspCommands, vertices.Value.vertices, go, backfaceCulling, mr.material);
                    //gao.name += " " + vertices.Value.Offset + " - " + vertices.Value.vertices.Length + " - " + triangles.Value.Offset;

                    /*for (int i = 0; i < mesh.triangles.Length; i++) {
                     *      gao.name += " " + mesh.triangles[i];
                     * }*/
                    //gao.name += " " + go.unk0 + " " + go.unk1 + " " + go.hasVertexColors + " " + go.unk3;
                    //gao.name += " - Verts ( " + sz_vertices + "):" + vertices.Value.Offset + " - Tris ( " + sz_triangles + " ):" + triangles.Value.Offset + " - " + Index + " - " + flags;
                    //gao.name += " - Flags: " + string.Format("{0:X4}", visualMaterial.Value.textures.Value.vmTex[0].texRef.Value.texInfo.Value.flags);
                }
                else if (Settings.s.platform == Settings.Platform.DS)
                {
                    if (triangles.Value != null)
                    {
                        mesh = DS3D.GeometryParser.Parse(triangles.Value.ds3dCommands, go, backfaceCulling, mr.material);
                        //gao.name += " - Tris ( " + sz_triangles + " ):" + triangles.Value.Offset + " - " + Index + " - " + flags;
                    }
                }
                mf.mesh = mesh;
                // Apply vertex colors
                if (go.hasVertexColors != 0)
                {
                    mr.sharedMaterial.SetFloat("_Prelit", 1f);
                    mr.sharedMaterial.SetVector("_DiffuseCoef", new Vector4(1, 1, 1, 1));
                }
                return(gao);
            }
            else
            {
                return(null);
            }
        }
        public GameObject GetGameObject(GeometricObject.Type type, GeometricObject go, CollideType collideType = CollideType.None)
        {
            GameObject gao = null;

            if (type == GeometricObject.Type.Collide)
            {
                gao       = new GameObject("Element @ " + Offset);
                gao.layer = LayerMask.NameToLayer("Collide");
                gao.transform.localPosition = Vector3.zero;
                MeshRenderer mr = gao.AddComponent <MeshRenderer>();
                MeshFilter   mf = gao.AddComponent <MeshFilter>();
                mr.material = MapLoader.Loader.collideMaterial;
                if (material.Value != null && material.Value is GameMaterial)
                {
                    GameMaterial gmt = material.Value as GameMaterial;
                    //MapLoader.Loader.print(gmt.collideMaterial);
                    if (gmt.collideMaterial.Value != null)
                    {
                        gmt.collideMaterial.Value.SetMaterial(mr);
                    }
                }
                else
                {
                    MapLoader.Loader.print("Type: " + type_material + " - Ind: " + ind_material);
                }
                if (collideType != CollideType.None)
                {
                    Color col = mr.material.color;
                    mr.material       = new Material(MapLoader.Loader.collideTransparentMaterial);
                    mr.material.color = new Color(col.r, col.g, col.b, col.a * 0.7f);
                    switch (collideType)
                    {
                    case CollideType.ZDD:
                        mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdd")); break;

                    case CollideType.ZDE:
                        mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zde")); break;

                    case CollideType.ZDM:
                        mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdm")); break;

                    case CollideType.ZDR:
                        mr.material.SetTexture("_MainTex", Resources.Load <Texture2D>("Textures/zdr")); break;
                    }
                }
                Vector3[] vertices = go.verticesCollide.Value.GetVectors(go.ScaleFactor);
                int[]     tris     = triangles.Value.triangles.SelectMany(t => new int[] { t.v2, t.v1, t.v3 }).ToArray();


                Mesh mesh = new Mesh();
                mesh.vertices = tris.Select(t => vertices[t]).ToArray();
                //mesh.normals = go.normals.Value.GetVectors(Int16.MaxValue);
                //mesh.SetUVs(0, triangles.Value.uvs.Select(u => new Vector3(u.x, u.y, 1f)).ToList());
                mesh.triangles = Enumerable.Range(0, tris.Length).ToArray();
                mesh.RecalculateNormals();

                Vector2[] uvs = new Vector2[mesh.vertexCount];

                // Generate simple UVs for collision checkerboard (basically a box projection)
                Vector3[] normals = null;
                {
                    List <Vector3> norm = new List <Vector3>();
                    mesh.GetNormals(norm);
                    normals = norm.ToArray();
                    // Norm can be GC'd after these curly braces
                }
                for (int j = 0; j < uvs.Length; j++)
                {
                    Vector3 normal = normals[j];
                    normal = new Vector3(Mathf.Abs(normal.x), Mathf.Abs(normal.y), Mathf.Abs(normal.z));
                    float biggestNorm = Mathf.Max(normal.x, normal.y, normal.z);

                    float uvX = (mesh.vertices[j].x / 20.0f);
                    float uvY = (mesh.vertices[j].y / 20.0f);
                    float uvZ = (mesh.vertices[j].z / 20.0f);

                    //Debug.Log("Norms: " + normal.x+","+normal.y+","+normal.z);
                    //Debug.Log("Biggest norm: " + biggestNorm);
                    if (biggestNorm == Mathf.Abs(normal.x))
                    {
                        uvs[j] = new Vector2(uvY, uvZ);
                    }
                    else if (biggestNorm == Mathf.Abs(normal.y))
                    {
                        uvs[j] = new Vector2(uvX, uvZ);
                    }
                    else if (biggestNorm == Mathf.Abs(normal.z))
                    {
                        uvs[j] = new Vector2(uvX, uvY);
                    }
                    else
                    {
                        Debug.LogError("HALP");
                    }
                }
                mesh.uv = uvs;

                mf.mesh = mesh;

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

                CollideComponent cc = gao.AddComponent <CollideComponent>();
                cc.collideROM = this;
                cc.type       = collideType;
            }
            return(gao);
        }
        public GameObject GetGameObject(GeometricObject.Type type, GeometricObject go)
        {
            if (type == GeometricObject.Type.Visual)
            {
                float      curScaleX = scaleX / 2f;
                float      curScaleY = scaleY / 2f;
                GameObject gao       = new GameObject("ElementSprites @ " + Offset);
                gao.layer = LayerMask.NameToLayer("Visual");
                gao.transform.localPosition = Vector3.zero;

                GameObject spr_gao = new GameObject("Sprite 0");
                spr_gao.transform.SetParent(gao.transform);
                spr_gao.transform.localPosition = go.verticesCollide.Value.vectors[vertexIndex].GetVector(go.ScaleFactor);
                BillboardBehaviour billboard = spr_gao.AddComponent <BillboardBehaviour>();
                billboard.mode = BillboardBehaviour.LookAtMode.ViewRotation;
                MeshFilter   mf = spr_gao.AddComponent <MeshFilter>();
                MeshRenderer mr = spr_gao.AddComponent <MeshRenderer>();
                BoxCollider  bc = spr_gao.AddComponent <BoxCollider>();
                bc.size       = new Vector3(0, curScaleY * 2, curScaleX * 2);
                spr_gao.layer = LayerMask.NameToLayer("Visual");
                mr.material   = visualMaterial.Value.GetMaterial(VisualMaterial.Hint.Billboard, gao: spr_gao);

                bool mirrorX = false;
                bool mirrorY = false;
                if (visualMaterial.Value.num_textures > 0 &&
                    visualMaterial.Value.textures.Value.vmTex[0].texRef.Value != null &&
                    visualMaterial.Value.textures.Value.vmTex[0].texRef.Value.texInfo.Value != null)
                {
                    TextureInfo ti = visualMaterial.Value.textures.Value.vmTex[0].texRef.Value.texInfo.Value;
                    if (ti.IsMirrorX)
                    {
                        mirrorX = true;
                    }
                    if (ti.IsMirrorY)
                    {
                        mirrorY = true;
                    }

                    /*spr_gao.name += " " + string.Format("0x{0:X4}", visualMaterial.Value.num_textures) + " " + string.Format("0x{0:X4}", visualMaterial.Value.num_animTextures);
                     * for (int i = 0; i < visualMaterial.Value.num_textures; i++) {
                     *      spr_gao.name += " " + visualMaterial.Value.textures.Value.vmTex[i].time;
                     * }*/
                }

                /*if (visualMaterial.Value.num_textures > 1) {
                 *      MultiTextureMaterial mtmat = mr.gameObject.AddComponent<MultiTextureMaterial>();
                 *      mtmat.visMat = sprites[i].visualMaterial;
                 *      mtmat.mat = mr.sharedMaterial;
                 * }*/
                Mesh      meshUnity = new Mesh();
                Vector3[] vertices  = new Vector3[4];
                vertices[0] = new Vector3(0, -curScaleY, -curScaleX);
                vertices[1] = new Vector3(0, -curScaleY, curScaleX);
                vertices[2] = new Vector3(0, curScaleY, -curScaleX);
                vertices[3] = new Vector3(0, curScaleY, curScaleX);
                Vector3[] normals = new Vector3[4];
                normals[0] = Vector3.forward;
                normals[1] = Vector3.forward;
                normals[2] = Vector3.forward;
                normals[3] = Vector3.forward;
                Vector3[] uvs = new Vector3[4];
                if (Settings.s.platform == Settings.Platform.N64)
                {
                    uvs[0] = new Vector3(0, -(mirrorY ? 1 : 0), 1);
                    uvs[1] = new Vector3(1 + (mirrorX ? 1 : 0), -(mirrorY ? 1 : 0), 1);
                    uvs[2] = new Vector3(0, 1, 1);
                    uvs[3] = new Vector3(1 + (mirrorX ? 1 : 0), 1, 1);
                }
                else
                {
                    uvs[0] = new Vector3(0, 1 + (mirrorY ? 1 : 0), 1);
                    uvs[1] = new Vector3(1 + (mirrorX ? 1 : 0), 1 + (mirrorY ? 1 : 0), 1);
                    uvs[2] = new Vector3(0, 0, 1);
                    uvs[3] = new Vector3(1 + (mirrorX ? 1 : 0), 0, 1);
                }
                int[] triangles = new int[] { 0, 2, 1, 1, 2, 3 };

                meshUnity.vertices  = vertices;
                meshUnity.normals   = normals;
                meshUnity.triangles = triangles;
                meshUnity.SetUVs(0, uvs.ToList());


                mf.sharedMesh = meshUnity;
                return(gao);
            }
            else
            {
                return(null);
            }
        }