Ejemplo n.º 1
0
        /// <summary>
        /// Static constructor that initializes the lookup table.
        /// </summary>
        static StringUtil()
        {
            CharByteDict = new BiLookup <char, byte>();

            for (byte i = 0; i < AllowedChatCharacters.Length; i++)
            {
                CharByteDict.Add(AllowedChatCharacters[i], i);
            }
        }
Ejemplo n.º 2
0
    public B45OctreeDataSource(BiLookup <int, B45ChunkData> chunkRebuildList, Block45Building _b45Building)
    {
        _chunkRebuildList = chunkRebuildList;
        _chunks           = new Dictionary <IntVector4, B45ChunkData>();

        bvtRoot = new BlockVectorNode(new IntVector4(0, 0, 0, 1), null, 0);

        b45Building = _b45Building;
    }
Ejemplo n.º 3
0
//	B45ChunkData[,,] _chunks;
    public B45StdDataSource(int width, int height, int depth, BiLookup <int, B45ChunkData> chunkRebuildList)
    {
        _chunkNumX        = width;
        _chunkNumY        = height;
        _chunkNumZ        = depth;
        _chunkRebuildList = chunkRebuildList;
//		_chunks = new B45ChunkData[_chunkNumX, _chunkNumY, _chunkNumZ];
        _chunks   = new Dictionary <IntVector3, B45ChunkData>();
        _SaveData = new Dictionary <IntVector3, B45Block>();
    }
