Example #1
0
    public void testBSPTree()
    {
        Mesh mesh = (meshFilter.mesh.vertexCount > 0) ? meshFilter.mesh : meshFilter.sharedMesh;

        PrintMesh(mesh);

        var materials = new List <Material>(); meshRenderer.GetSharedMaterials(materials);
        var start     = System.DateTime.Now;

        tree = CSG.BSPTreeCreator.Construct(mesh, materials, maxTrianglesInLeaves, nbCandidates, precision);
        Debug.Log("BSPTree created in: " + (System.DateTime.Now - start).TotalMilliseconds + " ms");
        Debug.Log(tree.PrintString());
        Mesh computedMesh = tree.ComputeMesh();

        PrintMesh(computedMesh);

        GameObject go = new GameObject();

        go.AddComponent <MeshFilter>().sharedMesh        = computedMesh;
        go.AddComponent <MeshRenderer>().sharedMaterials = tree.Materials.ToArray();
        go.transform.localPosition = transform.localPosition;
        go.transform.localRotation = transform.localRotation;
        go.transform.localScale    = transform.localScale;
        go.transform.Translate(1.5f, 0, 0);
    }
Example #2
0
    void Update()
    {
        if (sy != slidery.value)
        {
            index = 0;
            sy    = slidery.value;
        }
        else
        if (sx != sliderx.value)
        {
            index = 1;
            sx    = sliderx.value;
        }
        else
        if (sz != sliderz.value)
        {
            index = 2;
            sz    = sliderz.value;
        }
        valuey = valuey - 0.01f;
        foreach (Transform child in gameObject.transform)
        {
            MeshRenderer meshRenderer = child.GetComponent <MeshRenderer>();

            if (meshRenderer != null)
            {
                meshRenderer.enabled = true;
                // location.lat =0;
                List <Material> materials = new List <Material>();
                meshRenderer.GetSharedMaterials(materials);
                foreach (Material material in materials)
                {
                    if (index == -1)
                    {
                        if (valuey <= 0)
                        {
                            valuey = 0;
                        }
                        _topYVector(valuey, material);
                    }
                    else
                    if (index == 0)
                    {
                        _topYVector(slidery.value, material);
                    }
                    else
                    if (index == 1)
                    {
                        _topXVector(sliderx.value, material);
                    }
                    else
                    if (index == 2)
                    {
                        _topZVector(sliderz.value, material);
                    }
                }
            }
        }
    }
Example #3
0
        private void Draw(Matrix4x4 rotationMatrix, int pixelsPerUnit)
        {
            var parent       = transform.parent;
            var drawPosition = parent.TransformPoint(rotationMatrix // Compensate actor (parent game object) rotation.
                                                     .MultiplyPoint3x4(parent.InverseTransformPoint(transform.position)));
            var drawTransform = Matrix4x4.TRS(drawPosition * pixelsPerUnit, parent.localRotation, parent.lossyScale * pixelsPerUnit);

            meshRenderer.GetPropertyBlock(propertyBlock);
            meshRenderer.GetSharedMaterials(materials);
            for (int i = 0; i < materials.Count; i++)
            {
                commandBuffer.DrawMesh(meshFilter.sharedMesh, drawTransform, materials[i], i + meshRenderer.subMeshStartIndex, -1, propertyBlock);
            }
        }
Example #4
0
    public void AddGameObject(GameObject go, int layer, bool isBatchable)
    {
        if (!childs.ContainsKey(go))
        {
            childs.Add(go, 0);

            go.transform.parent = objectContainer;

            if (isBatchable)
            {
                ChildRendering cr = new ChildRendering();
                cr.gameObject = go;

                foreach (Transform t in go.transform)
                {
                    if (batchableNames.Contains(t.name))
                    {
                        MeshFilter   mf = t.gameObject.GetComponent <MeshFilter>();
                        MeshRenderer mr = t.gameObject.GetComponent <MeshRenderer>();

                        if (mf != null && mf.sharedMesh != null && mr != null)
                        {
                            cr.meshFilters.Add(mf);
                            cr.meshRenderers.Add(mr);
                            List <Material> m = new List <Material>();
                            mr.GetSharedMaterials(m);
                            cr.meshMaterials.UnionWith(m);

                            batchUpdate.UnionWith(m);
                        }
                    }
                }

                if (cr.meshFilters.Count != 0)
                {
                    childRendering.Add(go, cr);
                }

                if (batchUpdate.Count != 0)
                {
                    SetBatchVisible(false);
                }
            }
        }
        else
        {
            Debug.LogError(go.name + " already inserted in " + gameObject.name);
        }
    }
Example #5
0
        private void SetMaterialsIfModified(MeshRenderer meshRenderer, Material[] renderMaterials)
        {
            meshRenderer.GetSharedMaterials(sSharedMaterials);
            if (sSharedMaterials != null &&
                sSharedMaterials.Count == renderMaterials.Length)
            {
                for (int i = 0; i < renderMaterials.Length; i++)
                {
                    if (renderMaterials[i] != sSharedMaterials[i])
                    {
                        goto SetMaterials;
                    }
                }
                sSharedMaterials.Clear(); // prevent dangling references
                return;
            }
            sSharedMaterials.Clear(); // prevent dangling references
SetMaterials:
            meshRenderer.sharedMaterials = renderMaterials;
        }