Ejemplo n.º 4
0
 public void Append(BiLookup <TFirst, TSecond> listToAppend)
 {
     lock (obj4Lock)
     {
         int n = listToAppend.indexByFirst.Count;
         for (int i = 0; i < n; i++)
         {
             TFirst  first  = listToAppend.indexByFirst[i];
             TSecond second = listToAppend.firstToSecond[first];
             Add(first, second);
         }
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Static constructor that initializes the bi-directional lookup.
        /// </summary>
        static AuthUtil()
        {
            // A string containing all possible characters for an authentication key
            const string authKeyCharacter =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

            AuthKeyLookup = new BiLookup <char, byte>();

            for (byte i = 0; i < authKeyCharacter.Length; i++)
            {
                AuthKeyLookup.Add(authKeyCharacter[i], i);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Construct a packet ID lookup given the generic type.
        /// </summary>
        /// <typeparam name="T">The type parameter to construct the lookup with. This should extend the
        /// enum class</typeparam>
        /// <returns>A bi-directional lookup from the generic type to a byte value.</returns>
        public static BiLookup<T, byte> ConstructPacketIdLookup<T>() where T : Enum {
            var packetIdLookup = new BiLookup<T, byte>();

            // We add an entry in the dictionary for each value, so that we have
            // bytes 0, 1, 2, ..., n
            var packetIdValues = Enum.GetValues(typeof(T));
            for (byte i = 0; i < packetIdValues.Length; i++) {
                var packetId = (T)packetIdValues.GetValue(i);

                packetIdLookup.Add(packetId, i);
            }

            return packetIdLookup;
        }
Ejemplo n.º 7
0
    void Start()                                //must be after GameManager's Awake()
    {
        timetableUITracker = new BiLookup <TimetableItemUIObject, TimetableItem> ();
        trainUITracker     = new Dictionary <Train, TrainTrackerUIObject> ();

        if (timetableItemPrefab == null || timetableItemsParent == null || trainTrackerParent == null || trainTrackerPrefab == null)
        {
            Debug.LogWarning("No timetable/train tracker item prefab and/or the parent object for them assigned.");
        }

        if (GameManager.instance.trainPool.AvailableOptions == null || GameManager.instance.trainPool.AvailableOptions.Count == 0)
        {
            Debug.LogWarning("GameUIManager is trying to access GameManager's train pool but it is not initialised or empty.");
        }
        else
        {
            foreach (Train train in GameManager.instance.trainPool.AvailableOptions)
            {
                GameObject           trainTracker         = Instantiate(trainTrackerPrefab, trainTrackerParent.transform) as GameObject;
                TrainTrackerUIObject trainTrackerUIObject = trainTracker.GetComponent <TrainTrackerUIObject> ();
                trainUITracker.Add(train, trainTrackerUIObject);
                trainTrackerUIObject.trainIDText.text = train.trainSerialID;
                trainTrackerUIObject.statusText.text  = "Ready to approach...";
            }
        }

        emptyTrainOption    = new Dropdown.OptionData("None", trainUISprite);
        emptyPlatformOption = new Dropdown.OptionData("Platform -");

        clockText            = MyFindUIObjectWithTag("UI_ClockText").GetComponent <Text> ();
        approvalSlider       = MyFindUIObjectWithTag("UI_ApprovalSlider").GetComponent <Slider> ();
        defaultOptionsMenu   = MyFindUIObjectWithTag("UI_DefaultOptionsMenu");          //note: must have all of the menus activated initially to find their elements, then deactivate them later
        itemCreationMenu     = MyFindUIObjectWithTag("UI_ItemCreationMenu");
        itemModificationMenu = MyFindUIObjectWithTag("UI_ItemModificationMenu");

        creation_schedDepartureTimeText     = MyFindUIObjectWithTag("UI_Create_SchedDepartureTimeText").GetComponent <Text> ();
        modification_schedDepartureTimeText = MyFindUIObjectWithTag("UI_Mod_SchedDepartureTimeText").GetComponent <Text> ();
        modification_DestinationText        = MyFindUIObjectWithTag("UI_DestinationText").GetComponent <Text> ();
        creation_destinationDropdown        = MyFindUIObjectWithTag("UI_DestinationDropdown").GetComponent <Dropdown>();
        modification_trainDropdown          = MyFindUIObjectWithTag("UI_TrainDropdown").GetComponent <Dropdown>();
        modification_platformDropdown       = MyFindUIObjectWithTag("UI_PlatformDropdown").GetComponent <Dropdown>();
        creation_destinationDropdown.ClearOptions();
        creation_destinationDropdown.AddOptions(GameManager.instance.destinations.Select(a => a.name).ToList());

        itemCreationMenu.SetActive(false);              //finally hide the non-default menus
        itemModificationMenu.SetActive(false);

        InvokeRepeating("UpdateDisplayAtInterval", 0f, displayUpdateInterval);                  //start a repeating invoke that updates the display at interval for those UI items that don't need update per frame
    }
Ejemplo n.º 8
0
 public void Start(MonoBehaviour parentMono,
                   BiLookup <int, B45ChunkData> chunkToComputeList,
                   OnComputeComplete setChunkMeshFunc, cpuBlock45 _b45proc,
                   bool bAsyncMode = false)
 {
     b45proc           = _b45proc;
     _mono             = parentMono;
     _setChunkMesh     = setChunkMeshFunc;
     _chunkToBuildList = chunkToComputeList;
     _bAsyncBuildMode  = bAsyncMode;
     _mono.StartCoroutine(rebuildChunksInList());
     //_setMeshFuncStack = new Stack<OnComputeComplete>();
     //_buildListStack = new Stack<BiLookup<int, B45ChunkData>>();
     b45proc.init();
 }
Ejemplo n.º 9
0
    void Awake()
    {
        if (GlobalInstance)
        {
            self = this;
        }
        bBuildColliderAsync = false;
        colliderBuilding    = true;
        b45proc             = new cpuBlock45();
        b45proc.init();

        chunkRebuildList = new BiLookup <int, B45ChunkData>();

        _blockDS = new B45OctreeDataSource(chunkRebuildList, this);
    }
Ejemplo n.º 10
0
 public BiLookup <TFirst, TSecond> CutPaste()
 {
     lock (obj4Lock)
     {
         BiLookup <TFirst, TSecond> ret = new BiLookup <TFirst, TSecond>();
         int n = indexByFirst.Count;
         for (int i = 0; i < n; i++)
         {
             TFirst  first  = indexByFirst[i];
             TSecond second = firstToSecond[first];
             ret.Add(first, second);
         }
         Clear();
         return(ret);
     }
 }
Ejemplo n.º 11
0
        public static int getBoneIdForBoneName(BiLookup <int, string> boneLookup, Dictionary <string, double[]> boneNameToPositionMap, string boneName, float boneWeight, float[] vertexPosition)
        {
            int boneId;

            if (boneName.Equals(""))
            {
                if (boneWeight == 0)
                {
                    boneId = 0;
                }
                else
                {
                    double minDistance     = Double.MaxValue;
                    string closestBoneName = null;

                    foreach (string keyBoneName in boneNameToPositionMap.Keys)
                    {
                        double[] bonePosition = boneNameToPositionMap[keyBoneName];
                        double   deltaX       = vertexPosition[0] - bonePosition[0];
                        double   deltaY       = vertexPosition[1] - bonePosition[1];
                        double   deltaZ       = vertexPosition[2] - bonePosition[2];

                        double distance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);

                        if (distance < minDistance)
                        {
                            minDistance     = distance;
                            closestBoneName = keyBoneName;
                        }
                    }
                    if (!String.IsNullOrEmpty(closestBoneName))
                    {
                        boneId = boneLookup[closestBoneName][0];
                    }
                    else
                    {
                        boneId = 0;
                    }
                }
            }
            else
            {
                boneId = boneLookup[boneName][0];
            }
            return(boneId);
        }
Ejemplo n.º 12
0
        public static void br2Export(IGrannyFile grannyFile, int currentModelIndex)
        {
            string fileExtension  = ".br2";
            string outputFilename = "";
            string numberFormat   = "f8";

            if (grannyFile.Models.Count > 1)
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", "_model" + currentModelIndex + fileExtension);
                outputFilename = outputFilename.Replace(".FGX", "_model" + currentModelIndex + fileExtension);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", fileExtension);
                outputFilename = outputFilename.Replace(".FGX", fileExtension);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create));

            IGrannyModel    model    = grannyFile.Models[currentModelIndex];
            IGrannySkeleton skeleton = model.Skeleton;

            // Lookup so we can identify the meshes belonging the current model in the list of file meshes
            Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>();
            HashSet <string>      distinctMeshNames = new HashSet <string>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                for (int j = 0; j < grannyFile.Meshes.Count; j++)
                {
                    GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]);
                    IGrannyMesh       fileMesh  = grannyFile.Meshes[j];
                    if (modelMesh.meshEqual(fileMesh))
                    {
                        meshBindingToMesh.Add(i, j);
                    }
                }
                distinctMeshNames.Add(model.MeshBindings[i].Name);
            }

            // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2
            Dictionary <string, int> meshNameCount = new Dictionary <string, int>();

            foreach (string meshName in distinctMeshNames)
            {
                meshNameCount.Add(meshName, 0);
            }

            List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]);
                grannyMeshInfos.Add(meshWrapper.getMeshInfo());
            }

            BiLookup <int, string> boneLookup = new BiLookup <int, string>();

            for (int i = 0; i < skeleton.Bones.Count; i++)
            {
                boneLookup.Add(i, skeleton.Bones[i].Name);
            }

            Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>();

            foreach (IGrannyBone bone in skeleton.Bones)
            {
                double[] bonePosition = NB2NA2FileOps.getBoneWorldPosition(bone);
                boneNameToPositionMap.Add(bone.Name, bonePosition);

                //MemoryUtil.memLogLine("boneName: " + bone.Name + " bone position:" + bonePosition[0] + " " + bonePosition[1] + " " + bonePosition[2]);
            }

            outputWriter.WriteLine("// Nexus Buddy BR2 - Exported from Nexus Buddy 2");
            outputWriter.WriteLine("skeleton");

            // Write Bones
            //outputWriter.WriteLine("Bones: " + skeleton.Bones.Count);
            for (int boneIndex = 0; boneIndex < skeleton.Bones.Count; boneIndex++)
            {
                IGrannyBone      bone              = skeleton.Bones[boneIndex];
                string           boneName          = bone.Name;
                IGrannyTransform transform         = bone.LocalTransform;
                float[]          orientation       = transform.Orientation;
                float[]          position          = transform.Position;
                float[]          invWorldTransform = bone.InverseWorldTransform;

                StringBuilder boneStringBuilder = new StringBuilder(boneIndex + " \"" + boneName + "\" " + bone.ParentIndex + " " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                                                    orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture));

                foreach (float j in invWorldTransform)
                {
                    boneStringBuilder.Append(" " + j.ToString(numberFormat, CultureInfo.InvariantCulture));
                }

                outputWriter.WriteLine(boneStringBuilder);
            }

            // Write Meshes
            outputWriter.WriteLine("meshes: " + model.MeshBindings.Count);
            for (int mi = 0; mi < grannyMeshInfos.Count; mi++)
            {
                GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi];
                string         meshName       = model.MeshBindings[mi].Name;

                meshNameCount[meshName]++;
                if (meshNameCount[meshName] > 1)
                {
                    meshName += meshNameCount[meshName];
                }
                //StringBuilder boneStringBuilder = new StringBuilder();


                outputWriter.WriteLine("mesh:\"" + meshName + "\"");

                // Write Vertices
                outputWriter.WriteLine("vertices");
                for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++)
                {
                    GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi];

                    string boneName0   = grannyMeshInfo.boneBindings[vertex.boneIndices[0]];
                    float  boneWeight0 = (float)vertex.boneWeights[0] / 255;
                    int    boneId0     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName0, boneWeight0, vertex.position);

                    string boneName1   = grannyMeshInfo.boneBindings[vertex.boneIndices[1]];
                    float  boneWeight1 = (float)vertex.boneWeights[1] / 255;
                    int    boneId1     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName1, boneWeight1, vertex.position);

                    string boneName2   = grannyMeshInfo.boneBindings[vertex.boneIndices[2]];
                    float  boneWeight2 = (float)vertex.boneWeights[2] / 255;
                    int    boneId2     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName2, boneWeight2, vertex.position);

                    string boneName3   = grannyMeshInfo.boneBindings[vertex.boneIndices[3]];
                    float  boneWeight3 = (float)vertex.boneWeights[3] / 255;
                    int    boneId3     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName3, boneWeight3, vertex.position);

                    float[] tangents = new float[3];
                    if (vertex.tangent == null)
                    {
                        tangents[0] = vertex.normal[0];
                        tangents[1] = vertex.normal[1];
                        tangents[2] = vertex.normal[2];
                    }
                    else
                    {
                        tangents[0] = vertex.tangent[0];
                        tangents[1] = vertex.tangent[1];
                        tangents[2] = vertex.tangent[2];
                    }

                    float[] binormals = new float[3];
                    if (vertex.binormal == null)
                    {
                        binormals[0] = vertex.normal[0];
                        binormals[1] = vertex.normal[1];
                        binormals[2] = vertex.normal[2];
                    }
                    else
                    {
                        binormals[0] = vertex.binormal[0];
                        binormals[1] = vertex.binormal[1];
                        binormals[2] = vertex.binormal[2];
                    }

                    outputWriter.WriteLine(vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                           vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                           vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId0 + " " + boneId1 + " " + boneId2 + " " + boneId3 + " "
                                           + vertex.boneWeights[0] + " " + vertex.boneWeights[1] + " " + vertex.boneWeights[2] + " " + vertex.boneWeights[3] + " "
                                           + tangents[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + binormals[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[2].ToString(numberFormat, CultureInfo.InvariantCulture)
                                           );
                }

                // Write Triangles
                outputWriter.WriteLine("triangles");
                for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++)
                {
                    int[] triangle = grannyMeshInfo.triangles[ti];
                    outputWriter.WriteLine(triangle[0] + " " + triangle[1] + " " + triangle[2]);
                }
            }
            outputWriter.WriteLine("end");

            outputWriter.Close();
        }
Ejemplo n.º 13
0
        private static WriteModelToCN6Response WriteModelToCN6(IGrannyFile grannyFile, bool isBatch, IGrannyModel model, string filterMeshName)
        {
            List <string> textureMaps = new List <string>();

            string        fileExtension  = ".cn6";
            string        outputFilename = "";
            string        numberFormat   = "f8";
            List <string> decalMeshNames = new List <string>();

            IGrannySkeleton skeleton = model.Skeleton;

            string decalMeshName = "";

            if (filterMeshName != null)
            {
                decalMeshName = "_DCL_" + GetSafeFilename(filterMeshName);
            }

            if (grannyFile.Models.Count > 1)
            {
                string modelFilename = "__" + model.Name + decalMeshName + fileExtension;
                outputFilename = grannyFile.Filename.Replace(".gr2", modelFilename);
                outputFilename = outputFilename.Replace(".GR2", modelFilename);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".gr2", fileExtension);
                outputFilename = outputFilename.Replace(".GR2", fileExtension);
            }

            if (isBatch)
            {
                outputFilename = outputFilename.Replace(fileExtension, "_batch" + fileExtension);
            }

            string directory = Path.GetDirectoryName(outputFilename);
            string filename  = Path.GetFileName(outputFilename);

            outputFilename = directory + "\\" + GetSafeFilename(filename);

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create));

            // Lookup so we can identify the meshes belonging the current model in the list of file meshes
            Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>();
            HashSet <string>      distinctMeshNames = new HashSet <string>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                for (int j = 0; j < grannyFile.Meshes.Count; j++)
                {
                    GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]);
                    IGrannyMesh       fileMesh  = grannyFile.Meshes[j];
                    if (modelMesh.meshEqual(fileMesh))
                    {
                        meshBindingToMesh.Add(i, j);
                    }
                }
                distinctMeshNames.Add(model.MeshBindings[i].Name);
            }

            // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2
            Dictionary <string, int> meshNameCount = new Dictionary <string, int>();

            foreach (string meshName in distinctMeshNames)
            {
                meshNameCount.Add(meshName, 0);
            }

            List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]);
                grannyMeshInfos.Add(meshWrapper.getMeshInfo());
            }

            BiLookup <int, string> boneLookup = new BiLookup <int, string>();

            for (int i = 0; i < skeleton.Bones.Count; i++)
            {
                boneLookup.Add(i, skeleton.Bones[i].Name);
            }

            Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>();

            foreach (IGrannyBone bone in skeleton.Bones)
            {
                if (!boneNameToPositionMap.ContainsKey(bone.Name))
                {
                    double[] bonePosition = NB2Exporter.getBoneWorldPosition(bone);
                    boneNameToPositionMap.Add(bone.Name, bonePosition);
                }
            }

            string headerLine = "// CivNexus6 CN6 - Exported from Nexus Buddy " + NexusBuddyApplicationForm.getVersionString();

            outputWriter.WriteLine(headerLine);
            outputWriter.WriteLine("skeleton");

            // Write Bones
            for (int boneIndex = 0; boneIndex < skeleton.Bones.Count; boneIndex++)
            {
                IGrannyBone      bone              = skeleton.Bones[boneIndex];
                string           boneName          = bone.Name;
                IGrannyTransform transform         = bone.LocalTransform;
                float[]          orientation       = transform.Orientation;
                float[]          position          = transform.Position;
                float[]          invWorldTransform = bone.InverseWorldTransform;

                StringBuilder boneStringBuilder = new StringBuilder(boneIndex + " \"" + boneName + "\" " + bone.ParentIndex + " " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                                                    orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture));

                foreach (float j in invWorldTransform)
                {
                    boneStringBuilder.Append(" " + j.ToString(numberFormat, CultureInfo.InvariantCulture));
                }

                outputWriter.WriteLine(boneStringBuilder);
            }


            List <IndieMaterial> modelMaterials = new List <IndieMaterial>();

            foreach (IGrannyMesh mesh in model.MeshBindings)
            {
                IGrannyMaterial material = mesh.MaterialBindings[0];
                foreach (ListViewItem materialListItem in NexusBuddyApplicationForm.form.materialList.Items)
                {
                    IndieMaterial         shader   = (IndieMaterial)materialListItem.Tag;
                    GrannyMaterialWrapper matWrap1 = new GrannyMaterialWrapper(shader.GetMaterial());
                    GrannyMaterialWrapper matWrap2 = new GrannyMaterialWrapper(material);
                    if (matWrap1.getName().Equals(matWrap2.getName()) && !modelMaterials.Contains(shader))
                    {
                        modelMaterials.Add(shader);
                    }
                }
            }

            int meshCount = 0;

            for (int mi = 0; mi < grannyMeshInfos.Count; mi++)
            {
                IGrannyMesh       mesh        = model.MeshBindings[mi];
                string            meshName    = model.MeshBindings[mi].Name;
                GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh);
                GrannyMeshInfo    meshInfo    = meshWrapper.getMeshInfo();

                bool isFlatMesh = true;
                foreach (GrannyVertexInfo vertexInfo in meshInfo.vertices)
                {
                    float zPos   = vertexInfo.position[2];
                    bool  isZero = NumberUtils.almostEquals(zPos, 0.0f, 4);
                    if (!isZero)
                    {
                        isFlatMesh = false;
                        break;
                    }
                }

                if (filterMeshName == null)
                {
                    if (isFlatMesh)
                    {
                        decalMeshNames.Add(meshName);
                    }
                    else
                    {
                        meshCount++;
                    }
                }
                else
                {
                    meshCount = 1;
                }
            }

            if (meshCount == 0)
            {
                outputWriter.Close();
                File.Delete(outputFilename);
                return(new WriteModelToCN6Response(decalMeshNames, textureMaps));
            }

            // Write Meshes
            outputWriter.WriteLine("meshes:" + meshCount);

            for (int mi = 0; mi < grannyMeshInfos.Count; mi++)
            {
                GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi];
                string         meshName       = model.MeshBindings[mi].Name;

                if ((filterMeshName == null && !decalMeshNames.Contains(meshName)) || meshName.Equals(filterMeshName))
                {
                    meshNameCount[meshName]++;
                    if (meshNameCount[meshName] > 1)
                    {
                        meshName += meshNameCount[meshName];
                    }

                    outputWriter.WriteLine("mesh:\"" + meshName + "\"");

                    // Write Materials
                    outputWriter.WriteLine("materials");
                    foreach (IGrannyMaterial material in model.MeshBindings[mi].MaterialBindings)
                    {
                        IndieMaterial shader = NexusBuddyApplicationForm.GetIndieMaterialFromMaterial(material);

                        string baseMap;

                        if (shader.GetType() == typeof(IndieLeaderGlassShader))
                        {
                            baseMap = "Leader_cornea";
                        }
                        else if (shader.GetType() == typeof(IndieBuildingShader))
                        {
                            baseMap = shader.Diffuse;
                        }
                        else if (shader.GetType().Name.StartsWith("IndieLeaderFur"))
                        {
                            baseMap = shader.Fur_BaseMap;
                        }
                        else if (shader.GetType().Name.StartsWith("IndieLeader"))
                        {
                            baseMap = shader.DiffuseMap;
                        }
                        else if (shader.GetType() == typeof(IndieLandmarkStencilShader))
                        {
                            baseMap = shader.BaseTextureMap;
                        }
                        else
                        {
                            baseMap = shader.BaseTextureMap;
                        }

                        if (!String.IsNullOrEmpty(baseMap))
                        {
                            outputWriter.WriteLine("\"" + baseMap + "\"");
                            textureMaps.Add(baseMap);
                        }
                        else
                        {
                            outputWriter.WriteLine("\"" + material.Name + "\"");
                        }
                    }

                    // Write Vertices
                    outputWriter.WriteLine("vertices");
                    for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++)
                    {
                        GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi];

                        string[] boneNames   = new string[8];
                        float[]  boneWeights = new float[8];
                        int[]    boneIds     = new int[8];

                        for (int z = 0; z < 8; z++)
                        {
                            if (z > 3)
                            {
                                //boneNames[z] = grannyMeshInfo.boneBindings[vertex.boneIndices[z]];
                                boneWeights[z] = 0f;
                                boneIds[z]     = 0;
                            }
                            else
                            {
                                boneNames[z]   = grannyMeshInfo.boneBindings[vertex.boneIndices[z]];
                                boneWeights[z] = (float)vertex.boneWeights[z] / 255;
                                boneIds[z]     = NB2Exporter.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneNames[z], boneWeights[z], vertex.position);
                            }
                        }

                        float[] tangents = new float[3];
                        if (vertex.tangent == null)
                        {
                            tangents[0] = vertex.normal[0];
                            tangents[1] = vertex.normal[1];
                            tangents[2] = vertex.normal[2];
                        }
                        else
                        {
                            tangents[0] = vertex.tangent[0];
                            tangents[1] = vertex.tangent[1];
                            tangents[2] = vertex.tangent[2];
                        }

                        float[] binormals = new float[3];
                        if (vertex.binormal == null)
                        {
                            binormals[0] = vertex.normal[0];
                            binormals[1] = vertex.normal[1];
                            binormals[2] = vertex.normal[2];
                        }
                        else
                        {
                            binormals[0] = vertex.binormal[0];
                            binormals[1] = vertex.binormal[1];
                            binormals[2] = vertex.binormal[2];
                        }

                        outputWriter.WriteLine(vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               tangents[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               binormals[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                               boneIds[0] + " " + boneIds[1] + " " + boneIds[2] + " " + boneIds[3] + " 0 0 0 0 " +
                                               vertex.boneWeights[0] + " " + vertex.boneWeights[1] + " " + vertex.boneWeights[2] + " " + vertex.boneWeights[3] + " 0 0 0 0 "
                                               );
                    }

                    // Write Triangles
                    outputWriter.WriteLine("triangles");
                    for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++)
                    {
                        int[] triangle = grannyMeshInfo.triangles[ti];
                        outputWriter.WriteLine(triangle[0] + " " + triangle[1] + " " + triangle[2] + " 0");
                    }
                }
            }

            outputWriter.WriteLine("end");

            outputWriter.Close();

            WriteModelToCN6Response response = new WriteModelToCN6Response(decalMeshNames, textureMaps);

            return(response);
        }