Example #6
0
    // Start is called before the first frame update
    void Start()
    {
        Shader shader = (Shader.Find("Unlit/CilpShader"));

        if (shader != null)
        {
        }
        slidery = GameObject.Find("SliderY").GetComponent <Slider>();
        sliderx = GameObject.Find("SliderX").GetComponent <Slider>();
        sliderz = GameObject.Find("SliderZ").GetComponent <Slider>();

        foreach (Transform child in gameObject.transform)
        {
            if (child.name.Equals("logo") || child.name.Equals("tree_04"))
            {
                continue;
            }
            MeshRenderer meshRenderer = child.GetComponent <MeshRenderer>();

            // Location location = child.gameObject.AddComponent<Location>();
            if (meshRenderer != null)
            {
                meshRenderer.enabled = false;
                float y  = meshRenderer.bounds.size.y / 2 + child.transform.position.y;
                float _y = child.transform.position.y - meshRenderer.bounds.size.y / 2;
                if (!child.name.Equals("LH_43") && !child.name.Equals("B_01") && !child.name.Equals("B_02") && !child.name.Equals("B_03"))
                {
                    float x  = meshRenderer.bounds.size.x / 2 + child.transform.position.x;
                    float _x = child.transform.position.x - meshRenderer.bounds.size.x / 2;


                    float z  = meshRenderer.bounds.size.z / 2 + child.transform.position.z;
                    float _z = child.transform.position.z - meshRenderer.bounds.size.z / 2;

                    if (minX > _x)
                    {
                        minX = _x;
                    }
                    if (x > maxX)
                    {
                        maxX = x;
                    }
                    if (minZ > _z)
                    {
                        minZ = _z;
                    }
                    if (z > maxZ)
                    {
                        maxZ = z;
                    }
                }
                if (y > maxY)
                {
                    maxY = y;
                }
                if (minY > _y)
                {
                    minY = _y;
                }
                List <Material> materials = new List <Material>();
                meshRenderer.GetSharedMaterials(materials);
                foreach (Material material in materials)
                {
                    material.shader = shader;
                    material.SetFloat("_clip", 1);
                }
            }
        }
        //if (transform.position.y < 0)
        //{
        //    Debug.Log(minY + "---" + maxY + "=@==" + transform.position.y);
        //    minY = minY - transform.position.y;
        //    maxY = maxY - transform.position.y;
        //    transform.position = new Vector3(transform.position.x, 0, transform.position.z);


        //    Debug.Log(minY + "---" + maxY + "=@==" + transform.position.y);
        //}
        //   Debug.Log(minX + "===" + maxX);
        //Debug.Log(minZ + "---" + maxZ + "=@==" + transform.position.z);
        //   maxX = maxX + 1 * sacale;
        maxZ = maxZ - 1 * sacale;
    }
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        // set up initial counts and values for everything
        MaxFarmers  = maxFarmers;
        MaxDrones   = maxDrones;
        droneCount  = 0;
        farmerCount = 0;
        BoardWidth  = boardWidth;
        PerformTaskSystem.InitializeTillSystem(maxFarmers);

        // set up mesh rendering from prefab
        MeshRenderer meshRenderer = TilePrefab.GetComponent <MeshRenderer>();
        var          meshFilter   = TilePrefab.GetComponent <MeshFilter>();
        var          materials    = new List <Material>(MATERIAL_NUMBER);
        var          mesh         = meshFilter.sharedMesh;

        meshRenderer.GetSharedMaterials(materials);

        // set up entity and manager
        entityManager = dstManager;
        boardEntity   = conversionSystem.GetPrimaryEntity(TilePrefab);

        // a board archetype
        boardArchetype = entityManager.CreateArchetype(
            typeof(Translation), typeof(GridBoard));

        // Generate rock prefab entity
        rockEntity = conversionSystem.GetPrimaryEntity(RockPrefab);
        entityManager.AddComponentData(rockEntity, new RockTag {
        });

        // Generate drone prefab entity
        droneEntity = conversionSystem.GetPrimaryEntity(DronePrefab);
        entityManager.AddComponentData(droneEntity, new MovementComponent {
        });
        entityManager.AddComponentData(droneEntity, new EntityInfo {
            specificEntity = droneEntity, type = -1
        });
        entityManager.AddComponent(droneEntity, typeof(DroneTag));

        // generate 3 plants to use for everything else
        plantEntity = new Entity[DIFF_PLANT_COUNT];
        Unity.Mathematics.Random rand  = new Unity.Mathematics.Random(42);
        int          nextRandom        = rand.NextInt();
        MeshRenderer meshPlantRenderer = PlantMeshPrefab.GetComponent <MeshRenderer>();
        var          meshPlantFilter   = PlantMeshPrefab.GetComponent <MeshFilter>();
        var          materials2        = new List <Material>(MATERIAL_NUMBER);

        meshPlantRenderer.GetSharedMaterials(materials2);

        for (int i = 0; i < DIFF_PLANT_COUNT; i++)
        {
            plantMesh = GeneratePlantMesh(nextRandom);
            var meshPlantTmp = Instantiate(plantMesh);
            meshPlantFilter.sharedMesh = meshPlantTmp;
            plantEntity[i]             = conversionSystem.GetPrimaryEntity(PlantMeshPrefab);
            Convert(plantEntity[i], dstManager, conversionSystem, meshPlantRenderer, meshPlantTmp, materials2);
            entityManager.AddComponent(plantEntity[i], typeof(PlantTag));
            entityManager.SetComponentData(plantEntity[i], new Translation {
                Value = new float3(-1, -5, -1)
            });
            entityManager.AddComponentData(plantEntity[i], new NonUniformScale {
                Value = new float3(1.0f, 2.0f, 1.0f)
            });
            entityManager.AddComponentData(plantEntity[i], new PlantComponent
            {
                timeGrown    = 0,
                state        = (int)PlantState.None,
                reserveIndex = -1
            });
            nextRandom = rand.NextInt();
        }
        // create atlas and texture info
        CalculatePredeterminedTextures();
        // if textures changed we'd have to re-create them with the following:
        //CreateAtlasData();
        //CreateTextures();

        // the texture indices in the world
        // clearing memory gives everything the first image in the uv's,
        // which is conveniently non-tilled ground
        blockIndices = new NativeArray <int>(BoardWidth * BoardWidth, Allocator.Persistent, NativeArrayOptions.ClearMemory);

        // initialize hash table that stores all the tile state info
        GridData gdata = GridData.GetInstance();

        gdata.Initialize(BoardWidth);

        // generate the terrain mesh and add it to the world
        Mesh mesh2;
        int  maxX = BoardWidth / MAX_MESH_WIDTH;
        int  maxZ = BoardWidth / MAX_MESH_WIDTH;

        // only one mesh
        allMeshes = new Mesh[(maxX + 1) * (maxZ + 1)];
        allUVs    = new NativeArray <float2> [(maxX + 1) * (maxZ + 1)];
        allVerts  = new NativeArray <float3> [(maxX + 1) * (maxZ + 1)];
        allTris   = new NativeArray <int> [(maxX + 1) * (maxZ + 1)];

        // for small enough meshes it's just a single mesh in the world
        int height = 0;

        if (maxX == 0 && maxZ == 0)
        {
            int cornerX = 0;
            int cornerZ = 0;
            allUVs[0] = new NativeArray <float2>(BoardWidth * BoardWidth * 4, Allocator.Persistent);
            mesh2     = GenerateTerrainMesh(BoardWidth, BoardWidth, 0, 0, height, allUVs[0]);

            mesh                  = Instantiate(mesh2);
            allMeshes[0]          = mesh;
            meshFilter.sharedMesh = mesh;

            var segmentEntity = conversionSystem.CreateAdditionalEntity(gameObject);
            var pos           = new float3(cornerX, 0, cornerZ);

            var localToWorld = new LocalToWorld
            {
                Value = float4x4.Translate(pos)
            };
            var aabb = new AABB
            {
                Center  = pos,
                Extents = new float3(BoardWidth, 0.5f, BoardWidth)
            };
            var worldRenderBounds = new WorldRenderBounds
            {
                Value = aabb
            };

            dstManager.AddComponentData(segmentEntity, localToWorld);
            dstManager.AddComponentData(segmentEntity, worldRenderBounds);
            dstManager.AddComponent(segmentEntity, ComponentType.ChunkComponent <ChunkWorldRenderBounds>());
            //dstManager.AddComponent(segmentEntity, typeof(Frozen));

            Convert(segmentEntity, dstManager, conversionSystem, meshRenderer, mesh, materials);
        }
        else
        {
            // FIX: this could be parallelized as all meshes are
            // independent from each other
            // for larger meshes it's broken up into
            // 64k vertex pieces

            for (int index = 0; index < (maxX + 1) * (maxZ + 1); index++)
            {
                //Parallel.For(0, (maxX + 1) * (maxZ + 1), (index) =>
                //{
                int x = (int)(index / (maxX + 1));
                int z = index - (maxX + 1) * x;
                //UnityEngine.Debug.Log("x: " + x + " " + z);
                int cornerX = x * MAX_MESH_WIDTH;
                int cornerZ = z * MAX_MESH_WIDTH;
                int width   = 0;
                int depth   = 0;
                int startX  = 0;
                int startZ  = 0;

                float3 pos = new float3(cornerX, 0, cornerZ);

                if (x < maxX && z < maxZ)
                {
                    startX = cornerX;
                    startZ = cornerZ;
                    width  = MAX_MESH_WIDTH;
                    depth  = MAX_MESH_WIDTH;
                }
                else if (x < maxX)
                {
                    startX = cornerX;
                    startZ = cornerZ;
                    width  = MAX_MESH_WIDTH;
                    depth  = BoardWidth - cornerZ;
                }
                else if (z < maxZ)
                {
                    startX = cornerX;
                    startZ = cornerZ;
                    width  = BoardWidth - cornerX;
                    depth  = MAX_MESH_WIDTH;
                }
                else
                {
                    startX = cornerX;
                    startZ = cornerZ;
                    width  = BoardWidth - cornerX;
                    depth  = BoardWidth - cornerZ;
                }
                //UnityEngine.Debug.Log("index " + index + " " + width + " " + depth +
                //    " " + cornerX + " " + cornerZ);

                allUVs[index]   = new NativeArray <float2>(width * depth * 4, Allocator.Persistent);
                allVerts[index] = new NativeArray <float3>(width * depth * 4, Allocator.Persistent);
                allTris[index]  = new NativeArray <int>(width * depth * 6, Allocator.Persistent);
                NativeArray <float2> uvs  = allUVs[index];
                NativeArray <float3> vert = allVerts[index];
                NativeArray <int>    tri  = allTris[index];

                int triangleIndex    = 0;
                int vertexIndex      = 0;
                int vertexMultiplier = 4; // create quads to fit uv's to so we can use more than one uv

                int uvIndex = 0;

                for (x = 0; x < width; x++)
                {
                    for (z = 0; z < depth; z++)
                    {
                        int y            = height;
                        int textureIndex = 0;
                        int index2D      = (z + startZ) + width * (x + startX);
                        textureIndex = blockIndices[index2D];

                        // add vertices for the quad first
                        // front
                        vert[vertexIndex]     = new float3(x + 0.5f, 0.5f, z + -0.5f);
                        vert[vertexIndex + 1] = new float3(x + 0.5f, 0.5f, z + 0.5f);
                        vert[vertexIndex + 2] = new float3(x + -0.5f, 0.5f, z + 0.5f);
                        vert[vertexIndex + 3] = new float3(x + -0.5f, 0.5f, z + -0.5f);

                        // set the UV's
                        uvs[uvIndex] = new float2(textures[textureIndex].pixelStartX,
                                                  textures[textureIndex].pixelStartY);
                        uvs[uvIndex + 1] = new float2(textures[textureIndex].pixelStartX,
                                                      textures[textureIndex].pixelEndY);
                        uvs[uvIndex + 2] = new float2(textures[textureIndex].pixelEndX,
                                                      textures[textureIndex].pixelEndY);
                        uvs[uvIndex + 3] = new float2(textures[textureIndex].pixelEndX,
                                                      textures[textureIndex].pixelStartY);
                        uvIndex += 4;

                        // front or top face
                        tri[triangleIndex]     = vertexIndex;
                        tri[triangleIndex + 1] = vertexIndex + 2;
                        tri[triangleIndex + 2] = vertexIndex + 1;
                        tri[triangleIndex + 3] = vertexIndex;
                        tri[triangleIndex + 4] = vertexIndex + 3;
                        tri[triangleIndex + 5] = vertexIndex + 2;
                        triangleIndex         += 6;

                        // increment the vertices
                        vertexIndex += vertexMultiplier;
                    }
                }
                AABB aabb;
                aabb = new AABB
                {
                    Center  = pos,
                    Extents = new float3(width, 0.5f, depth)
                };
                mesh2 = new Mesh();
                mesh2.SetVertices(allVerts[index]);
                mesh2.SetUVs(0, allUVs[index]);
                mesh2.SetTriangles(allTris[index].ToArray(), 0);
                mesh2.RecalculateNormals();
                mesh2.RecalculateBounds();
                mesh = Instantiate(mesh2);
                meshFilter.sharedMesh = mesh;
                //Debug.Log("creating mesh for : " + x + " " + z + "  " + (z + (maxX + 1) * x));
                allMeshes[index] = mesh;
                var segmentEntity = conversionSystem.CreateAdditionalEntity(gameObject);

                var localToWorld = new LocalToWorld
                {
                    Value = float4x4.Translate(pos)
                };
                var worldRenderBounds = new WorldRenderBounds
                {
                    Value = aabb
                };

                dstManager.AddComponentData(segmentEntity, localToWorld);
                dstManager.AddComponentData(segmentEntity, worldRenderBounds);
                dstManager.AddComponent(segmentEntity, ComponentType.ChunkComponent <ChunkWorldRenderBounds>());
                //dstManager.AddComponent(segmentEntity, typeof(Frozen));

                Convert(segmentEntity, dstManager, conversionSystem, meshRenderer, mesh, materials);
            }
            //);
        }

        // generate rocks and such on the grid
        GenerateGrid();

        // generate the farmers
        // Create farmer entity prefab from the game object hierarchy once
        farmerEntity = conversionSystem.GetPrimaryEntity(FarmerPrefab);
        entityManager.AddComponent <FarmerTag>(farmerEntity);

        // FIX: this could be parallelized
        // NOTE: NOT WORTH DOING UNTIL ALL THE add/set component is
        // part of burst as that's all this is
        // Also note: usually not that many farmers to justify
        // parallelization.
        for (int i = 0; i < farmerNumber; i++)
        {
            farmerCount++;
            var instance = entityManager.Instantiate(farmerEntity);
            if (i == 0)
            {
                firstFarmer = instance;
            }
            int startX = Math.Abs(rand.NextInt()) % gdata.width;
            int startZ = Math.Abs(rand.NextInt()) % gdata.width;

            // Place the instantiated entity in a grid with some noise
            var position = new float3(startX, 2, startZ);
            entityManager.SetComponentData(instance, new Translation()
            {
                Value = position
            });
            var data = new MovementComponent
            {
                startPos  = new float2(startX, startZ),
                speed     = 2,
                targetPos = new float2(startX, startZ),
            };
            var entityData = new EntityInfo {
                specificEntity = instance, type = -1
            };
            entityManager.AddComponentData(instance, data);
            entityManager.AddComponentData(instance, entityData);

            // give his first command based on the 1's in the hash
            entityManager.AddComponent <NeedsTaskTag>(instance);
        }

        if (blockIndices.IsCreated)
        {
            blockIndices.Dispose();
        }
    }
        /// <summary>
        /// Gets all the meshes and outputs to a string (even grabbing the child of each gameObject)
        /// </summary>
        /// <returns>The mesh to string.</returns>
        /// <param name="gameObj">GameObject Parent.</param>
        /// <param name="materials">Every Material in the parent that can be accessed.</param>
        /// <param name="objects">The StringBuidler to create objects for the FBX file.</param>
        /// <param name="connections">The StringBuidler to create connections for the FBX file.</param>
        /// <param name="parentObject">Parent object, if left null this is the top parent.</param>
        /// <param name="parentModelId">Parent model id, 0 if top parent.</param>
        public static long GetMeshToString(GameObject gameObj,
                                           Material[] materials,
                                           ref StringBuilder objects,
                                           ref StringBuilder connections,
                                           GameObject parentObject = null,
                                           long parentModelId      = 0)
        {
            StringBuilder tempObjectSb      = new StringBuilder();
            StringBuilder tempConnectionsSb = new StringBuilder();

            long geometryId = FBXExporter.GetRandomFBXId();
            long modelId    = FBXExporter.GetRandomFBXId();

            // Sees if there is a mesh to export and add to the system
            MeshFilter          filter      = gameObj.ThreadSafe_GetComponent <MeshFilter>();
            SkinnedMeshRenderer skinnedMesh = gameObj.ThreadSafe_GetComponent <SkinnedMeshRenderer>();

            // The mesh to export is this level's mesh that is going to be exported
            Mesh meshToExport = ThreadSafeUtils.CreateMesh();

            if (filter != null)
            {
                meshToExport = filter.GetSharedMesh();
            }
            else if (skinnedMesh != null) // If this object has a skinned mesh on it, bake that mesh into whatever pose it is at and add it as a new mesh to export
            {
                meshToExport = new Mesh();
                skinnedMesh.ThreadSafe_BakeMesh(meshToExport);
            }

            if (meshToExport == null)
            {
                Debug.LogError("Couldn't find a mesh to export");
            }

            string meshName = gameObj.GetName();

            // A NULL parent means that the gameObject is at the top
            string isMesh = "Null";

            if (meshToExport != null)
            {
                meshName = meshToExport.GetName();
                isMesh   = "Mesh";
            }

            if (filter != null)
            {
                if (filter.GetSharedMesh() == null)
                {
                    // The MeshFilter has no mesh assigned, so treat it like an FBX Null node.
                    filter = null;
                }
                else
                {
                    meshName = filter.GetSharedMesh().GetName();
                    isMesh   = "Mesh";
                }
            }

            // If we've got a skinned mesh without a name, give it a random name
            if (meshName == "" && skinnedMesh != null)
            {
                meshName = "Skinned Mesh " + Random.Range(0, 1000000);
            }

            if (parentModelId == 0)
            {
                tempConnectionsSb.AppendLine("\t;Model::" + meshName + ", Model::RootNode");
            }
            else
            {
                tempConnectionsSb.AppendLine("\t;Model::" + meshName + ", Model::USING PARENT");
            }
            tempConnectionsSb.AppendLine("\tC: \"OO\"," + modelId + "," + parentModelId);
            tempConnectionsSb.AppendLine();
            tempObjectSb.AppendLine("\tModel: " + modelId + ", \"Model::" + gameObj.GetName() + "\", \"" + isMesh + "\" {");
            tempObjectSb.AppendLine("\t\tVersion: 232");
            tempObjectSb.AppendLine("\t\tProperties70:  {");
            tempObjectSb.AppendLine("\t\t\tP: \"RotationOrder\", \"enum\", \"\", \"\",4");
            tempObjectSb.AppendLine("\t\t\tP: \"RotationActive\", \"bool\", \"\", \"\",1");
            tempObjectSb.AppendLine("\t\t\tP: \"InheritType\", \"enum\", \"\", \"\",1");
            tempObjectSb.AppendLine("\t\t\tP: \"ScalingMax\", \"Vector3D\", \"Vector\", \"\",0,0,0");
            tempObjectSb.AppendLine("\t\t\tP: \"DefaultAttributeIndex\", \"int\", \"Integer\", \"\",0");
            // ===== Local Translation Offset =========
            Vector3 position = gameObj.GetTransform().GetLocalPosition();

            tempObjectSb.Append("\t\t\tP: \"Lcl Translation\", \"Lcl Translation\", \"\", \"A+\",");

            // Append the X Y Z coords to the system
            tempObjectSb.AppendFormat("{0},{1},{2}", FE.FBXFormat(position.GetX() * -1), FE.FBXFormat(position.GetY()), FE.FBXFormat(position.GetZ()));
            tempObjectSb.AppendLine();

            // Rotates the object correctly from Unity space
            Vector3 localRotation = gameObj.GetTransform().GetLocalEulerAngles();

            tempObjectSb.AppendFormat("\t\t\tP: \"Lcl Rotation\", \"Lcl Rotation\", \"\", \"A+\",{0},{1},{2}", FE.FBXFormat(localRotation.GetX()), FE.FBXFormat(localRotation.GetY() * -1), FE.FBXFormat(-1 * localRotation.GetZ()));
            tempObjectSb.AppendLine();

            // Adds the local scale of this object
            Vector3 localScale = gameObj.GetTransform().GetLocalScale();

            tempObjectSb.AppendFormat("\t\t\tP: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",{0},{1},{2}", FE.FBXFormat(localScale.GetX()), FE.FBXFormat(localScale.GetY()), FE.FBXFormat(localScale.GetZ()));
            tempObjectSb.AppendLine();

            tempObjectSb.AppendLine("\t\t\tP: \"currentUVSet\", \"KString\", \"\", \"U\", \"map1\"");
            tempObjectSb.AppendLine("\t\t}");
            tempObjectSb.AppendLine("\t\tShading: T");
            tempObjectSb.AppendLine("\t\tCulling: \"CullingOff\"");
            tempObjectSb.AppendLine("\t}");

            // Adds in geometry if it exists, if it it does not exist, this is a empty gameObject file and skips over this
            if (meshToExport != null)
            {
                Mesh mesh = meshToExport;

                // =================================
                //         General Geometry Info
                // =================================
                // Generate the geometry information for the mesh created

                tempObjectSb.AppendLine("\tGeometry: " + geometryId + ", \"Geometry::\", \"Mesh\" {");

                // ===== WRITE THE VERTICIES =====
                Vector3[] verticies = mesh.GetVertices();
                int       vertCount = mesh.GetVertexCount() * 3; // <= because the list of points is just a list of comma seperated values, we need to multiply by three

                tempObjectSb.AppendLine("\t\tVertices: *" + vertCount + " {");
                tempObjectSb.Append("\t\t\ta: ");
                for (int i = 0; i < verticies.Length; i++)
                {
                    if (i > 0)
                    {
                        tempObjectSb.Append(",");
                    }

                    // Points in the verticies. We also reverse the x value because Unity has a reverse X coordinate
                    tempObjectSb.AppendFormat("{0},{1},{2}", FE.FBXFormat(verticies[i].GetX() * -1), FE.FBXFormat(verticies[i].GetY()), FE.FBXFormat(verticies[i].GetZ()));
                }

                tempObjectSb.AppendLine();
                tempObjectSb.AppendLine("\t\t} ");

                // ======= WRITE THE TRIANGLES ========
                int   triangleCount = mesh.GetTriangles().Length;
                int[] triangles     = mesh.GetTriangles();

                tempObjectSb.AppendLine("\t\tPolygonVertexIndex: *" + triangleCount + " {");

                // Write triangle indexes
                tempObjectSb.Append("\t\t\ta: ");
                for (int i = 0; i < triangleCount; i += 3)
                {
                    if (i > 0)
                    {
                        tempObjectSb.Append(",");
                    }

                    // To get the correct normals, must rewind the triangles since we flipped the x direction
                    tempObjectSb.AppendFormat("{0},{1},{2}",
                                              triangles[i],
                                              triangles[i + 2],
                                              (triangles[i + 1] * -1) - 1); // <= Tells the poly is ended
                }

                tempObjectSb.AppendLine();

                tempObjectSb.AppendLine("\t\t} ");
                tempObjectSb.AppendLine("\t\tGeometryVersion: 124");
                tempObjectSb.AppendLine("\t\tLayerElementNormal: 0 {");
                tempObjectSb.AppendLine("\t\t\tVersion: 101");
                tempObjectSb.AppendLine("\t\t\tName: \"\"");
                tempObjectSb.AppendLine("\t\t\tMappingInformationType: \"ByPolygonVertex\"");
                tempObjectSb.AppendLine("\t\t\tReferenceInformationType: \"Direct\"");

                // ===== WRITE THE NORMALS ==========
                Vector3[] normals = mesh.ThreadSafe_GetNormals();

                tempObjectSb.AppendLine("\t\t\tNormals: *" + (triangleCount * 3) + " {");
                tempObjectSb.Append("\t\t\t\ta: ");

                for (int i = 0; i < triangleCount; i += 3)
                {
                    if (i > 0)
                    {
                        tempObjectSb.Append(",");
                    }

                    // To get the correct normals, must rewind the normal triangles like the triangles above since x was flipped
                    Vector3 newNormal = normals[triangles[i]];

                    tempObjectSb.AppendFormat("{0},{1},{2},",
                                              FE.FBXFormat(newNormal.GetX() * -1), // Switch normal as is tradition
                                              FE.FBXFormat(newNormal.GetY()),
                                              FE.FBXFormat(newNormal.GetZ()));

                    newNormal = normals[triangles[i + 2]];

                    tempObjectSb.AppendFormat("{0},{1},{2},",
                                              FE.FBXFormat(newNormal.GetX() * -1), // Switch normal as is tradition
                                              FE.FBXFormat(newNormal.GetY()),
                                              FE.FBXFormat(newNormal.GetZ()));

                    newNormal = normals[triangles[i + 1]];

                    tempObjectSb.AppendFormat("{0},{1},{2}",
                                              FE.FBXFormat(newNormal.GetX() * -1), // Switch normal as is tradition
                                              FE.FBXFormat(newNormal.GetY()),
                                              FE.FBXFormat(newNormal.GetZ()));
                }

                tempObjectSb.AppendLine();
                tempObjectSb.AppendLine("\t\t\t}");
                tempObjectSb.AppendLine("\t\t}");

                // ===== WRITE THE COLORS =====
                bool containsColors = mesh.ThreadSafe_GetColors().Length == verticies.Length;

                if (containsColors)
                {
                    Color[] colors = mesh.ThreadSafe_GetColors();

                    Dictionary <Color, int> colorTable = new Dictionary <Color, int>(); // reducing amount of data by only keeping unique colors.
                    int idx = 0;

                    // build index table of all the different colors present in the mesh
                    for (int i = 0; i < colors.Length; i++)
                    {
                        if (!colorTable.ContainsKey(colors[i]))
                        {
                            colorTable[colors[i]] = idx;
                            idx++;
                        }
                    }

                    tempObjectSb.AppendLine("\t\tLayerElementColor: 0 {");
                    tempObjectSb.AppendLine("\t\t\tVersion: 101");
                    tempObjectSb.AppendLine("\t\t\tName: \"Col\"");
                    tempObjectSb.AppendLine("\t\t\tMappingInformationType: \"ByPolygonVertex\"");
                    tempObjectSb.AppendLine("\t\t\tReferenceInformationType: \"IndexToDirect\"");
                    tempObjectSb.AppendLine("\t\t\tColors: *" + colorTable.Count * 4 + " {");
                    tempObjectSb.Append("\t\t\t\ta: ");

                    bool first = true;
                    foreach (KeyValuePair <Color, int> color in colorTable)
                    {
                        if (!first)
                        {
                            tempObjectSb.Append(",");
                        }

                        tempObjectSb.AppendFormat("{0},{1},{2},{3}", FE.FBXFormat(color.Key.GetR()), FE.FBXFormat(color.Key.GetG()), FE.FBXFormat(color.Key.GetB()), FE.FBXFormat(color.Key.GetA()));
                        first = false;
                    }
                    tempObjectSb.AppendLine();

                    tempObjectSb.AppendLine("\t\t\t\t}");

                    // Color index
                    tempObjectSb.AppendLine("\t\t\tColorIndex: *" + triangles.Length + " {");
                    tempObjectSb.Append("\t\t\t\ta: ");

                    for (int i = 0; i < triangles.Length; i += 3)
                    {
                        if (i > 0)
                        {
                            tempObjectSb.Append(",");
                        }

                        // Triangles need to be fliped for the x flip
                        int index1 = triangles[i];
                        int index2 = triangles[i + 2];
                        int index3 = triangles[i + 1];

                        // Find the color index related to that vertice index
                        index1 = colorTable[colors[index1]];
                        index2 = colorTable[colors[index2]];
                        index3 = colorTable[colors[index3]];

                        tempObjectSb.AppendFormat("{0},{1},{2}", index1, index2, index3);
                    }

                    tempObjectSb.AppendLine();

                    tempObjectSb.AppendLine("\t\t\t}");
                    tempObjectSb.AppendLine("\t\t}");
                }
                else
                {
                    Debug.LogWarning("Mesh contains " + mesh.GetVertices().Length + " vertices for " + mesh.ThreadSafe_GetColors().Length + " colors. Skip color export");
                }

                // ================ UV CREATION =========================

                // -- UV 1 Creation
                int       uvLength = mesh.GetUV().Length;
                Vector2[] uvs      = mesh.GetUV();

                tempObjectSb.AppendLine("\t\tLayerElementUV: 0 {"); // the Zero here is for the first UV map
                tempObjectSb.AppendLine("\t\t\tVersion: 101");
                tempObjectSb.AppendLine("\t\t\tName: \"map1\"");
                tempObjectSb.AppendLine("\t\t\tMappingInformationType: \"ByPolygonVertex\"");
                tempObjectSb.AppendLine("\t\t\tReferenceInformationType: \"IndexToDirect\"");
                tempObjectSb.AppendLine("\t\t\tUV: *" + uvLength * 2 + " {");
                tempObjectSb.Append("\t\t\t\ta: ");

                for (int i = 0; i < uvLength; i++)
                {
                    if (i > 0)
                    {
                        tempObjectSb.Append(",");
                    }

                    tempObjectSb.AppendFormat("{0},{1}", FE.FBXFormat(uvs[i].GetX()), FE.FBXFormat(uvs[i].GetY()));
                }
                tempObjectSb.AppendLine();

                tempObjectSb.AppendLine("\t\t\t\t}");

                // UV tile index coords
                tempObjectSb.AppendLine("\t\t\tUVIndex: *" + triangleCount + " {");
                tempObjectSb.Append("\t\t\t\ta: ");

                for (int i = 0; i < triangleCount; i += 3)
                {
                    if (i > 0)
                    {
                        tempObjectSb.Append(",");
                    }

                    // Triangles need to be fliped for the x flip
                    int index1 = triangles[i];
                    int index2 = triangles[i + 2];
                    int index3 = triangles[i + 1];

                    tempObjectSb.AppendFormat("{0},{1},{2}", index1, index2, index3);
                }

                tempObjectSb.AppendLine();

                tempObjectSb.AppendLine("\t\t\t}");
                tempObjectSb.AppendLine("\t\t}");

                // -- UV 2 Creation
                // TODO: Add UV2 Creation here

                // -- Smoothing
                // TODO: Smoothing doesn't seem to do anything when importing. This maybe should be added. -KBH

                // ============ MATERIALS =============

                tempObjectSb.AppendLine("\t\tLayerElementMaterial: 0 {");
                tempObjectSb.AppendLine("\t\t\tVersion: 101");
                tempObjectSb.AppendLine("\t\t\tName: \"\"");
                tempObjectSb.AppendLine("\t\t\tMappingInformationType: \"ByPolygon\"");
                tempObjectSb.AppendLine("\t\t\tReferenceInformationType: \"IndexToDirect\"");

                int totalFaceCount = 0;

                // So by polygon means that we need 1/3rd of how many indicies we wrote.
                int numberOfSubmeshes = mesh.GetSubmeshCount();

                StringBuilder submeshesSb = new StringBuilder();

                // For just one submesh, we set them all to zero
                if (numberOfSubmeshes == 1)
                {
                    int numFaces = triangles.Length / 3;

                    for (int i = 0; i < numFaces; i++)
                    {
                        submeshesSb.Append("0,");
                        totalFaceCount++;
                    }
                }
                else
                {
                    List <int[]> allSubmeshes = new List <int[]>();

                    // Load all submeshes into a space
                    for (int i = 0; i < numberOfSubmeshes; i++)
                    {
                        allSubmeshes.Add(mesh.ThreadSafe_GetIndices(i));
                    }

                    // TODO: Optimize this search pattern
                    for (int i = 0; i < triangles.Length; i += 3)
                    {
                        for (int subMeshIndex = 0; subMeshIndex < allSubmeshes.Count; subMeshIndex++)
                        {
                            bool breaker = false;

                            for (int n = 0; n < allSubmeshes[subMeshIndex].Length; n += 3)
                            {
                                if (triangles[i] == allSubmeshes[subMeshIndex][n] &&
                                    triangles[i + 1] == allSubmeshes[subMeshIndex][n + 1] &&
                                    triangles[i + 2] == allSubmeshes[subMeshIndex][n + 2])
                                {
                                    submeshesSb.Append(subMeshIndex.ToString());
                                    submeshesSb.Append(",");
                                    totalFaceCount++;
                                    break;
                                }

                                if (breaker)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                tempObjectSb.AppendLine("\t\t\tMaterials: *" + totalFaceCount + " {");
                tempObjectSb.Append("\t\t\t\ta: ");
                tempObjectSb.AppendLine(submeshesSb.ToString());
                tempObjectSb.AppendLine("\t\t\t} ");
                tempObjectSb.AppendLine("\t\t}");

                // ============= INFORMS WHAT TYPE OF LATER ELEMENTS ARE IN THIS GEOMETRY =================
                tempObjectSb.AppendLine("\t\tLayer: 0 {");
                tempObjectSb.AppendLine("\t\t\tVersion: 100");
                tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementNormal\"");
                tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 0");
                tempObjectSb.AppendLine("\t\t\t}");
                tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementMaterial\"");
                tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 0");
                tempObjectSb.AppendLine("\t\t\t}");
                tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementTexture\"");
                tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 0");
                tempObjectSb.AppendLine("\t\t\t}");
                if (containsColors)
                {
                    tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                    tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementColor\"");
                    tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 0");
                    tempObjectSb.AppendLine("\t\t\t}");
                }
                tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementUV\"");
                tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 0");
                tempObjectSb.AppendLine("\t\t\t}");
                // TODO: Here we would add UV layer 1 for ambient occlusion UV file
                //			tempObjectSb.AppendLine("\t\t\tLayerElement:  {");
                //			tempObjectSb.AppendLine("\t\t\t\tType: \"LayerElementUV\"");
                //			tempObjectSb.AppendLine("\t\t\t\tTypedIndex: 1");
                //			tempObjectSb.AppendLine("\t\t\t}");
                tempObjectSb.AppendLine("\t\t}");
                tempObjectSb.AppendLine("\t}");

                // Add the connection for the model to the geometry so it is attached the right mesh
                tempConnectionsSb.AppendLine("\t;Geometry::, Model::" + mesh.GetName());
                tempConnectionsSb.AppendLine("\tC: \"OO\"," + geometryId + "," + modelId);
                tempConnectionsSb.AppendLine();

                // Add the connection of all the materials in order of submesh
                MeshRenderer meshRenderer = gameObj.ThreadSafe_GetComponent <MeshRenderer>();
                if (meshRenderer != null)
                {
                    Material[] allMaterialsInThisMesh = meshRenderer.GetSharedMaterials();

                    for (int i = 0; i < allMaterialsInThisMesh.Length; i++)
                    {
                        Material mat         = allMaterialsInThisMesh[i];
                        int      referenceId = Mathf.Abs(mat.ThreadSafe_GetInstanceID());

                        if (mat == null)
                        {
                            Debug.LogError("ERROR: the game object " + gameObj.GetName() + " has an empty material on it. This will export problematic files. Please fix and reexport");
                            continue;
                        }

                        tempConnectionsSb.AppendLine("\t;Material::" + mat.GetName() + ", Model::" + mesh.GetName());
                        tempConnectionsSb.AppendLine("\tC: \"OO\"," + referenceId + "," + modelId);
                        tempConnectionsSb.AppendLine();
                    }
                }
            }

            // Recursively add all the other objects to the string that has been built.
            for (int i = 0; i < gameObj.GetTransform().ThreadSafe_GetChildCount(); i++)
            {
                GameObject childObject = gameObj.GetTransform().ThreadSafe_GetChild(i).GetGameObject();

                FBXUnityMeshGetter.GetMeshToString(childObject, materials, ref tempObjectSb, ref tempConnectionsSb, gameObj, modelId);
            }

            objects.Append(tempObjectSb.ToString());
            connections.Append(tempConnectionsSb.ToString());

            return(modelId);
        }