Ejemplo n.º 14
0
        public static void exportNB2Model(IGrannyFile grannyFile, int modelId)
        {
            string fileExtension  = ".nb2";
            string outputFilename = "";
            string numberFormat   = "f6";

            if (grannyFile.Models.Count > 1)
            {
                string modelFilename = "__" + grannyFile.Models[modelId].Name + fileExtension;
                outputFilename = grannyFile.Filename.Replace(".gr2", modelFilename);
                outputFilename = outputFilename.Replace(".GR2", modelFilename);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".gr2", fileExtension);
                outputFilename = outputFilename.Replace(".GR2", fileExtension);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename.ToLower(), FileMode.Create));

            IGrannyModel    model    = grannyFile.Models[modelId];
            IGrannySkeleton skeleton = model.Skeleton;

            // Lookup so we can identify the meshes belonging the current model in the list of file meshes
            Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>();
            HashSet <string>      distinctMeshNames = new HashSet <string>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                for (int j = 0; j < grannyFile.Meshes.Count; j++)
                {
                    GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]);
                    IGrannyMesh       fileMesh  = grannyFile.Meshes[j];
                    if (modelMesh.meshEqual(fileMesh))
                    {
                        meshBindingToMesh.Add(i, j);
                    }
                }
                distinctMeshNames.Add(model.MeshBindings[i].Name);
            }

            // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2
            Dictionary <string, int> meshNameCount = new Dictionary <string, int>();

            foreach (string meshName in distinctMeshNames)
            {
                meshNameCount.Add(meshName, 0);
            }

            List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]);
                grannyMeshInfos.Add(meshWrapper.getMeshInfo());
            }

            BiLookup <int, string> boneLookup = new BiLookup <int, string>();

            for (int i = 0; i < skeleton.Bones.Count; i++)
            {
                boneLookup.Add(i, skeleton.Bones[i].Name);
            }

            Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>();

            double[] bonePosition;
            foreach (IGrannyBone bone in skeleton.Bones)
            {
                try {
                    bonePosition = getBoneWorldPosition(bone);
                    boneNameToPositionMap.Add(bone.Name, bonePosition);
                } catch (ArgumentException)
                {
                }
            }

            outputWriter.WriteLine("// Nexus Buddy NB2 - Exported from Nexus Buddy 2");
            outputWriter.WriteLine("Frames: 30");
            outputWriter.WriteLine("Frame: 1");

            List <IndieMaterial> modelMaterials = new List <IndieMaterial>();

            foreach (IGrannyMesh mesh in model.MeshBindings)
            {
                IGrannyMaterial material = mesh.MaterialBindings[0];
                foreach (ListViewItem materialListItem in NexusBuddyApplicationForm.form.materialList.Items)
                {
                    IndieMaterial         shader   = (IndieMaterial)materialListItem.Tag;
                    GrannyMaterialWrapper matWrap1 = new GrannyMaterialWrapper(shader.GetMaterial());
                    GrannyMaterialWrapper matWrap2 = new GrannyMaterialWrapper(material);
                    if (matWrap1.getName().Equals(matWrap2.getName()) && !modelMaterials.Contains(shader))
                    {
                        modelMaterials.Add(shader);
                    }
                }
            }

            // Write Meshes
            outputWriter.WriteLine("Meshes: " + model.MeshBindings.Count);
            for (int mi = 0; mi < grannyMeshInfos.Count; mi++)
            {
                GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi];
                string         meshName       = model.MeshBindings[mi].Name;

                meshNameCount[meshName]++;
                if (meshNameCount[meshName] > 1)
                {
                    meshName += meshNameCount[meshName];
                }

                var materialBindingName = model.MeshBindings[mi].MaterialBindings[0].Name;
                var materialIndex       = 0;
                foreach (IndieMaterial material in modelMaterials)
                {
                    if (materialBindingName.Equals(material.GetMaterial().Name))
                    {
                        break;
                    }
                    materialIndex++;
                }

                outputWriter.WriteLine("\"" + meshName + "\" 0 " + materialIndex);

                // Write Vertices
                outputWriter.WriteLine(grannyMeshInfo.vertices.Count);
                for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++)
                {
                    GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi];

                    string boneName0   = grannyMeshInfo.boneBindings[vertex.boneIndices[0]];
                    float  boneWeight0 = (float)vertex.boneWeights[0] / 255;
                    int    boneId0     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName0, boneWeight0, vertex.position);

                    string boneName1   = grannyMeshInfo.boneBindings[vertex.boneIndices[1]];
                    float  boneWeight1 = (float)vertex.boneWeights[1] / 255;
                    int    boneId1     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName1, boneWeight1, vertex.position);

                    string boneName2   = grannyMeshInfo.boneBindings[vertex.boneIndices[2]];
                    float  boneWeight2 = (float)vertex.boneWeights[2] / 255;
                    int    boneId2     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName2, boneWeight2, vertex.position);

                    string boneName3   = grannyMeshInfo.boneBindings[vertex.boneIndices[3]];
                    float  boneWeight3 = (float)vertex.boneWeights[3] / 255;
                    int    boneId3     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName3, boneWeight3, vertex.position);


                    outputWriter.WriteLine("0 " + vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                           vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId0 + " " + boneWeight0.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId1 + " " + boneWeight1.ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId2 + " " + boneWeight2.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId3 + " " + boneWeight3.ToString(numberFormat, CultureInfo.InvariantCulture)
                                           );
                }

                // Write Normals
                outputWriter.WriteLine(grannyMeshInfo.vertices.Count);
                for (int ni = 0; ni < grannyMeshInfo.vertices.Count; ni++)
                {
                    GrannyVertexInfo vertex = grannyMeshInfo.vertices[ni];

                    outputWriter.WriteLine(vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture));
                }

                // Write Triangles
                outputWriter.WriteLine(grannyMeshInfo.triangles.Count);
                for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++)
                {
                    int[] triangle = grannyMeshInfo.triangles[ti];
                    outputWriter.WriteLine("0 " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " 1");
                }
            }

            // Write Materials
            outputWriter.WriteLine("Materials: " + modelMaterials.Count);
            for (int i = 0; i < modelMaterials.Count; i++)
            {
                outputWriter.WriteLine("\"" + modelMaterials[i].GetMaterial().Name + "\"");
                outputWriter.WriteLine("0.200000 0.200000 0.200000 1.000000");
                outputWriter.WriteLine("0.800000 0.800000 0.800000 1.000000");
                outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000");
                outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000");
                outputWriter.WriteLine("0.000000");
                outputWriter.WriteLine("1.000000");
                string        map1 = "ColorMap_" + i;
                string        map2 = "AlphaMap_" + i;
                string        baseMap;
                string        srefmap;
                IndieMaterial shader = modelMaterials[i];
                if (shader.GetType() == typeof(IndieBuildingShader))
                {
                    baseMap = shader.Diffuse;
                    srefmap = shader.BuildingSREF;
                }
                else if (shader.GetType() == typeof(IndieLandmarkStencilShader))
                {
                    baseMap = shader.BaseTextureMap;
                    srefmap = shader.SpecTextureMap;
                }
                else
                {
                    baseMap = shader.BaseTextureMap;
                    srefmap = shader.SREFMap;
                }

                if (!String.IsNullOrEmpty(baseMap))
                {
                    map1 = baseMap;
                }

                if (!String.IsNullOrEmpty(srefmap))
                {
                    map2 = srefmap;
                }
                outputWriter.WriteLine("\"" + map1 + "\"");
                outputWriter.WriteLine("\"" + map2 + "\"");
            }

            // Write Bones
            outputWriter.WriteLine("Bones: " + skeleton.Bones.Count);
            for (int bi = 0; bi < skeleton.Bones.Count; bi++)
            {
                IGrannyBone bone     = skeleton.Bones[bi];
                string      boneName = bone.Name;
                outputWriter.WriteLine("\"" + boneName + "\"");

                if (bone.ParentIndex == -1)
                {
                    outputWriter.WriteLine("\"\"");
                }
                else
                {
                    string parentBoneName = skeleton.Bones[bone.ParentIndex].Name;
                    outputWriter.WriteLine("\"" + parentBoneName + "\"");
                }

                IGrannyTransform transform   = bone.LocalTransform;
                float[]          orientation = transform.Orientation;
                float[]          position    = transform.Position;

                //Matrix3D boneWorldMatrix = getBoneWorldMatrix(bone);

                //ETransformFlags transformFlags = transform.Flags;
                //bool hasPosition = transformFlags.HasFlag(ETransformFlags.GrannyHasPosition);
                //bool hasOrientation = transformFlags.HasFlag(ETransformFlags.GrannyHasOrientation);

                // bone: flags, posx, posy, posz, quatx, quaty, quatz, quatw

                outputWriter.WriteLine("0 " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                       orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture));

                // number of position keys
                outputWriter.WriteLine("0");
                // number of rotation keys
                outputWriter.WriteLine("0");
            }

            outputWriter.Close();
        }
Ejemplo n.º 15
0
        public static void exportNB2Model(IGrannyFile grannyFile, int modelId)
        {
            string fileExtension  = ".nb2";
            string outputFilename = "";
            string numberFormat   = "f6";

            if (grannyFile.Models.Count > 1)
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", "_model" + modelId + fileExtension);
                outputFilename = outputFilename.Replace(".FGX", "_model" + modelId + fileExtension);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", fileExtension);
                outputFilename = outputFilename.Replace(".FGX", fileExtension);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create));

            IGrannyModel          model           = grannyFile.Models[modelId];
            IGrannySkeleton       skeleton        = model.Skeleton;
            GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(skeleton);

            skeletonWrapper.readSkeletonInfo();

            // Lookup so we can identify the meshes belonging the current model in the list of file meshes
            Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>();
            HashSet <string>      distinctMeshNames = new HashSet <string>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                for (int j = 0; j < grannyFile.Meshes.Count; j++)
                {
                    GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]);
                    IGrannyMesh       fileMesh  = grannyFile.Meshes[j];
                    if (modelMesh.meshEqual(fileMesh))
                    {
                        meshBindingToMesh.Add(i, j);
                    }
                }
                distinctMeshNames.Add(model.MeshBindings[i].Name);
            }

            // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2
            Dictionary <string, int> meshNameCount = new Dictionary <string, int>();

            foreach (string meshName in distinctMeshNames)
            {
                meshNameCount.Add(meshName, 0);
            }

            List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>();

            for (int i = 0; i < model.MeshBindings.Count; i++)
            {
                GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]);
                grannyMeshInfos.Add(meshWrapper.getMeshInfo());
            }

            BiLookup <int, string> boneLookup = new BiLookup <int, string>();

            for (int i = 0; i < skeleton.Bones.Count; i++)
            {
                boneLookup.Add(i, skeleton.Bones[i].Name);
            }

            Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>();

            foreach (IGrannyBone bone in skeleton.Bones)
            {
                double[] bonePosition = getBoneWorldPosition(bone);
                boneNameToPositionMap.Add(bone.Name, bonePosition);
            }

            outputWriter.WriteLine("// Nexus Buddy NB2 - Exported from Nexus Buddy 2");
            outputWriter.WriteLine("Frames: 30");
            outputWriter.WriteLine("Frame: 1");

            // Write Meshes
            outputWriter.WriteLine("Meshes: " + model.MeshBindings.Count);
            for (int mi = 0; mi < grannyMeshInfos.Count; mi++)
            {
                GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi];
                string         meshName       = model.MeshBindings[mi].Name;

                meshNameCount[meshName]++;
                if (meshNameCount[meshName] > 1)
                {
                    meshName += meshNameCount[meshName];
                }
                outputWriter.WriteLine("\"" + meshName + "\" 0 0");

                // Write Vertices
                outputWriter.WriteLine(grannyMeshInfo.vertices.Count);
                for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++)
                {
                    GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi];

                    string boneName0   = grannyMeshInfo.boneBindings[vertex.boneIndices[0]];
                    float  boneWeight0 = (float)vertex.boneWeights[0] / 255;
                    int    boneId0     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName0, boneWeight0, vertex.position);

                    string boneName1   = grannyMeshInfo.boneBindings[vertex.boneIndices[1]];
                    float  boneWeight1 = (float)vertex.boneWeights[1] / 255;
                    int    boneId1     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName1, boneWeight1, vertex.position);

                    string boneName2   = grannyMeshInfo.boneBindings[vertex.boneIndices[2]];
                    float  boneWeight2 = (float)vertex.boneWeights[2] / 255;
                    int    boneId2     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName2, boneWeight2, vertex.position);

                    string boneName3   = grannyMeshInfo.boneBindings[vertex.boneIndices[3]];
                    float  boneWeight3 = (float)vertex.boneWeights[3] / 255;
                    int    boneId3     = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName3, boneWeight3, vertex.position);


                    outputWriter.WriteLine("0 " + vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                           vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId0 + " " + boneWeight0.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId1 + " " + boneWeight1.ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId2 + " " + boneWeight2.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId3 + " " + boneWeight3.ToString(numberFormat, CultureInfo.InvariantCulture)
                                           );
                }

                // Write Normals
                outputWriter.WriteLine(grannyMeshInfo.vertices.Count);
                for (int ni = 0; ni < grannyMeshInfo.vertices.Count; ni++)
                {
                    GrannyVertexInfo vertex = grannyMeshInfo.vertices[ni];

                    outputWriter.WriteLine(vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture));
                }

                // Write Triangles
                outputWriter.WriteLine(grannyMeshInfo.triangles.Count);
                for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++)
                {
                    int[] triangle = grannyMeshInfo.triangles[ti];
                    outputWriter.WriteLine("0 " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " 1");
                }
            }

            // Write Material
            outputWriter.WriteLine("Materials: 1");
            outputWriter.WriteLine("\"Material_0\"");
            outputWriter.WriteLine("0.200000 0.200000 0.200000 1.000000");
            outputWriter.WriteLine("0.800000 0.800000 0.800000 1.000000");
            outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000");
            outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000");
            outputWriter.WriteLine("0.000000");
            outputWriter.WriteLine("1.000000");
            outputWriter.WriteLine("\"Material_0\"");
            outputWriter.WriteLine("\"\"");

            // Write Bones
            outputWriter.WriteLine("Bones: " + skeleton.Bones.Count);
            for (int bi = 0; bi < skeleton.Bones.Count; bi++)
            {
                IGrannyBone bone     = skeleton.Bones[bi];
                string      boneName = bone.Name;
                outputWriter.WriteLine("\"" + boneName + "\"");

                if (bone.ParentIndex == -1)
                {
                    outputWriter.WriteLine("\"\"");
                }
                else
                {
                    string parentBoneName = skeleton.Bones[bone.ParentIndex].Name;
                    outputWriter.WriteLine("\"" + parentBoneName + "\"");
                }

                IGrannyTransform transform   = bone.LocalTransform;
                float[]          orientation = transform.Orientation;
                float[]          position    = transform.Position;

                outputWriter.WriteLine("0 " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " +
                                       orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture));

                // number of position keys
                outputWriter.WriteLine("0");
                // number of rotation keys
                outputWriter.WriteLine("0");
            }

            outputWriter.Close();
        }